From: batt Date: Fri, 4 Apr 2008 13:42:05 +0000 (+0000) Subject: Refactor BeRTOS to be in his own directory. X-Git-Tag: 1.0.0~39 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=791e167e053bdd9250d34a9a5ccae6ccde4d6679;p=bertos.git Refactor BeRTOS to be in his own directory. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1213 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/Makefile b/Makefile index 43b9ec7b..c899766b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ V := 0 default: all -include config.mk +include bertos/config.mk #Include subtargets include app/demo/demo.mk @@ -19,4 +19,4 @@ include app/demo/demo.mk #include app/battfs/battfs_test.mk #include app/triface/triface.mk -include rules.mk +include bertos/rules.mk diff --git a/algo/crc.c b/algo/crc.c deleted file mode 100644 index d465e260..00000000 --- a/algo/crc.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * \file - * - * - * \brief CRC table and support routines - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "crc.h" - -/** - * crctab calculated by Mark G. Mendel, Network Systems Corporation - */ -const uint16_t crc16tab[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -uint16_t crc16(uint16_t crc, const void *buffer, size_t len) -{ - const unsigned char *buf = (const unsigned char *)buffer; - while(len--) - crc = UPDCRC16(*buf++, crc); - - return crc; -} - diff --git a/algo/crc.h b/algo/crc.h deleted file mode 100644 index d6a1f45d..00000000 --- a/algo/crc.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * \file - * - * - * \brief XModem-CRC16 algorithm (interface) - * - * \note This algorithm is incompatible with the CCITT-CRC16. - * - * This code is based on the article Copyright 1986 Stephen Satchell. - * - * Programmers may incorporate any or all code into their programs, - * giving proper credit within the source. Publication of the - * source routines is permitted so long as proper credit is given - * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, - * Omen Technology. - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#ifndef ALGO_CRC_H -#define ALGO_CRC_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -/* CRC table */ -extern const uint16_t crc16tab[256]; - - -/** - * \brief Compute the updated CRC16 value for one octet (macro version) - * - * \note This version is only intended for old/broken compilers. - * Use the inline function in new code. - * - * \param c New octet (range 0-255) - * \param oldcrc Previous CRC16 value (referenced twice, beware of side effects) - */ -#define UPDCRC16(c, oldcrc) (crc16tab[((oldcrc) >> 8) ^ ((unsigned char)(c))] ^ ((oldcrc) << 8)) - - -#ifdef INLINE -/** - * \brief Compute the updated CRC16 value for one octet (macro version) - */ -INLINE uint16_t updcrc16(uint8_t c, uint16_t oldcrc) -{ - return crc16tab[(oldcrc >> 8) ^ c] ^ (oldcrc << 8); -} -#endif // INLINE - - -/** - * This function implements the CRC 16 calculation on a buffer. - * - * \param crc Current CRC16 value. - * \param buf The buffer to perform CRC calculation on. - * \param len The length of the Buffer. - * - * \return The updated CRC16 value. - */ -extern uint16_t crc16(uint16_t crc, const void *buf, size_t len); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ALGO_CRC_H */ diff --git a/algo/md2.c b/algo/md2.c deleted file mode 100644 index 53b44865..00000000 --- a/algo/md2.c +++ /dev/null @@ -1,377 +0,0 @@ -/** - * \file - * - * - * \brief MD2 Message-Digest algorithm. - * - * The MD2 algorithm work with a constant array of 256 permutationt - * defined in RFC1319. If you don't want to use a standard array of - * permutatione you can use a md2_perm() function that generate an - * array of 256 "casual" permutation. To swich from a standard array - * to md2_perm function you must chanche CONFIG_MD2_STD_PERM defined in - * appconfig.h. - * If you need to store array in program memory you must define - * a macro _PROGMEM (for more info see mware/pgm.h). - * - * - * \version $Id$ - * \author Daniele Basile - */ - -/*#* - *#* $Log$ - *#* Revision 1.17 2007/06/07 16:06:39 batt - *#* Fix some doxygen errors. - *#* - *#* Revision 1.16 2007/02/15 13:29:49 asterix - *#* Add MD2_DIGEST_LEN macro. - *#* - *#* Revision 1.15 2007/02/06 15:53:34 asterix - *#* Add ROTR macro in m2d_perm, add comments, typos. - *#* - *#* Revision 1.13 2007/02/05 18:44:42 asterix - *#* Add md2_perm function. - *#* - *#* Revision 1.12 2007/02/05 16:52:44 asterix - *#* Add define for harvard architecture. - *#* - *#* Revision 1.11 2007/02/02 18:15:31 asterix - *#* Add function MD2_test. Fix bug in md2_update function. - *#* - *#* Revision 1.9 2007/02/02 13:10:01 asterix - *#* Fix some bugs in md2_pad and md2_update fuction. - *#* - *#* Revision 1.8 2007/02/01 14:45:56 asterix - *#* Rewrite md2_update function and fix some bug. - *#* - *#* Revision 1.7 2007/01/31 18:04:15 asterix - *#* Write md2_end function - *#* - *#* Revision 1.4 2007/01/31 13:51:57 asterix - *#* Write md2_compute function. - *#* - *#* Revision 1.2 2007/01/30 17:31:44 asterix - *#* Add function prototypes. - *#* - *#* Revision 1.1 2007/01/30 15:53:26 batt - *#* Add first md2 skel. - *#* - *#*/ - -#include "md2.h" - -#include //memset(), memcpy(); -#include -#include //ASSERT() -#include //MIN(), countof(), ROTR(); -#include - - -#if CONFIG_MD2_STD_PERM - /* - * Official array of 256 byte pemutation contructed from digits of pi, defined - * in the RFC 1319. - */ - static const uint8_t PGM_ATTR md2_perm[256] = - { - 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, - 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, - 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, - 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, - 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, - 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, - 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, - 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, - 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, - 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, - 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, - 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, - 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, - 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, - 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, - 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, - 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, - 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 - }; - - #define MD2_PERM(x) PGM_READ_CHAR(&md2_perm[x]) -#else - /** - * Md2_perm() function generate an array of 256 "casual" permutation. - */ - - /** - * Costant define for computing an array of 256 "casual" permutation. - * \{ - */ - #define K1 5 - #define K2 3 - #define R 2 - #define X 172 - /*\}*/ - - static uint8_t md2_perm(uint8_t i) - { - - i = i * K1; - i = ROTR(i, R); - i ^= X; - i = i * K2; - - return i; - } - - #define MD2_PERM(x) md2_perm(x) - -#endif - - -/** - * Pad function. Put len_pad unsigned char in - * input block. - */ -static void md2_pad(void *_block, size_t len_pad) -{ - uint8_t *block; - - block = (uint8_t *)_block; - - ASSERT(len_pad <= CONFIG_MD2_BLOCK_LEN); - - /* - * Fill input block with len_pad char. - */ - memset(block, len_pad, len_pad); - -} - -static void md2_compute(void *_state, void *_checksum, void *_block) -{ - int i = 0; - uint16_t t = 0; - uint8_t compute_array[COMPUTE_ARRAY_LEN]; - uint8_t *state; - uint8_t *checksum; - uint8_t *block; - - state = (uint8_t *)_state; - checksum = (uint8_t *)_checksum; - block = (uint8_t *)_block; - - /* - * Copy state and checksum context in compute array. - */ - memcpy(compute_array, state, CONFIG_MD2_BLOCK_LEN); - memcpy(compute_array + CONFIG_MD2_BLOCK_LEN, block, CONFIG_MD2_BLOCK_LEN); - - /* - * Fill compute array with state XOR block - */ - for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++) - compute_array[i + (CONFIG_MD2_BLOCK_LEN * 2)] = state[i] ^ block[i]; - - /* - * Encryt block. - */ - for(i = 0; i < NUM_COMPUTE_ROUNDS; i++) - { - for(int j = 0; j < COMPUTE_ARRAY_LEN; j++) - { - compute_array[j] ^= MD2_PERM(t); - t = compute_array[j]; - } - - t = (t + i) & 0xff; //modulo 256. - } - /* - * Update checksum. - */ - t = checksum[CONFIG_MD2_BLOCK_LEN - 1]; - - for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++) - { - checksum[i] ^= MD2_PERM(block[i] ^ t); - t = checksum[i]; - } - - /* - * Update state and clean compute array. - */ - memcpy(state, compute_array, CONFIG_MD2_BLOCK_LEN); - memset(compute_array, 0, sizeof(compute_array)); -} - -/** - * Algorithm initialization. - * - * \param context empty context. - */ -void md2_init(Md2Context *context) -{ - - memset(context, 0, sizeof(Md2Context)); - -} - -/** - * Update block. - */ -void md2_update(Md2Context *context, const void *_block_in, size_t block_len) -{ - - const uint8_t *block_in; - size_t cpy_len; - - - block_in = (const uint8_t *)_block_in; - - while(block_len > 0) - { - /* - * Choose a number of block that fill input context buffer. - */ - cpy_len = MIN(block_len, CONFIG_MD2_BLOCK_LEN - context->counter); - - - /* - * Copy in the buffer input block. - */ - memcpy(&context->buffer[context->counter], block_in, cpy_len); - - /* - * Update a context counter, input block length and remaning - * context buffer block lenght. - */ - context->counter += cpy_len; - block_len -= cpy_len; - block_in += cpy_len; - - /* - * If buffer is full, compute it. - */ - if (context->counter >= CONFIG_MD2_BLOCK_LEN) - { - md2_compute(context->state, context->checksum, context->buffer); - context->counter = 0; - } - } - - -} -/** - * Ends an MD2 message digest operation. - * This fuction take an context and return a pointer - * to context state. - * - * \param context in input. - * \return a pointer to context state (message digest). - */ -uint8_t *md2_end(Md2Context *context) -{ - - uint8_t buf[CONFIG_MD2_BLOCK_LEN]; - - /* - * Fill remaning empty context buffer. - */ - md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter); - - /* - * Update context buffer and compute it. - */ - md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter); - - /* - * Add context checksum to message input. - */ - md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN); - - - return context->state; //return a pointer to message digest. -} -/** - * MD2 test fuction. - * This function test MD2 algorithm with a standard string specified - * in RFC 1319. - * - * \note This test work with official array of 256 byte pemutation - * contructed from digits of pi, defined in the RFC 1319. - * - */ -bool md2_test(void) -{ - - Md2Context context; - - const char *test[] = - { - "", - "message digest", - "abcdefghijklmnopqrstuvwxyz", - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" - }; - - - const uint8_t *result[] = { - "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73", - "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0", - "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b", - "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8", - }; - - - for (int i = 0; i < countof(test); i++) - { - md2_init(&context); - md2_update(&context, test[i], strlen(test[i])); - - if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN)) - return false; - } - - return true; -} - -#if 0 - -#include -int main(int argc, char * argv[]) -{ - - if(md2_test()) - printf("MD2 algorithm work well!\n"); - else - printf("MD2 algorithm doesn't work well.\n"); - -} - -#endif - diff --git a/algo/md2.h b/algo/md2.h deleted file mode 100644 index 8d0edb79..00000000 --- a/algo/md2.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * \file - * - * - * \brief MD2 Message-Digest algorithm. - * - * The algorithm takes as input a message of arbitrary length and produces - * as output a 128-bit message digest of the input. - * It is conjectured that it is computationally infeasible to produce - * two messages having the same message digest, or to produce any - * message having a given prespecified target message digest. - * - * - * - * \version $Id$ - * \author Daniele Basile - */ - -#ifndef ALGO_MD2_H -#define ALGO_MD2_H - -#include -#include - -#define NUM_COMPUTE_ROUNDS 18 ///< Number of compute rounds. -#define COMPUTE_ARRAY_LEN CONFIG_MD2_BLOCK_LEN * 3 ///< Lenght of compute array. -#define MD2_DIGEST_LEN CONFIG_MD2_BLOCK_LEN -/** - * Context for MD2 computation. - */ -typedef struct Md2Context -{ - uint8_t buffer[CONFIG_MD2_BLOCK_LEN]; ///< Input buffer. - uint8_t state[CONFIG_MD2_BLOCK_LEN]; ///< Current state buffer. - uint8_t checksum[CONFIG_MD2_BLOCK_LEN]; ///< Checksum. - size_t counter; ///< Counter of remaining bytes. - -} Md2Context; - -void md2_init(Md2Context *context); -void md2_update(Md2Context *context, const void *block_in, size_t block_len); -uint8_t *md2_end(Md2Context *context); -bool md2_test(void); - -#endif /* ALGO_MD2_H */ diff --git a/algo/ramp.c b/algo/ramp.c deleted file mode 100644 index 9a2cc92e..00000000 --- a/algo/ramp.c +++ /dev/null @@ -1,206 +0,0 @@ -/*! - * \file - * - * - * \brief Compute, save and load ramps for stepper motors (implementation) - * - * \version $Id$ - * - * \author Simone Zinanni - * \author Bernardo Innocenti - * \author Giovanni Bajo - * \author Daniele Basile - * - * - * The formula used by the ramp is the following: - * - *
- *            a * b
- * f(t) = -------------
- *         lerp(a,b,t)
- * 
- * - * Where a and b are the maximum and minimum speed - * respectively (minimum and maximum wavelength respectively), and lerp - * is a linear interpolation with a factor: - * - *
- * lerp(a,b,t) =  a + t * (b - a)  =  (a * (1 - t)) + (b * t)
- * 
- * - * t must be in the [0,1] interval. It is easy to see that the - * following holds true: - * - *
- * f(0) = b,   f(1) = a
- * 
- * - * And that the function is monotonic. So, the function effectively interpolates - * between the maximum and minimum speed through its domain ([0,1] -> [b,a]). - * - * The curve drawn by this function is similar to 1 / (sqrt(n)), so it is slower - * than a linear acceleration (which would be 1/n). - * - * The floating point version uses a slightly modified function which accepts - * the parameter in the domain [0, MT] (where MT is maxTime, the length of the - * ramp, which is a setup parameter for the ramp). This is done to reduce the - * number of operations per step. The formula looks like this: - * - *
- *               a * b * MT
- * g(t) = ----------------------------
- *           (a * MT) + t * (b - a)
- * 
- * - * It can be shown that this g(t) = f(t * MT). The denominator - * is a linear interpolation in the range [b*MT, a*MT], as t moves in the - * interval [0, MT]. So the interpolation interval of the function is again - * [b, a]. The implementation caches the value of the numerator and parts - * of the denominator, so that the formula becomes: - * - *
- * alpha = a * b * MT
- * beta = a * MT
- * gamma = b - a
- *
- *                alpha
- * g(t) = ----------------------
- *           beta + t * gamma
- * 
- * - * and t is exactly the parameter that ramp_evaluate() gets, - * that is the current time (in range [0, MT]). The operations performed - * for each step are just an addition, a multiplication and a division. - * - * The fixed point version of the formula instead transforms the original - * function as follows: - * - *
- *                   a * b                         a
- *  f(t) =  -------------------------  =  --------------------
- *                 a                         a
- *           b * ( - * (1 - t) + t )         - * (1 - t) + t
- *                 b                         b
- * 
- * - * t must be computed by dividing the current time (24 bit integer) - * by the maximum time (24 bit integer). This is done by precomputing the - * reciprocal of the maximum time as a 0.32 fixed point number, and multiplying - * it to the current time. Multiplication is performed 8-bits a time by - * FIX_MULT32(), so that we end up with a 0.16 fixed point number for - * t (and 1-t is just its twos-complement negation). - * a/b is in the range [0,1] (because a is always less than b, - * being the minimum wavelength), so it is precomputed as a 0.16 fixed point. - * The final step is then computing the denominator and executing the division - * (32 cycles using the 1-step division instruction in the DSP). - * - * The assembly implementation is needed for efficiency, but a C version of it - * can be easily written, in case it is needed in the future. - * - */ - -#include "ramp.h" -#include - -#include // memcpy() - -/** - * Multiply \p a and \p b two integer at 32 bit and extract the high 16 bit word. - */ -#define FIX_MULT32(a,b) (((uint64_t)(a)*(uint32_t)(b)) >> 16) - -void ramp_compute(struct Ramp *ramp, uint32_t clocksRamp, uint16_t clocksMinWL, uint16_t clocksMaxWL) -{ - ASSERT(clocksMaxWL >= clocksMinWL); - - // Save values in ramp struct - ramp->clocksRamp = clocksRamp; - ramp->clocksMinWL = clocksMinWL; - ramp->clocksMaxWL = clocksMaxWL; - -#if RAMP_USE_FLOATING_POINT - ramp->precalc.gamma = ramp->clocksMaxWL - ramp->clocksMinWL; - ramp->precalc.beta = (float)ramp->clocksMinWL * (float)ramp->clocksRamp; - ramp->precalc.alpha = ramp->precalc.beta * (float)ramp->clocksMaxWL; - -#else - ramp->precalc.max_div_min = ((uint32_t)clocksMinWL << 16) / (uint32_t)clocksMaxWL; - - /* Calcola 1/total_time in fixed point .32. Assumiamo che la rampa possa al - * massimo avere 25 bit (cioé valore in tick fino a 2^25, che con il - * prescaler=3 sono circa 7 secondi). Inoltre, togliamo qualche bit di precisione - * da destra (secondo quanto specificato in RAMP_CLOCK_SHIFT_PRECISION). - */ - ASSERT(ramp->clocksRamp < (1UL << (24 + RAMP_CLOCK_SHIFT_PRECISION))); - ramp->precalc.inv_total_time = 0xFFFFFFFFUL / (ramp->clocksRamp >> RAMP_CLOCK_SHIFT_PRECISION); - ASSERT(ramp->precalc.inv_total_time < 0x1000000UL); - -#endif -} - - -void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq) -{ - uint32_t minWL, maxWL; - - minWL = TIME2CLOCKS(FREQ2MICROS(maxFreq)); - maxWL = TIME2CLOCKS(FREQ2MICROS(minFreq)); - - ASSERT2(minWL < 65536UL, "Maximum frequency too high"); - ASSERT2(maxWL < 65536UL, "Minimum frequency too high"); - ASSERT(maxFreq > minFreq); - - ramp_compute( - ramp, - TIME2CLOCKS(length), - TIME2CLOCKS(FREQ2MICROS(maxFreq)), - TIME2CLOCKS(FREQ2MICROS(minFreq)) - ); -} - -void ramp_default(struct Ramp *ramp) -{ - ramp_setup(ramp, RAMP_DEF_TIME, RAMP_DEF_MINFREQ, RAMP_DEF_MAXFREQ); -} - -#if RAMP_USE_FLOATING_POINT - -float ramp_evaluate(const struct Ramp* ramp, float curClock) -{ - return ramp->precalc.alpha / (curClock * ramp->precalc.gamma + ramp->precalc.beta); -} - -#else - -INLINE uint32_t fix_mult32(uint32_t m1, uint32_t m2) -{ - uint32_t accum = 0; - accum += m1 * ((m2 >> 0) & 0xFF); - accum >>= 8; - accum += m1 * ((m2 >> 8) & 0xFF); - accum >>= 8; - accum += m1 * ((m2 >> 16) & 0xFF); - return accum; -} - -// a*b >> 16 -INLINE uint16_t fix_mult16(uint16_t a, uint32_t b) -{ - return (b*(uint32_t)a) >> 16; -} - -uint16_t FAST_FUNC ramp_evaluate(const struct Ramp* ramp, uint32_t curClock) -{ - uint16_t t = FIX_MULT32(curClock >> RAMP_CLOCK_SHIFT_PRECISION, ramp->precalc.inv_total_time); - uint16_t denom = fix_mult16((uint16_t)~t + 1, ramp->precalc.max_div_min) + t; - uint16_t cur_delta = ((uint32_t)ramp->clocksMinWL << 16) / denom; - - return cur_delta; -} - -#endif - - diff --git a/algo/ramp.h b/algo/ramp.h deleted file mode 100644 index f438dc5e..00000000 --- a/algo/ramp.h +++ /dev/null @@ -1,199 +0,0 @@ - -/** - * \file - * - * - * \brief Compute, save and load ramps for stepper motors (interace) - * - * \version $Id$ - * - * \author Simone Zinanni - * \author Giovanni Bajo - * \author Daniele Basile - * - * The acceleration ramp is used to properly accelerate a stepper motor. The main - * entry point is the function ramp_evaluate(), which must be called at every step - * of the motor: it gets as input the time elapsed since the stepper started - * accelerating, and returns the time to wait before sending the next step. A pseudo - * usage pattern is as follows: - * - *
- *  float time = 0;
- *  while (1)
- *  {
- *      float delta = ramp_evaluate(&my_ramp, time);
- *      sleep(delta);
- *      do_motor_step();
- *      time += delta;
- *  }
- * 
- * - * A similar pattern can be used to decelerate (it is sufficient to move the total - * time backward, such as "time -= delta"). - * - * The ramp can be configured with ramp_setup(), providing it with the minimum and - * maximum operating frequency of the motor, and the total acceleration time in - * milliseconds (that is, the time that will be needed to accelerate from the - * minimum frequency to the maximum frequency). - * - * Both a very precise floating point and a very fast fixed point implementation - * of the ramp evaluation are provided. The fixed point is hand-optimized assembly - * for DSP56000 (but a portable C version of it can be easily written, see the - * comments in the code). - * - */ - -#ifndef ALGO_RAMP_H -#define ALGO_RAMP_H - -#include -#include "hw_stepper.h" - -/** - * Define whether the ramp will use floating point calculation within ramp_evaluate(). - * Otherwise, a less precise fixed point version will be used, which is faster on - * platforms which do no support floating point operations. - * - * \note Floating point operations will be always done within ramp_compute() to - * precalculate values, so there has to be at least a floating point emulation support. - */ -#define RAMP_USE_FLOATING_POINT 0 - - -#if !RAMP_USE_FLOATING_POINT - - /** - * Number of least-significant bits which are stripped away during ramp evaluation. - * This setting allows to specify larger ramps at the price of less precision. - * - * The maximum ramp size allowed is 2^(24 + RAMP_CLOCK_SHIFT_PRECISION), in clocks. - * For instance, using RAMP_CLOCK_SHIFT_PRECISION 1, and a 8x prescaler, the maximum - * length of a ramp is about 6.7 secs. Raising RAMP_CLOCK_SHIFT_PRECISION to 2 - * brings the maximum length to 13.4 secs, at the price of less precision. - * - * ramp_compute() will check that the length is below the maximum allowed through - * a runtime assertion. - * - * \note This macro is used only for the fixed-point version of the ramp. - */ - #define RAMP_CLOCK_SHIFT_PRECISION 2 -#endif - - -///< Negative pulse width for ramp -#define RAMP_PULSE_WIDTH 50 - -///< Default ramp -#define RAMP_DEF_TIME 6000000 ///< microsecs -#define RAMP_DEF_MAXFREQ 5000 ///< Hz -#define RAMP_DEF_MINFREQ 200 ///< Hz -#define RAMP_DEF_POWERRUN 10 ///< 10 deciampere (1 ampere) -#define RAMP_DEF_POWERIDLE 1 ///< 1 deciampere - - -/** - * Convert microseconds to timer clock ticks - */ -#define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000)) - -/** - * Convert timer clock ticks back to microseconds - */ -#define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000)) - -/** - * Convert microseconds to Hz - */ -#define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros))) - -/** - * Convert frequency (in Hz) to time (in microseconds) - */ -#define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz))) - - - -/** - * Structure holding pre-calculated data for speeding up real-time evaluation - * of the ramp. This structure is totally different between the fixed and the - * floating point version of the code. - * - * Consult the file-level documentation of ramp.c for more information about - * the values of this structure. - */ -struct RampPrecalc -{ -#if RAMP_USE_FLOATING_POINT - float beta; - float alpha; - float gamma; -#else - uint16_t max_div_min; - uint32_t inv_total_time; -#endif -}; - - -/** - * Ramp structure - */ -struct Ramp -{ - uint32_t clocksRamp; - uint16_t clocksMinWL; - uint16_t clocksMaxWL; - - struct RampPrecalc precalc; ///< pre-calculated values for speed -}; - - -/* - * Function prototypes - */ -void ramp_compute( - struct Ramp * ramp, - uint32_t clocksInRamp, - uint16_t clocksInMinWavelength, - uint16_t clocksInMaxWavelength); - - -/** Setup an acceleration ramp for a stepper motor - * - * \param ramp Ramp to fill - * \param length Length of the ramp (milliseconds) - * \param minFreq Minimum operating frequency of the motor (hertz) - * \param maxFreq Maximum operating frequency of the motor (hertz) - * - */ -void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq); - - -/** - * Initialize a new ramp with default values - */ -void ramp_default(struct Ramp *ramp); - - -/** - * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since - * the start of the acceleration, compute the next step, that is the interval at which - * send the signal to the motor. - * - * \note The fixed point version does not work when curClock is zero. Anyway, - * the first step is always clocksMaxWL, as stored within the ramp structure. - */ -#if RAMP_USE_FLOATING_POINT - float ramp_evaluate(const struct Ramp* ramp, float curClock); -#else - uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock); -#endif - - -/** Self test */ -void ramp_test(void); - -#endif /* ALGO_RAMP_H */ - diff --git a/algo/ramp_test.c b/algo/ramp_test.c deleted file mode 100644 index 92de9405..00000000 --- a/algo/ramp_test.c +++ /dev/null @@ -1,175 +0,0 @@ -/*! - * \file - * - * - * \brief Test for compute, save and load ramps for stepper motors (implementation) - * - * \version $Id$ - * - * \author Simone Zinanni - * \author Bernardo Innocenti - * \author Giovanni Bajo - * \author Daniele Basile - * - * - * The formula used by the ramp is the following: - * - *
- *            a * b
- * f(t) = -------------
- *         lerp(a,b,t)
- * 
- * - * Where a and b are the maximum and minimum speed - * respectively (minimum and maximum wavelength respectively), and lerp - * is a linear interpolation with a factor: - * - *
- * lerp(a,b,t) =  a + t * (b - a)  =  (a * (1 - t)) + (b * t)
- * 
- * - * t must be in the [0,1] interval. It is easy to see that the - * following holds true: - * - *
- * f(0) = b,   f(1) = a
- * 
- * - * And that the function is monotonic. So, the function effectively interpolates - * between the maximum and minimum speed through its domain ([0,1] -> [b,a]). - * - * The curve drawn by this function is similar to 1 / (sqrt(n)), so it is slower - * than a linear acceleration (which would be 1/n). - * - * The floating point version uses a slightly modified function which accepts - * the parameter in the domain [0, MT] (where MT is maxTime, the length of the - * ramp, which is a setup parameter for the ramp). This is done to reduce the - * number of operations per step. The formula looks like this: - * - *
- *               a * b * MT
- * g(t) = ----------------------------
- *           (a * MT) + t * (b - a)
- * 
- * - * It can be shown that this g(t) = f(t * MT). The denominator - * is a linear interpolation in the range [b*MT, a*MT], as t moves in the - * interval [0, MT]. So the interpolation interval of the function is again - * [b, a]. The implementation caches the value of the numerator and parts - * of the denominator, so that the formula becomes: - * - *
- * alpha = a * b * MT
- * beta = a * MT
- * gamma = b - a
- *
- *                alpha
- * g(t) = ----------------------
- *           beta + t * gamma
- * 
- * - * and t is exactly the parameter that ramp_evaluate() gets, - * that is the current time (in range [0, MT]). The operations performed - * for each step are just an addition, a multiplication and a division. - * - * The fixed point version of the formula instead transforms the original - * function as follows: - * - *
- *                   a * b                         a
- *  f(t) =  -------------------------  =  --------------------
- *                 a                         a
- *           b * ( - * (1 - t) + t )         - * (1 - t) + t
- *                 b                         b
- * 
- * - * t must be computed by dividing the current time (24 bit integer) - * by the maximum time (24 bit integer). This is done by precomputing the - * reciprocal of the maximum time as a 0.32 fixed point number, and multiplying - * it to the current time. Multiplication is performed 8-bits a time by - * FIX_MULT32(), so that we end up with a 0.16 fixed point number for - * t (and 1-t is just its twos-complement negation). - * a/b is in the range [0,1] (because a is always less than b, - * being the minimum wavelength), so it is precomputed as a 0.16 fixed point. - * The final step is then computing the denominator and executing the division - * (32 cycles using the 1-step division instruction in the DSP). - * - * The assembly implementation is needed for efficiency, but a C version of it - * can be easily written, in case it is needed in the future. - * - */ - -#include "ramp.h" -#include - -static bool ramp_test_single(uint32_t minFreq, uint32_t maxFreq, uint32_t length) -{ - struct Ramp r; - uint16_t cur, old; - uint32_t clock; - uint32_t oldclock; - - ramp_setup(&r, length, minFreq, maxFreq); - - cur = old = r.clocksMaxWL; - clock = 0; - oldclock = 0; - - kprintf("testing ramp: (length=%lu, min=%lu, max=%lu)\n", length, minFreq, maxFreq); - kprintf(" [length=%lu, max=%04x, min=%04x]\n", r.clocksRamp, r.clocksMaxWL, r.clocksMinWL); - - int i = 0; - int nonbyte = 0; - - while (clock + cur < r.clocksRamp) - { - oldclock = clock; - old = cur; - - clock += cur; - cur = ramp_evaluate(&r, clock); - - if (old < cur) - { - uint16_t t1 = FIX_MULT32(oldclock >> RAMP_CLOCK_SHIFT_PRECISION, r.precalc.inv_total_time); - uint16_t t2 = FIX_MULT32(clock >> RAMP_CLOCK_SHIFT_PRECISION, r.precalc.inv_total_time); - uint16_t denom1 = FIX_MULT32((uint16_t)((~t1) + 1), r.precalc.max_div_min) + t1; - uint16_t denom2 = FIX_MULT32((uint16_t)((~t2) + 1), r.precalc.max_div_min) + t2; - - kprintf(" Failed: %04x @ %lu --> %04x @ %lu\n", old, oldclock, cur, clock); - kprintf(" T: %04x -> %04x\n", t1, t2); - kprintf(" DENOM: %04x -> %04x\n", denom1, denom2); - - cur = ramp_evaluate(&r, clock); - return false; - } - i++; - if ((old-cur) >= 256) - nonbyte++; - } - - - - kprintf("Test finished: %04x @ %lu [min=%04x, totlen=%lu, numsteps:%d, nonbyte:%d]\n", cur, clock, r.clocksMinWL, r.clocksRamp, i, nonbyte); - - return true; -} - - -void ramp_test(void) -{ - bool ok = true; - - ok = ramp_test_single(200, 5000, 3000000) && ok; - ok = ramp_test_single(1000, 2000, 1000000) && ok; - - if (ok) - kputs("Ramp test succeeded!\n"); - else - kputs("Ramp test fail!\n"); -} - - diff --git a/algo/randpool.c b/algo/randpool.c deleted file mode 100644 index a32fdff4..00000000 --- a/algo/randpool.c +++ /dev/null @@ -1,298 +0,0 @@ -/** - * \file - * - * - * \brief API function for to manage entropy pool. - * - * \version $Id$ - * \author Daniele Basile - */ - -/*#* - *#* $Log$ - *#* Revision 1.20 2007/06/07 16:06:39 batt - *#* Fix some doxygen errors. - *#* - *#* Revision 1.19 2007/02/15 13:54:26 asterix - *#* Rename randpool_getN in randpool_get. Fix bug in randpool_get. - *#* - *#* Revision 1.17 2007/02/15 13:40:42 asterix - *#* Fix bug in randpool_add and randpool_strir. - *#* - *#* Revision 1.16 2007/02/13 15:11:37 asterix - *#* Typo. - *#* - *#* Revision 1.14 2007/02/13 09:57:12 asterix - *#* Add directive #if in struct EntropyPool, and remove #else in randpool_add. - *#* - *#* Revision 1.13 2007/02/12 18:25:34 asterix - *#* Fix bug in randpool_getN. - *#* - *#* Revision 1.12 2007/02/12 09:47:39 asterix - *#* Remove randpool_save. Add randpool_pool. - *#* - *#* Revision 1.10 2007/02/12 09:03:32 asterix - *#* Add CONFIG_RANDPOOL_TIMER macro to swich on or off timer support - *#* - *#* Revision 1.9 2007/02/09 17:58:09 asterix - *#* Add macro CONFIG_RANDPOOL_TIMER. - *#* - *#* Revision 1.6 2007/02/09 09:24:38 asterix - *#* Typos. Add data_len in randpool_add and n_byte in randpool_push pototypes. - *#* - *#* Revision 1.3 2007/02/08 14:25:29 asterix - *#* Write static funcion push_byte. - *#* - *#*/ - -#include "randpool.h" -#include "md2.h" - -#include //sprintf(); -#include //memset(), memcpy(); - -#include -#include //ASSERT() -#include //MIN(), ROUND_UP(); - -#if CONFIG_RANDPOOL_TIMER - #include //timer_clock(); -#endif - - - -/* - * Insert bytes in entropy pool, making a XOR of bytes present - * in entropy pool. - */ -static void randpool_push(EntropyPool *pool, void *_byte, size_t n_byte) -{ - size_t i = pool->pos_add; // Current number of byte insert in entropy pool. - uint8_t *byte; - - byte = (uint8_t *)_byte; - - /* - * Insert a bytes in entropy pool. - */ - for(int j = 0; j < n_byte; j++) - { - pool->pool_entropy[i] = pool->pool_entropy[i] ^ byte[j]; - i = (++i) % CONFIG_SIZE_ENTROPY_POOL; - } - - pool->pos_add = i; // Update a insert bytes. -} - - -/* - * This function stir entropy pool with MD2 function hash. - * - */ -static void randpool_stir(EntropyPool *pool) -{ - size_t entropy = pool->entropy; //Save current calue of entropy. - Md2Context context; - uint8_t tmp_buf[((sizeof(size_t) * 2) + sizeof(int)) * 2 + 1]; //Temporary buffer. - - md2_init(&context); //Init MD2 algorithm. - - randpool_add(pool, NULL, 0); - - for (int i = 0; i < (CONFIG_SIZE_ENTROPY_POOL / MD2_DIGEST_LEN); i++) - { - sprintf(tmp_buf, "%0x%0x%0x",pool->counter, i, pool->pos_add); - - /* - * Hash with MD2 algorithm the entropy pool. - */ - md2_update(&context, pool->pool_entropy, CONFIG_SIZE_ENTROPY_POOL); - - md2_update(&context, tmp_buf, sizeof(tmp_buf) - 1); - - /*Insert a message digest in entropy pool.*/ - randpool_push(pool, md2_end(&context), MD2_DIGEST_LEN); - - pool->counter = pool->counter + 1; - - } - - /*Insert in pool the difference between a two call of this function (see above).*/ - randpool_add(pool, NULL, 0); - - pool->entropy = entropy; //Restore old value of entropy. We haven't add entropy. -} - -/** - * Add \param entropy bits from \param data buffer to the entropy \param pool - */ -void randpool_add(EntropyPool *pool, void *data, size_t entropy) -{ - uint8_t sep[] = "\xaa\xaa\xaa\xaa"; // ?? - size_t data_len = ROUND_UP(entropy, 8) / 8; //Number of entropy byte in input. - - randpool_push(pool, data, data_len); //Insert data to entropy pool. - -#if CONFIG_RANDPOOL_TIMER - - ticks_t event = timer_clock(); - ticks_t delta; - - /*Difference of time between a two accese to entropy pool.*/ - delta = event - pool->last_counter; - - randpool_push(pool, &event, sizeof(ticks_t)); - randpool_push(pool, sep, sizeof(sep) - 1); // ?? - randpool_push(pool, &delta, sizeof(delta)); - - /* - * Count of number entropy bit add with delta. - */ - delta = delta & 0xff; - while(delta) - { - delta >>= 1; - entropy++; - } - - pool->last_counter = event; - -#endif - - pool->entropy += entropy; //Update a entropy of the pool. -} - -/** - * Randpool function initialization. - * The entropy pool can be initialize also with - * a previous entropy pool. - */ -void randpool_init(EntropyPool *pool, void *_data, size_t len) -{ - uint8_t *data; - - data = (uint8_t *)_data; - - memset(pool, 0, sizeof(EntropyPool)); - pool->pos_get = MD2_DIGEST_LEN; - -#if CONFIG_RANDPOOL_TIMER - pool->last_counter = timer_clock(); -#endif - - if(data) - { - /* - * Initialize a entropy pool with a - * previous pool, and assume all pool as - * entropy. - */ - len = MIN(len,(size_t)CONFIG_SIZE_ENTROPY_POOL); - memcpy(pool->pool_entropy, data, len); - pool->entropy = len; - } - -} - -/** - * Get the actual value of entropy. - */ -size_t randpool_size(EntropyPool *pool) -{ - return pool->entropy; -} - -/** - * Get \param n_byte from entropy pool. If n_byte is larger than number - * byte of entropy in entropy pool, randpool_get continue - * to generate pseudocasual value from previous state of - * pool. - * \param n_byte number fo bytes to read. - * \param pool is the pool entropy context. - * \param _data is the pointer to write the random data to. - */ -void randpool_get(EntropyPool *pool, void *_data, size_t n_byte) -{ - Md2Context context; - size_t i = pool->pos_get; - size_t n = n_byte; - size_t pos_write = 0; //Number of block has been written in data. - size_t len = MIN((size_t)MD2_DIGEST_LEN, n_byte); - uint8_t *data; - - data = (uint8_t *)_data; - - /* Test if i + CONFIG_MD2_BLOCK_LEN is inside of entropy pool.*/ - ASSERT((MD2_DIGEST_LEN + i) < CONFIG_SIZE_ENTROPY_POOL); - - md2_init(&context); - - while(n > 0) - { - - /*Hash previous state of pool*/ - md2_update(&context, &pool->pool_entropy[i], MD2_DIGEST_LEN); - - memcpy(&data[pos_write], md2_end(&context), len); - - pos_write += len; //Update number of block has been written in data. - n -= len; //Number of byte copied in data. - - len = MIN(n,(size_t)MD2_DIGEST_LEN); - - i = (i + MD2_DIGEST_LEN) % CONFIG_SIZE_ENTROPY_POOL; - - /* If we haven't more entropy pool to hash, we stir it.*/ - if(i < MD2_DIGEST_LEN) - { - randpool_stir(pool); - i = pool->pos_get; - } - - } - - pool->pos_get = i; //Current number of byte we get from pool. - pool->entropy -= n_byte; //Update a entropy. - - /*If we get all entropy entropy is 0*/ - if(pool->entropy < 0) - pool->entropy = 0; - -} - -/** - * Return a pointer to entropy pool. - */ -uint8_t *randpool_pool(EntropyPool *pool) -{ - return pool->pool_entropy; -} - diff --git a/algo/randpool.h b/algo/randpool.h deleted file mode 100644 index 317ebe74..00000000 --- a/algo/randpool.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * \file - * - * - * \brief API function for to manage entropy pool. - * - * - * \version $Id$ - * \author Daniele Basile - */ - -#ifndef ALGO_RANDPOOL_H -#define ALGO_RANDPOOL_H - -#include -#include - - -/** - * Sturct data of entropy pool. - */ -typedef struct EntropyPool -{ - size_t entropy; ///< Actual value of entropy (byte). - size_t pos_add; ///< Number of byte idd in entropy pool. - size_t pos_get; ///< Number of byte get in entropy pool. - size_t counter; ///< Counter. - -#if CONFIG_RANDPOOL_TIMER - size_t last_counter; ///< Last timer value. -#endif - - uint8_t pool_entropy[CONFIG_SIZE_ENTROPY_POOL]; ///< Entropy pool. - -} EntropyPool; - - -void randpool_add(EntropyPool *pool, void *data, size_t entropy); -void randpool_init(EntropyPool *pool, void *_data, size_t len); -size_t randpool_size(EntropyPool *pool); -void randpool_get(EntropyPool *pool, void *data, size_t n_byte); -uint8_t *randpool_pool(EntropyPool *pool); - -#endif /* ALGO_RANDPOOL_H */ diff --git a/algo/rotating_hash.h b/algo/rotating_hash.h deleted file mode 100644 index c154af1d..00000000 --- a/algo/rotating_hash.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \file - * - * - * \brief Rotating Hash algorithm (interface). - * - * This is a simple yet powerfull checksum algorithm. - * Instead of just xor-ing the data, rotating hash - * circular shift the checksum 4 place left before xoring. - * This is a bit more stronger than simply sum the data. - * - * \version $Id$ - * - * \author Francesco Sacchi - */ - - -#ifndef ALGO_ROTATING_H -#define ALGO_ROTATING_H - -#include - -typedef uint16_t rotating_t; - - -/** - * Init rotating checksum. - */ -INLINE void rotating_init(rotating_t *rot) -{ - *rot = 0; -} - -/** - * Update checksum pointed by \c rot with \c c data. - */ -INLINE void rotating_update1(uint8_t c, rotating_t *rot) -{ - *rot = (*rot << 4) ^ (*rot >> 12) ^ c; -} - -/** - * Update checksum pointed by \c rot with data supplied in \c buf. - */ -INLINE void rotating_update(const void *_buf, size_t len, rotating_t *rot) -{ - const uint8_t *buf = (const uint8_t *)_buf; - - while (len--) - rotating_update1(*buf++, rot); -} - - -#endif // ALGO_ROTATING_H diff --git a/algo/tea.c b/algo/tea.c deleted file mode 100644 index f67d4c5e..00000000 --- a/algo/tea.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * \file - * - * - * \brief TEA Tiny Encription Algorith functions (implementation). - * - * \version $Id$ - * \author Francesco Sacchi - * - * The Tiny Encryption Algorithm (TEA) by David Wheeler and Roger Needham - * of the Cambridge Computer Laboratory - * - * Placed in the Public Domain by David Wheeler and Roger Needham. - * - * **** ANSI C VERSION **** - * - * Notes: - * - * TEA is a Feistel cipher with XOR and and addition as the non-linear - * mixing functions. - * - * Takes 64 bits of data in v[0] and v[1]. Returns 64 bits of data in w[0] - * and w[1]. Takes 128 bits of key in k[0] - k[3]. - * - * TEA can be operated in any of the modes of DES. Cipher Block Chaining is, - * for example, simple to implement. - * - * n is the number of iterations. 32 is ample, 16 is sufficient, as few - * as eight may be OK. The algorithm achieves good dispersion after six - * iterations. The iteration count can be made variable if required. - * - * Note this is optimised for 32-bit CPUs with fast shift capabilities. It - * can very easily be ported to assembly language on most CPUs. - * - * delta is chosen to be the real part of (the golden ratio Sqrt(5/4) - - * 1/2 ~ 0.618034 multiplied by 2^32). - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2007/09/19 16:23:27 batt - *#* Fix doxygen warnings. - *#* - *#* Revision 1.1 2007/06/07 09:13:40 batt - *#* Add TEA enc/decryption algorithm. - *#* - *#* Revision 1.1 2007/01/10 17:30:10 batt - *#* Add cryptographic routines. - *#* - *#*/ - -#include "tea.h" -#include - -static uint32_t tea_func(uint32_t *in, uint32_t *sum, uint32_t *k) -{ - return ((*in << 4) + cpu_to_le32(k[0])) ^ (*in + *sum) ^ ((*in >> 5) + cpu_to_le32(k[1])); -} - -/** - * \brief TEA encryption function. - * This function encrypts v with k and returns the - * encrypted data in v. - * \param _v Array of two long values containing the data block. - * \param _k Array of four long values containing the key. - */ -void tea_enc(void *_v, void *_k) -{ - uint32_t y, z; - uint32_t sum = 0; - uint8_t n = ROUNDS; - uint32_t *v = (uint32_t *)_v; - uint32_t *k = (uint32_t *)_k; - - y=cpu_to_le32(v[0]); - z=cpu_to_le32(v[1]); - - while(n-- > 0) - { - sum += DELTA; - y += tea_func(&z, &sum, &(k[0])); - z += tea_func(&y, &sum, &(k[2])); - } - - v[0] = le32_to_cpu(y); - v[1] = le32_to_cpu(z); -} - -/** - * \brief TEA decryption function. - * This function decrypts v with k and returns the - * decrypted data in v. - * \param _v Array of two long values containing the data block. - * \param _k Array of four long values containing the key. - */ -void tea_dec(void *_v, void *_k) -{ - uint32_t y, z; - uint32_t sum = DELTA * ROUNDS; - uint8_t n = ROUNDS; - uint32_t *v = (uint32_t *)_v; - uint32_t *k = (uint32_t *)_k; - - y = cpu_to_le32(v[0]); - z = cpu_to_le32(v[1]); - - while(n-- > 0) - { - z -= tea_func(&y, &sum, &(k[2])); - y -= tea_func(&z, &sum, &(k[0])); - sum -= DELTA; - } - - v[0] = le32_to_cpu(y); - v[1] = le32_to_cpu(z); -} - diff --git a/algo/tea.h b/algo/tea.h deleted file mode 100644 index 97318012..00000000 --- a/algo/tea.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file - * - * - * \brief TEA Tiny Encription Algorith functions (interface). - * - * \version $Id$ - * \author Francesco Sacchi - * - * Documentation for TEA is available at - * http://www.cl.cam.ac.uk/ftp/users/djw3/tea.ps. - */ - -#ifndef ALGO_TEA_H -#define ALGO_TEA_H - -#include - -#define TEA_KEY_LEN 16 //!< TEA key size. -#define TEA_BLOCK_LEN 8 //!< TEA block length. - -#define DELTA 0x9E3779B9 //!< Magic value. (Golden number * 2^31) -#define ROUNDS 32 //!< Number of rounds. - -void tea_enc(void *_v, void *_k); -void tea_dec(void *_v, void *_k); - -#endif /* ALGO_TEA_H */ - diff --git a/app/demo/demo.mk b/app/demo/demo.mk index d8d1dbcf..7c264683 100644 --- a/app/demo/demo.mk +++ b/app/demo/demo.mk @@ -8,8 +8,8 @@ # Author: Bernardo Innocenti # -include fonts/fonts.mk -include emul/emul.mk +include bertos/fonts/fonts.mk +include bertos/emul/emul.mk # Set to 1 for debug builds demo_DEBUG = 1 @@ -21,65 +21,65 @@ TRG += demo CC = g++ demo_CXXSRC = \ - emul/emul.cpp \ - emul/emulwin.cpp \ - emul/emulkbd.cpp \ - drv/lcd_gfx_qt.cpp + bertos/emul/emul.cpp \ + bertos/emul/emulwin.cpp \ + bertos/emul/emulkbd.cpp \ + bertos/drv/lcd_gfx_qt.cpp demo_CSRC = \ app/demo/demo.c \ - os/hptime.c \ - gfx/bitmap.c \ - gfx/line.c \ - gfx/win.c \ - gfx/text.c \ - gfx/text_format.c \ - gui/menu.c \ - fonts/helvB10.c \ - fonts/luBS14.c \ - fonts/ncenB18.c \ - icons/logo.c \ - drv/kbd.c \ - drv/timer.c \ - drv/buzzer.c \ - drv/ser.c \ - drv/ser_posix.c \ - mware/formatwr.c \ - mware/hex.c \ - mware/event.c \ - mware/observer.c \ - mware/resource.c \ - mware/sprintf.c \ - kern/proc.c \ - kern/sem.c \ - kern/signal.c \ - kern/monitor.c \ - kern/proc_test.c \ - verstag.c + bertos/os/hptime.c \ + bertos/gfx/bitmap.c \ + bertos/gfx/line.c \ + bertos/gfx/win.c \ + bertos/gfx/text.c \ + bertos/gfx/text_format.c \ + bertos/gui/menu.c \ + bertos/fonts/helvB10.c \ + bertos/fonts/luBS14.c \ + bertos/fonts/ncenB18.c \ + bertos/icons/logo.c \ + bertos/drv/kbd.c \ + bertos/drv/timer.c \ + bertos/drv/buzzer.c \ + bertos/drv/ser.c \ + bertos/drv/ser_posix.c \ + bertos/mware/formatwr.c \ + bertos/mware/hex.c \ + bertos/mware/event.c \ + bertos/mware/observer.c \ + bertos/mware/resource.c \ + bertos/mware/sprintf.c \ + bertos/kern/proc.c \ + bertos/kern/sem.c \ + bertos/kern/signal.c \ + bertos/kern/monitor.c \ + bertos/kern/proc_test.c \ + bertos/verstag.c demo_CPPASRC = \ - kern/switch.S + bertos/kern/switch.S # FIXME: maybe this junk should go in emul/emul.mk? -$(OBJDIR)/demo/emul/emulwin.o: emul/emulwin_moc.cpp -$(OBJDIR)/demo/drv/lcd_gfx_qt.o: drv/lcd_gfx_qt_moc.cpp -$(OBJDIR)/demo/drv/timer.o: drv/timer_qt_moc.cpp -$(OBJDIR)/demo/emul/emulkbd.o: emul/emulkbd_moc.cpp +$(OBJDIR)/demo/bertos/emul/emulwin.o: bertos/emul/emulwin_moc.cpp +$(OBJDIR)/demo/bertos/drv/lcd_gfx_qt.o: bertos/drv/lcd_gfx_qt_moc.cpp +$(OBJDIR)/demo/bertos/drv/timer.o: bertos/drv/timer_qt_moc.cpp +$(OBJDIR)/demo/bertos/emul/emulkbd.o: bertos/emul/emulkbd_moc.cpp #FIXME: isn't there a way to avoid repeating the pattern rule? -drv/timer_qt_moc.cpp: drv/timer_qt.c +bertos/drv/timer_qt_moc.cpp: bertos/drv/timer_qt.c $(QT_MOC) -o $@ $< -demo_CFLAGS = -D_QT=4 -D'ARCH=ARCH_EMUL' -Iapp/demo -Ihw $(EMUL_CFLAGS) -demo_CXXFLAGS = -D_QT=4 -D'ARCH=ARCH_EMUL' -Iapp/demo -Ihw $(EMUL_CFLAGS) +demo_CFLAGS = -D_QT=4 -D'ARCH=ARCH_EMUL' -Iapp/demo $(EMUL_CFLAGS) +demo_CXXFLAGS = -D_QT=4 -D'ARCH=ARCH_EMUL' -Iapp/demo $(EMUL_CFLAGS) demo_LDFLAGS = $(EMUL_LDFLAGS) # Debug stuff ifeq ($(demo_DEBUG),1) demo_CFLAGS += -D_DEBUG demo_CXXFLAGS += -D_DEBUG - demo_CSRC += drv/kdebug.c + demo_CSRC += bertos/drv/kdebug.c else demo_CFLAGS += -Os demo_CXXFLAGS += -Os diff --git a/appconfig_common.h b/appconfig_common.h deleted file mode 100644 index 746ff1a6..00000000 --- a/appconfig_common.h +++ /dev/null @@ -1,245 +0,0 @@ -/** - * \file - * - * - * \brief DevLib configuration options - * - * You should copy this header in your project and rename it to - * "config.h" and delete the CONFIG_ macros for the modules - * you're not using. - * - *

Working with multiple applications

- * - * If your project is made of multiple DevLib-based applications, - * create a custom "config.h" file in each application subdirectory - * and play with the compiler include path to get the desired result. - * You can share common options by creationg a "config_common.h" header - * and including it from all your "config.h" copies. - * - *

Configuration style

- * - * For improved compile-time checking of configuration options, - * the preferred way to use a \c CONFIG_ symbol is keeping it - * always defined with a value of either 0 or 1. This lets - * you write tests like this: - * - * \code - * #if CONFIG_FOO - * void foo(void) - * { - * if (CONFIG_BAR) - * bar(); - * } - * #endif // CONFIG_FOO - * \endcode - * - * In most cases, we rely on the optimizer to discard checks - * on constant values and performing dead-code elimination. - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#ifndef APPCONFIG_COMMON_H -#define APPCONFIG_COMMON_H - -/** kdebug console */ -#define CONFIG_KDEBUG_PORT 0 - -/** Baud-rate for the kdebug console */ -#define CONFIG_KDEBUG_BAUDRATE 19200 - -/** - * printf()-style formatter configuration. - * - * \sa PRINTF_DISABLED - * \sa PRINTF_NOMODIFIERS - * \sa PRINTF_REDUCED - * \sa PRINTF_NOFLOAT - * \sa PRINTF_FULL - */ -#define CONFIG_PRINTF PRINTF_FULL - -/** - * Multithreading kernel. - * - * \sa config_kern.h - */ -#define CONFIG_KERNEL 0 - -/** - * \name Serial driver parameters - * \{ - */ - /** [bytes] Size of the outbound FIFO buffer for port 0. */ - #define CONFIG_UART0_TXBUFSIZE 32 - - /** [bytes] Size of the inbound FIFO buffer for port 0. */ - #define CONFIG_UART0_RXBUFSIZE 64 - - /** [bytes] Size of the outbound FIFO buffer for port 1. */ - #define CONFIG_UART1_TXBUFSIZE 32 - - /** [bytes] Size of the inbound FIFO buffer for port 1. */ - #define CONFIG_UART1_RXBUFSIZE CONFIG_PROTOCOL_BUFLEN - - /** [bytes] Size of the outbound FIFO buffer for SPI port 0. */ - #define CONFIG_SPI0_TXBUFSIZE 16 - - /** [bytes] Size of the inbound FIFO buffer for SPI port 0. */ - #define CONFIG_SPI0_RXBUFSIZE 32 - - /** [bytes] Size of the outbound FIFO buffer for SPI port 1. */ - #define CONFIG_SPI1_TXBUFSIZE 16 - - /** [bytes] Size of the inbound FIFO buffer for SPI port 1. */ - #define CONFIG_SPI1_RXBUFSIZE 32 - - /** SPI data order (AVR only). */ - #define CONFIG_SPI_DATA_ORDER SER_MSB_FIRST - - /** SPI clock division factor (AVR only). */ - #define CONFIG_SPI_CLOCK_DIV 16 - - /** SPI clock polarity: 0 = normal low, 1 = normal high (AVR only). */ - #define CONFIG_SPI_CLOCK_POL 0 - - /** SPI clock phase: 0 = sample on first edge, 1 = sample on second clock edge (AVR only). */ - #define CONFIG_SPI_CLOCK_PHASE 0 - - /** Default transmit timeout (ms). Set to -1 to disable timeout support */ - #define CONFIG_SER_TXTIMEOUT -1 - - /** Default receive timeout (ms). Set to -1 to disable timeout support */ - #define CONFIG_SER_RXTIMEOUT -1 - - /** Use RTS/CTS handshake */ - #define CONFIG_SER_HWHANDSHAKE 0 - - /** Default baud rate (set to 0 to disable) */ - #define CONFIG_SER_DEFBAUDRATE 0 - - /** Enable ser_gets() and ser_gets_echo() */ - #define CONFIG_SER_GETS 0 - - /** Enable second serial port in emulator. */ - #define CONFIG_EMUL_UART1 0 - - /** - * Transmit always something on serial port 0 TX - * to avoid interference when sending burst of data, - * using AVR multiprocessor serial mode - */ - #define CONFIG_SER_TXFILL 0 - - #define CONFIG_SER_STROBE 0 -/*\}*/ - -/// Hardware timer selection for drv/timer.c -#define CONFIG_TIMER TIMER_ON_OUTPUT_COMPARE2 - -/// Debug timer interrupt using a strobe pin. -#define CONFIG_TIMER_STROBE 0 - -/// Enable ADS strobe. -#define CONFIG_ADC_STROBE 0 - -/// Enable watchdog timer. -#define CONFIG_WATCHDOG 0 - -/// EEPROM type for drv/eeprom.c -#define CONFIG_EEPROM_TYPE EEPROM_24XX256 - -/// Select bitmap pixel format. -#define CONFIG_BITMAP_FMT BITMAP_FMT_PLANAR_V_LSB - -/// Enable line clipping algorithm. -#define CONFIG_GFX_CLIPPING 1 - -/// Enable text rendering in bitmaps. -#define CONFIG_GFX_TEXT 1 - -/// Enable virtual coordinate system. -#define CONFIG_GFX_VCOORDS 1 - -/// Keyboard polling method -#define CONFIG_KBD_POLL KBD_POLL_SOFTINT - -/// Enable keyboard event delivery to observers -#define CONFIG_KBD_OBSERVER 0 - -/// Enable key beeps -#define CONFIG_KBD_BEEP 1 - -/// Enable long pression handler for keys -#define CONFIG_KBD_LONGPRESS 1 - -/** - * \name Type for the chart dataset - * \{ - */ -#define CONFIG_CHART_TYPE_X uint8_t -#define CONFIG_CHART_TYPE_Y uint8_t -/*\}*/ - -/// Enable button bar behind menus -#define CONFIG_MENU_MENUBAR 0 - -/// Enable smooth scrolling in menus -#define CONFIG_MENU_SMOOTH 1 - -/// Size of block for MD2 algorithm. -#define CONFIG_MD2_BLOCK_LEN 16 - -/// Use standard permutation in MD2 algorithm. -#define CONFIG_MD2_STD_PERM 0 - -/// Define a size, in byte, of entropy pool. -#define CONFIG_SIZE_ENTROPY_POOL 64 - -/// Turn on or off timer support in Randpool. -#define CONFIG_RANDPOOL_TIMER 1 - -/** - * ADC timing setting parameter - * - * - CONFIG_ADC_CLOCK is frequency clock for ADC conversion. - * - CONFIG_ADC_STARTUP_TIME minimum time for startup a conversion in micro second. - * - CONFIG_ADC_SHTIME minimum time for sample and hold in nano second. - * \{ - */ -#define CONFIG_ADC_CLOCK 4800000UL -#define CONFIG_ADC_STARTUP_TIME 20 -#define CONFIG_ADC_SHTIME 834 -/* \} */ - -#endif /* APPCONFIG_H */ diff --git a/bertos/algo/crc.c b/bertos/algo/crc.c new file mode 100644 index 00000000..d465e260 --- /dev/null +++ b/bertos/algo/crc.c @@ -0,0 +1,88 @@ +/** + * \file + * + * + * \brief CRC table and support routines + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "crc.h" + +/** + * crctab calculated by Mark G. Mendel, Network Systems Corporation + */ +const uint16_t crc16tab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +uint16_t crc16(uint16_t crc, const void *buffer, size_t len) +{ + const unsigned char *buf = (const unsigned char *)buffer; + while(len--) + crc = UPDCRC16(*buf++, crc); + + return crc; +} + diff --git a/bertos/algo/crc.h b/bertos/algo/crc.h new file mode 100644 index 00000000..d6a1f45d --- /dev/null +++ b/bertos/algo/crc.h @@ -0,0 +1,102 @@ +/** + * \file + * + * + * \brief XModem-CRC16 algorithm (interface) + * + * \note This algorithm is incompatible with the CCITT-CRC16. + * + * This code is based on the article Copyright 1986 Stephen Satchell. + * + * Programmers may incorporate any or all code into their programs, + * giving proper credit within the source. Publication of the + * source routines is permitted so long as proper credit is given + * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, + * Omen Technology. + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#ifndef ALGO_CRC_H +#define ALGO_CRC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* CRC table */ +extern const uint16_t crc16tab[256]; + + +/** + * \brief Compute the updated CRC16 value for one octet (macro version) + * + * \note This version is only intended for old/broken compilers. + * Use the inline function in new code. + * + * \param c New octet (range 0-255) + * \param oldcrc Previous CRC16 value (referenced twice, beware of side effects) + */ +#define UPDCRC16(c, oldcrc) (crc16tab[((oldcrc) >> 8) ^ ((unsigned char)(c))] ^ ((oldcrc) << 8)) + + +#ifdef INLINE +/** + * \brief Compute the updated CRC16 value for one octet (macro version) + */ +INLINE uint16_t updcrc16(uint8_t c, uint16_t oldcrc) +{ + return crc16tab[(oldcrc >> 8) ^ c] ^ (oldcrc << 8); +} +#endif // INLINE + + +/** + * This function implements the CRC 16 calculation on a buffer. + * + * \param crc Current CRC16 value. + * \param buf The buffer to perform CRC calculation on. + * \param len The length of the Buffer. + * + * \return The updated CRC16 value. + */ +extern uint16_t crc16(uint16_t crc, const void *buf, size_t len); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ALGO_CRC_H */ diff --git a/bertos/algo/md2.c b/bertos/algo/md2.c new file mode 100644 index 00000000..53b44865 --- /dev/null +++ b/bertos/algo/md2.c @@ -0,0 +1,377 @@ +/** + * \file + * + * + * \brief MD2 Message-Digest algorithm. + * + * The MD2 algorithm work with a constant array of 256 permutationt + * defined in RFC1319. If you don't want to use a standard array of + * permutatione you can use a md2_perm() function that generate an + * array of 256 "casual" permutation. To swich from a standard array + * to md2_perm function you must chanche CONFIG_MD2_STD_PERM defined in + * appconfig.h. + * If you need to store array in program memory you must define + * a macro _PROGMEM (for more info see mware/pgm.h). + * + * + * \version $Id$ + * \author Daniele Basile + */ + +/*#* + *#* $Log$ + *#* Revision 1.17 2007/06/07 16:06:39 batt + *#* Fix some doxygen errors. + *#* + *#* Revision 1.16 2007/02/15 13:29:49 asterix + *#* Add MD2_DIGEST_LEN macro. + *#* + *#* Revision 1.15 2007/02/06 15:53:34 asterix + *#* Add ROTR macro in m2d_perm, add comments, typos. + *#* + *#* Revision 1.13 2007/02/05 18:44:42 asterix + *#* Add md2_perm function. + *#* + *#* Revision 1.12 2007/02/05 16:52:44 asterix + *#* Add define for harvard architecture. + *#* + *#* Revision 1.11 2007/02/02 18:15:31 asterix + *#* Add function MD2_test. Fix bug in md2_update function. + *#* + *#* Revision 1.9 2007/02/02 13:10:01 asterix + *#* Fix some bugs in md2_pad and md2_update fuction. + *#* + *#* Revision 1.8 2007/02/01 14:45:56 asterix + *#* Rewrite md2_update function and fix some bug. + *#* + *#* Revision 1.7 2007/01/31 18:04:15 asterix + *#* Write md2_end function + *#* + *#* Revision 1.4 2007/01/31 13:51:57 asterix + *#* Write md2_compute function. + *#* + *#* Revision 1.2 2007/01/30 17:31:44 asterix + *#* Add function prototypes. + *#* + *#* Revision 1.1 2007/01/30 15:53:26 batt + *#* Add first md2 skel. + *#* + *#*/ + +#include "md2.h" + +#include //memset(), memcpy(); +#include +#include //ASSERT() +#include //MIN(), countof(), ROTR(); +#include + + +#if CONFIG_MD2_STD_PERM + /* + * Official array of 256 byte pemutation contructed from digits of pi, defined + * in the RFC 1319. + */ + static const uint8_t PGM_ATTR md2_perm[256] = + { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 + }; + + #define MD2_PERM(x) PGM_READ_CHAR(&md2_perm[x]) +#else + /** + * Md2_perm() function generate an array of 256 "casual" permutation. + */ + + /** + * Costant define for computing an array of 256 "casual" permutation. + * \{ + */ + #define K1 5 + #define K2 3 + #define R 2 + #define X 172 + /*\}*/ + + static uint8_t md2_perm(uint8_t i) + { + + i = i * K1; + i = ROTR(i, R); + i ^= X; + i = i * K2; + + return i; + } + + #define MD2_PERM(x) md2_perm(x) + +#endif + + +/** + * Pad function. Put len_pad unsigned char in + * input block. + */ +static void md2_pad(void *_block, size_t len_pad) +{ + uint8_t *block; + + block = (uint8_t *)_block; + + ASSERT(len_pad <= CONFIG_MD2_BLOCK_LEN); + + /* + * Fill input block with len_pad char. + */ + memset(block, len_pad, len_pad); + +} + +static void md2_compute(void *_state, void *_checksum, void *_block) +{ + int i = 0; + uint16_t t = 0; + uint8_t compute_array[COMPUTE_ARRAY_LEN]; + uint8_t *state; + uint8_t *checksum; + uint8_t *block; + + state = (uint8_t *)_state; + checksum = (uint8_t *)_checksum; + block = (uint8_t *)_block; + + /* + * Copy state and checksum context in compute array. + */ + memcpy(compute_array, state, CONFIG_MD2_BLOCK_LEN); + memcpy(compute_array + CONFIG_MD2_BLOCK_LEN, block, CONFIG_MD2_BLOCK_LEN); + + /* + * Fill compute array with state XOR block + */ + for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++) + compute_array[i + (CONFIG_MD2_BLOCK_LEN * 2)] = state[i] ^ block[i]; + + /* + * Encryt block. + */ + for(i = 0; i < NUM_COMPUTE_ROUNDS; i++) + { + for(int j = 0; j < COMPUTE_ARRAY_LEN; j++) + { + compute_array[j] ^= MD2_PERM(t); + t = compute_array[j]; + } + + t = (t + i) & 0xff; //modulo 256. + } + /* + * Update checksum. + */ + t = checksum[CONFIG_MD2_BLOCK_LEN - 1]; + + for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++) + { + checksum[i] ^= MD2_PERM(block[i] ^ t); + t = checksum[i]; + } + + /* + * Update state and clean compute array. + */ + memcpy(state, compute_array, CONFIG_MD2_BLOCK_LEN); + memset(compute_array, 0, sizeof(compute_array)); +} + +/** + * Algorithm initialization. + * + * \param context empty context. + */ +void md2_init(Md2Context *context) +{ + + memset(context, 0, sizeof(Md2Context)); + +} + +/** + * Update block. + */ +void md2_update(Md2Context *context, const void *_block_in, size_t block_len) +{ + + const uint8_t *block_in; + size_t cpy_len; + + + block_in = (const uint8_t *)_block_in; + + while(block_len > 0) + { + /* + * Choose a number of block that fill input context buffer. + */ + cpy_len = MIN(block_len, CONFIG_MD2_BLOCK_LEN - context->counter); + + + /* + * Copy in the buffer input block. + */ + memcpy(&context->buffer[context->counter], block_in, cpy_len); + + /* + * Update a context counter, input block length and remaning + * context buffer block lenght. + */ + context->counter += cpy_len; + block_len -= cpy_len; + block_in += cpy_len; + + /* + * If buffer is full, compute it. + */ + if (context->counter >= CONFIG_MD2_BLOCK_LEN) + { + md2_compute(context->state, context->checksum, context->buffer); + context->counter = 0; + } + } + + +} +/** + * Ends an MD2 message digest operation. + * This fuction take an context and return a pointer + * to context state. + * + * \param context in input. + * \return a pointer to context state (message digest). + */ +uint8_t *md2_end(Md2Context *context) +{ + + uint8_t buf[CONFIG_MD2_BLOCK_LEN]; + + /* + * Fill remaning empty context buffer. + */ + md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter); + + /* + * Update context buffer and compute it. + */ + md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter); + + /* + * Add context checksum to message input. + */ + md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN); + + + return context->state; //return a pointer to message digest. +} +/** + * MD2 test fuction. + * This function test MD2 algorithm with a standard string specified + * in RFC 1319. + * + * \note This test work with official array of 256 byte pemutation + * contructed from digits of pi, defined in the RFC 1319. + * + */ +bool md2_test(void) +{ + + Md2Context context; + + const char *test[] = + { + "", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + }; + + + const uint8_t *result[] = { + "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73", + "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0", + "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b", + "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8", + }; + + + for (int i = 0; i < countof(test); i++) + { + md2_init(&context); + md2_update(&context, test[i], strlen(test[i])); + + if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN)) + return false; + } + + return true; +} + +#if 0 + +#include +int main(int argc, char * argv[]) +{ + + if(md2_test()) + printf("MD2 algorithm work well!\n"); + else + printf("MD2 algorithm doesn't work well.\n"); + +} + +#endif + diff --git a/bertos/algo/md2.h b/bertos/algo/md2.h new file mode 100644 index 00000000..8d0edb79 --- /dev/null +++ b/bertos/algo/md2.h @@ -0,0 +1,73 @@ +/** + * \file + * + * + * \brief MD2 Message-Digest algorithm. + * + * The algorithm takes as input a message of arbitrary length and produces + * as output a 128-bit message digest of the input. + * It is conjectured that it is computationally infeasible to produce + * two messages having the same message digest, or to produce any + * message having a given prespecified target message digest. + * + * + * + * \version $Id$ + * \author Daniele Basile + */ + +#ifndef ALGO_MD2_H +#define ALGO_MD2_H + +#include +#include + +#define NUM_COMPUTE_ROUNDS 18 ///< Number of compute rounds. +#define COMPUTE_ARRAY_LEN CONFIG_MD2_BLOCK_LEN * 3 ///< Lenght of compute array. +#define MD2_DIGEST_LEN CONFIG_MD2_BLOCK_LEN +/** + * Context for MD2 computation. + */ +typedef struct Md2Context +{ + uint8_t buffer[CONFIG_MD2_BLOCK_LEN]; ///< Input buffer. + uint8_t state[CONFIG_MD2_BLOCK_LEN]; ///< Current state buffer. + uint8_t checksum[CONFIG_MD2_BLOCK_LEN]; ///< Checksum. + size_t counter; ///< Counter of remaining bytes. + +} Md2Context; + +void md2_init(Md2Context *context); +void md2_update(Md2Context *context, const void *block_in, size_t block_len); +uint8_t *md2_end(Md2Context *context); +bool md2_test(void); + +#endif /* ALGO_MD2_H */ diff --git a/bertos/algo/ramp.c b/bertos/algo/ramp.c new file mode 100644 index 00000000..9a2cc92e --- /dev/null +++ b/bertos/algo/ramp.c @@ -0,0 +1,206 @@ +/*! + * \file + * + * + * \brief Compute, save and load ramps for stepper motors (implementation) + * + * \version $Id$ + * + * \author Simone Zinanni + * \author Bernardo Innocenti + * \author Giovanni Bajo + * \author Daniele Basile + * + * + * The formula used by the ramp is the following: + * + *
+ *            a * b
+ * f(t) = -------------
+ *         lerp(a,b,t)
+ * 
+ * + * Where a and b are the maximum and minimum speed + * respectively (minimum and maximum wavelength respectively), and lerp + * is a linear interpolation with a factor: + * + *
+ * lerp(a,b,t) =  a + t * (b - a)  =  (a * (1 - t)) + (b * t)
+ * 
+ * + * t must be in the [0,1] interval. It is easy to see that the + * following holds true: + * + *
+ * f(0) = b,   f(1) = a
+ * 
+ * + * And that the function is monotonic. So, the function effectively interpolates + * between the maximum and minimum speed through its domain ([0,1] -> [b,a]). + * + * The curve drawn by this function is similar to 1 / (sqrt(n)), so it is slower + * than a linear acceleration (which would be 1/n). + * + * The floating point version uses a slightly modified function which accepts + * the parameter in the domain [0, MT] (where MT is maxTime, the length of the + * ramp, which is a setup parameter for the ramp). This is done to reduce the + * number of operations per step. The formula looks like this: + * + *
+ *               a * b * MT
+ * g(t) = ----------------------------
+ *           (a * MT) + t * (b - a)
+ * 
+ * + * It can be shown that this g(t) = f(t * MT). The denominator + * is a linear interpolation in the range [b*MT, a*MT], as t moves in the + * interval [0, MT]. So the interpolation interval of the function is again + * [b, a]. The implementation caches the value of the numerator and parts + * of the denominator, so that the formula becomes: + * + *
+ * alpha = a * b * MT
+ * beta = a * MT
+ * gamma = b - a
+ *
+ *                alpha
+ * g(t) = ----------------------
+ *           beta + t * gamma
+ * 
+ * + * and t is exactly the parameter that ramp_evaluate() gets, + * that is the current time (in range [0, MT]). The operations performed + * for each step are just an addition, a multiplication and a division. + * + * The fixed point version of the formula instead transforms the original + * function as follows: + * + *
+ *                   a * b                         a
+ *  f(t) =  -------------------------  =  --------------------
+ *                 a                         a
+ *           b * ( - * (1 - t) + t )         - * (1 - t) + t
+ *                 b                         b
+ * 
+ * + * t must be computed by dividing the current time (24 bit integer) + * by the maximum time (24 bit integer). This is done by precomputing the + * reciprocal of the maximum time as a 0.32 fixed point number, and multiplying + * it to the current time. Multiplication is performed 8-bits a time by + * FIX_MULT32(), so that we end up with a 0.16 fixed point number for + * t (and 1-t is just its twos-complement negation). + * a/b is in the range [0,1] (because a is always less than b, + * being the minimum wavelength), so it is precomputed as a 0.16 fixed point. + * The final step is then computing the denominator and executing the division + * (32 cycles using the 1-step division instruction in the DSP). + * + * The assembly implementation is needed for efficiency, but a C version of it + * can be easily written, in case it is needed in the future. + * + */ + +#include "ramp.h" +#include + +#include // memcpy() + +/** + * Multiply \p a and \p b two integer at 32 bit and extract the high 16 bit word. + */ +#define FIX_MULT32(a,b) (((uint64_t)(a)*(uint32_t)(b)) >> 16) + +void ramp_compute(struct Ramp *ramp, uint32_t clocksRamp, uint16_t clocksMinWL, uint16_t clocksMaxWL) +{ + ASSERT(clocksMaxWL >= clocksMinWL); + + // Save values in ramp struct + ramp->clocksRamp = clocksRamp; + ramp->clocksMinWL = clocksMinWL; + ramp->clocksMaxWL = clocksMaxWL; + +#if RAMP_USE_FLOATING_POINT + ramp->precalc.gamma = ramp->clocksMaxWL - ramp->clocksMinWL; + ramp->precalc.beta = (float)ramp->clocksMinWL * (float)ramp->clocksRamp; + ramp->precalc.alpha = ramp->precalc.beta * (float)ramp->clocksMaxWL; + +#else + ramp->precalc.max_div_min = ((uint32_t)clocksMinWL << 16) / (uint32_t)clocksMaxWL; + + /* Calcola 1/total_time in fixed point .32. Assumiamo che la rampa possa al + * massimo avere 25 bit (cioé valore in tick fino a 2^25, che con il + * prescaler=3 sono circa 7 secondi). Inoltre, togliamo qualche bit di precisione + * da destra (secondo quanto specificato in RAMP_CLOCK_SHIFT_PRECISION). + */ + ASSERT(ramp->clocksRamp < (1UL << (24 + RAMP_CLOCK_SHIFT_PRECISION))); + ramp->precalc.inv_total_time = 0xFFFFFFFFUL / (ramp->clocksRamp >> RAMP_CLOCK_SHIFT_PRECISION); + ASSERT(ramp->precalc.inv_total_time < 0x1000000UL); + +#endif +} + + +void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq) +{ + uint32_t minWL, maxWL; + + minWL = TIME2CLOCKS(FREQ2MICROS(maxFreq)); + maxWL = TIME2CLOCKS(FREQ2MICROS(minFreq)); + + ASSERT2(minWL < 65536UL, "Maximum frequency too high"); + ASSERT2(maxWL < 65536UL, "Minimum frequency too high"); + ASSERT(maxFreq > minFreq); + + ramp_compute( + ramp, + TIME2CLOCKS(length), + TIME2CLOCKS(FREQ2MICROS(maxFreq)), + TIME2CLOCKS(FREQ2MICROS(minFreq)) + ); +} + +void ramp_default(struct Ramp *ramp) +{ + ramp_setup(ramp, RAMP_DEF_TIME, RAMP_DEF_MINFREQ, RAMP_DEF_MAXFREQ); +} + +#if RAMP_USE_FLOATING_POINT + +float ramp_evaluate(const struct Ramp* ramp, float curClock) +{ + return ramp->precalc.alpha / (curClock * ramp->precalc.gamma + ramp->precalc.beta); +} + +#else + +INLINE uint32_t fix_mult32(uint32_t m1, uint32_t m2) +{ + uint32_t accum = 0; + accum += m1 * ((m2 >> 0) & 0xFF); + accum >>= 8; + accum += m1 * ((m2 >> 8) & 0xFF); + accum >>= 8; + accum += m1 * ((m2 >> 16) & 0xFF); + return accum; +} + +// a*b >> 16 +INLINE uint16_t fix_mult16(uint16_t a, uint32_t b) +{ + return (b*(uint32_t)a) >> 16; +} + +uint16_t FAST_FUNC ramp_evaluate(const struct Ramp* ramp, uint32_t curClock) +{ + uint16_t t = FIX_MULT32(curClock >> RAMP_CLOCK_SHIFT_PRECISION, ramp->precalc.inv_total_time); + uint16_t denom = fix_mult16((uint16_t)~t + 1, ramp->precalc.max_div_min) + t; + uint16_t cur_delta = ((uint32_t)ramp->clocksMinWL << 16) / denom; + + return cur_delta; +} + +#endif + + diff --git a/bertos/algo/ramp.h b/bertos/algo/ramp.h new file mode 100644 index 00000000..f438dc5e --- /dev/null +++ b/bertos/algo/ramp.h @@ -0,0 +1,199 @@ + +/** + * \file + * + * + * \brief Compute, save and load ramps for stepper motors (interace) + * + * \version $Id$ + * + * \author Simone Zinanni + * \author Giovanni Bajo + * \author Daniele Basile + * + * The acceleration ramp is used to properly accelerate a stepper motor. The main + * entry point is the function ramp_evaluate(), which must be called at every step + * of the motor: it gets as input the time elapsed since the stepper started + * accelerating, and returns the time to wait before sending the next step. A pseudo + * usage pattern is as follows: + * + *
+ *  float time = 0;
+ *  while (1)
+ *  {
+ *      float delta = ramp_evaluate(&my_ramp, time);
+ *      sleep(delta);
+ *      do_motor_step();
+ *      time += delta;
+ *  }
+ * 
+ * + * A similar pattern can be used to decelerate (it is sufficient to move the total + * time backward, such as "time -= delta"). + * + * The ramp can be configured with ramp_setup(), providing it with the minimum and + * maximum operating frequency of the motor, and the total acceleration time in + * milliseconds (that is, the time that will be needed to accelerate from the + * minimum frequency to the maximum frequency). + * + * Both a very precise floating point and a very fast fixed point implementation + * of the ramp evaluation are provided. The fixed point is hand-optimized assembly + * for DSP56000 (but a portable C version of it can be easily written, see the + * comments in the code). + * + */ + +#ifndef ALGO_RAMP_H +#define ALGO_RAMP_H + +#include +#include "hw_stepper.h" + +/** + * Define whether the ramp will use floating point calculation within ramp_evaluate(). + * Otherwise, a less precise fixed point version will be used, which is faster on + * platforms which do no support floating point operations. + * + * \note Floating point operations will be always done within ramp_compute() to + * precalculate values, so there has to be at least a floating point emulation support. + */ +#define RAMP_USE_FLOATING_POINT 0 + + +#if !RAMP_USE_FLOATING_POINT + + /** + * Number of least-significant bits which are stripped away during ramp evaluation. + * This setting allows to specify larger ramps at the price of less precision. + * + * The maximum ramp size allowed is 2^(24 + RAMP_CLOCK_SHIFT_PRECISION), in clocks. + * For instance, using RAMP_CLOCK_SHIFT_PRECISION 1, and a 8x prescaler, the maximum + * length of a ramp is about 6.7 secs. Raising RAMP_CLOCK_SHIFT_PRECISION to 2 + * brings the maximum length to 13.4 secs, at the price of less precision. + * + * ramp_compute() will check that the length is below the maximum allowed through + * a runtime assertion. + * + * \note This macro is used only for the fixed-point version of the ramp. + */ + #define RAMP_CLOCK_SHIFT_PRECISION 2 +#endif + + +///< Negative pulse width for ramp +#define RAMP_PULSE_WIDTH 50 + +///< Default ramp +#define RAMP_DEF_TIME 6000000 ///< microsecs +#define RAMP_DEF_MAXFREQ 5000 ///< Hz +#define RAMP_DEF_MINFREQ 200 ///< Hz +#define RAMP_DEF_POWERRUN 10 ///< 10 deciampere (1 ampere) +#define RAMP_DEF_POWERIDLE 1 ///< 1 deciampere + + +/** + * Convert microseconds to timer clock ticks + */ +#define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000)) + +/** + * Convert timer clock ticks back to microseconds + */ +#define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000)) + +/** + * Convert microseconds to Hz + */ +#define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros))) + +/** + * Convert frequency (in Hz) to time (in microseconds) + */ +#define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz))) + + + +/** + * Structure holding pre-calculated data for speeding up real-time evaluation + * of the ramp. This structure is totally different between the fixed and the + * floating point version of the code. + * + * Consult the file-level documentation of ramp.c for more information about + * the values of this structure. + */ +struct RampPrecalc +{ +#if RAMP_USE_FLOATING_POINT + float beta; + float alpha; + float gamma; +#else + uint16_t max_div_min; + uint32_t inv_total_time; +#endif +}; + + +/** + * Ramp structure + */ +struct Ramp +{ + uint32_t clocksRamp; + uint16_t clocksMinWL; + uint16_t clocksMaxWL; + + struct RampPrecalc precalc; ///< pre-calculated values for speed +}; + + +/* + * Function prototypes + */ +void ramp_compute( + struct Ramp * ramp, + uint32_t clocksInRamp, + uint16_t clocksInMinWavelength, + uint16_t clocksInMaxWavelength); + + +/** Setup an acceleration ramp for a stepper motor + * + * \param ramp Ramp to fill + * \param length Length of the ramp (milliseconds) + * \param minFreq Minimum operating frequency of the motor (hertz) + * \param maxFreq Maximum operating frequency of the motor (hertz) + * + */ +void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq); + + +/** + * Initialize a new ramp with default values + */ +void ramp_default(struct Ramp *ramp); + + +/** + * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since + * the start of the acceleration, compute the next step, that is the interval at which + * send the signal to the motor. + * + * \note The fixed point version does not work when curClock is zero. Anyway, + * the first step is always clocksMaxWL, as stored within the ramp structure. + */ +#if RAMP_USE_FLOATING_POINT + float ramp_evaluate(const struct Ramp* ramp, float curClock); +#else + uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock); +#endif + + +/** Self test */ +void ramp_test(void); + +#endif /* ALGO_RAMP_H */ + diff --git a/bertos/algo/ramp_test.c b/bertos/algo/ramp_test.c new file mode 100644 index 00000000..92de9405 --- /dev/null +++ b/bertos/algo/ramp_test.c @@ -0,0 +1,175 @@ +/*! + * \file + * + * + * \brief Test for compute, save and load ramps for stepper motors (implementation) + * + * \version $Id$ + * + * \author Simone Zinanni + * \author Bernardo Innocenti + * \author Giovanni Bajo + * \author Daniele Basile + * + * + * The formula used by the ramp is the following: + * + *
+ *            a * b
+ * f(t) = -------------
+ *         lerp(a,b,t)
+ * 
+ * + * Where a and b are the maximum and minimum speed + * respectively (minimum and maximum wavelength respectively), and lerp + * is a linear interpolation with a factor: + * + *
+ * lerp(a,b,t) =  a + t * (b - a)  =  (a * (1 - t)) + (b * t)
+ * 
+ * + * t must be in the [0,1] interval. It is easy to see that the + * following holds true: + * + *
+ * f(0) = b,   f(1) = a
+ * 
+ * + * And that the function is monotonic. So, the function effectively interpolates + * between the maximum and minimum speed through its domain ([0,1] -> [b,a]). + * + * The curve drawn by this function is similar to 1 / (sqrt(n)), so it is slower + * than a linear acceleration (which would be 1/n). + * + * The floating point version uses a slightly modified function which accepts + * the parameter in the domain [0, MT] (where MT is maxTime, the length of the + * ramp, which is a setup parameter for the ramp). This is done to reduce the + * number of operations per step. The formula looks like this: + * + *
+ *               a * b * MT
+ * g(t) = ----------------------------
+ *           (a * MT) + t * (b - a)
+ * 
+ * + * It can be shown that this g(t) = f(t * MT). The denominator + * is a linear interpolation in the range [b*MT, a*MT], as t moves in the + * interval [0, MT]. So the interpolation interval of the function is again + * [b, a]. The implementation caches the value of the numerator and parts + * of the denominator, so that the formula becomes: + * + *
+ * alpha = a * b * MT
+ * beta = a * MT
+ * gamma = b - a
+ *
+ *                alpha
+ * g(t) = ----------------------
+ *           beta + t * gamma
+ * 
+ * + * and t is exactly the parameter that ramp_evaluate() gets, + * that is the current time (in range [0, MT]). The operations performed + * for each step are just an addition, a multiplication and a division. + * + * The fixed point version of the formula instead transforms the original + * function as follows: + * + *
+ *                   a * b                         a
+ *  f(t) =  -------------------------  =  --------------------
+ *                 a                         a
+ *           b * ( - * (1 - t) + t )         - * (1 - t) + t
+ *                 b                         b
+ * 
+ * + * t must be computed by dividing the current time (24 bit integer) + * by the maximum time (24 bit integer). This is done by precomputing the + * reciprocal of the maximum time as a 0.32 fixed point number, and multiplying + * it to the current time. Multiplication is performed 8-bits a time by + * FIX_MULT32(), so that we end up with a 0.16 fixed point number for + * t (and 1-t is just its twos-complement negation). + * a/b is in the range [0,1] (because a is always less than b, + * being the minimum wavelength), so it is precomputed as a 0.16 fixed point. + * The final step is then computing the denominator and executing the division + * (32 cycles using the 1-step division instruction in the DSP). + * + * The assembly implementation is needed for efficiency, but a C version of it + * can be easily written, in case it is needed in the future. + * + */ + +#include "ramp.h" +#include + +static bool ramp_test_single(uint32_t minFreq, uint32_t maxFreq, uint32_t length) +{ + struct Ramp r; + uint16_t cur, old; + uint32_t clock; + uint32_t oldclock; + + ramp_setup(&r, length, minFreq, maxFreq); + + cur = old = r.clocksMaxWL; + clock = 0; + oldclock = 0; + + kprintf("testing ramp: (length=%lu, min=%lu, max=%lu)\n", length, minFreq, maxFreq); + kprintf(" [length=%lu, max=%04x, min=%04x]\n", r.clocksRamp, r.clocksMaxWL, r.clocksMinWL); + + int i = 0; + int nonbyte = 0; + + while (clock + cur < r.clocksRamp) + { + oldclock = clock; + old = cur; + + clock += cur; + cur = ramp_evaluate(&r, clock); + + if (old < cur) + { + uint16_t t1 = FIX_MULT32(oldclock >> RAMP_CLOCK_SHIFT_PRECISION, r.precalc.inv_total_time); + uint16_t t2 = FIX_MULT32(clock >> RAMP_CLOCK_SHIFT_PRECISION, r.precalc.inv_total_time); + uint16_t denom1 = FIX_MULT32((uint16_t)((~t1) + 1), r.precalc.max_div_min) + t1; + uint16_t denom2 = FIX_MULT32((uint16_t)((~t2) + 1), r.precalc.max_div_min) + t2; + + kprintf(" Failed: %04x @ %lu --> %04x @ %lu\n", old, oldclock, cur, clock); + kprintf(" T: %04x -> %04x\n", t1, t2); + kprintf(" DENOM: %04x -> %04x\n", denom1, denom2); + + cur = ramp_evaluate(&r, clock); + return false; + } + i++; + if ((old-cur) >= 256) + nonbyte++; + } + + + + kprintf("Test finished: %04x @ %lu [min=%04x, totlen=%lu, numsteps:%d, nonbyte:%d]\n", cur, clock, r.clocksMinWL, r.clocksRamp, i, nonbyte); + + return true; +} + + +void ramp_test(void) +{ + bool ok = true; + + ok = ramp_test_single(200, 5000, 3000000) && ok; + ok = ramp_test_single(1000, 2000, 1000000) && ok; + + if (ok) + kputs("Ramp test succeeded!\n"); + else + kputs("Ramp test fail!\n"); +} + + diff --git a/bertos/algo/randpool.c b/bertos/algo/randpool.c new file mode 100644 index 00000000..a32fdff4 --- /dev/null +++ b/bertos/algo/randpool.c @@ -0,0 +1,298 @@ +/** + * \file + * + * + * \brief API function for to manage entropy pool. + * + * \version $Id$ + * \author Daniele Basile + */ + +/*#* + *#* $Log$ + *#* Revision 1.20 2007/06/07 16:06:39 batt + *#* Fix some doxygen errors. + *#* + *#* Revision 1.19 2007/02/15 13:54:26 asterix + *#* Rename randpool_getN in randpool_get. Fix bug in randpool_get. + *#* + *#* Revision 1.17 2007/02/15 13:40:42 asterix + *#* Fix bug in randpool_add and randpool_strir. + *#* + *#* Revision 1.16 2007/02/13 15:11:37 asterix + *#* Typo. + *#* + *#* Revision 1.14 2007/02/13 09:57:12 asterix + *#* Add directive #if in struct EntropyPool, and remove #else in randpool_add. + *#* + *#* Revision 1.13 2007/02/12 18:25:34 asterix + *#* Fix bug in randpool_getN. + *#* + *#* Revision 1.12 2007/02/12 09:47:39 asterix + *#* Remove randpool_save. Add randpool_pool. + *#* + *#* Revision 1.10 2007/02/12 09:03:32 asterix + *#* Add CONFIG_RANDPOOL_TIMER macro to swich on or off timer support + *#* + *#* Revision 1.9 2007/02/09 17:58:09 asterix + *#* Add macro CONFIG_RANDPOOL_TIMER. + *#* + *#* Revision 1.6 2007/02/09 09:24:38 asterix + *#* Typos. Add data_len in randpool_add and n_byte in randpool_push pototypes. + *#* + *#* Revision 1.3 2007/02/08 14:25:29 asterix + *#* Write static funcion push_byte. + *#* + *#*/ + +#include "randpool.h" +#include "md2.h" + +#include //sprintf(); +#include //memset(), memcpy(); + +#include +#include //ASSERT() +#include //MIN(), ROUND_UP(); + +#if CONFIG_RANDPOOL_TIMER + #include //timer_clock(); +#endif + + + +/* + * Insert bytes in entropy pool, making a XOR of bytes present + * in entropy pool. + */ +static void randpool_push(EntropyPool *pool, void *_byte, size_t n_byte) +{ + size_t i = pool->pos_add; // Current number of byte insert in entropy pool. + uint8_t *byte; + + byte = (uint8_t *)_byte; + + /* + * Insert a bytes in entropy pool. + */ + for(int j = 0; j < n_byte; j++) + { + pool->pool_entropy[i] = pool->pool_entropy[i] ^ byte[j]; + i = (++i) % CONFIG_SIZE_ENTROPY_POOL; + } + + pool->pos_add = i; // Update a insert bytes. +} + + +/* + * This function stir entropy pool with MD2 function hash. + * + */ +static void randpool_stir(EntropyPool *pool) +{ + size_t entropy = pool->entropy; //Save current calue of entropy. + Md2Context context; + uint8_t tmp_buf[((sizeof(size_t) * 2) + sizeof(int)) * 2 + 1]; //Temporary buffer. + + md2_init(&context); //Init MD2 algorithm. + + randpool_add(pool, NULL, 0); + + for (int i = 0; i < (CONFIG_SIZE_ENTROPY_POOL / MD2_DIGEST_LEN); i++) + { + sprintf(tmp_buf, "%0x%0x%0x",pool->counter, i, pool->pos_add); + + /* + * Hash with MD2 algorithm the entropy pool. + */ + md2_update(&context, pool->pool_entropy, CONFIG_SIZE_ENTROPY_POOL); + + md2_update(&context, tmp_buf, sizeof(tmp_buf) - 1); + + /*Insert a message digest in entropy pool.*/ + randpool_push(pool, md2_end(&context), MD2_DIGEST_LEN); + + pool->counter = pool->counter + 1; + + } + + /*Insert in pool the difference between a two call of this function (see above).*/ + randpool_add(pool, NULL, 0); + + pool->entropy = entropy; //Restore old value of entropy. We haven't add entropy. +} + +/** + * Add \param entropy bits from \param data buffer to the entropy \param pool + */ +void randpool_add(EntropyPool *pool, void *data, size_t entropy) +{ + uint8_t sep[] = "\xaa\xaa\xaa\xaa"; // ?? + size_t data_len = ROUND_UP(entropy, 8) / 8; //Number of entropy byte in input. + + randpool_push(pool, data, data_len); //Insert data to entropy pool. + +#if CONFIG_RANDPOOL_TIMER + + ticks_t event = timer_clock(); + ticks_t delta; + + /*Difference of time between a two accese to entropy pool.*/ + delta = event - pool->last_counter; + + randpool_push(pool, &event, sizeof(ticks_t)); + randpool_push(pool, sep, sizeof(sep) - 1); // ?? + randpool_push(pool, &delta, sizeof(delta)); + + /* + * Count of number entropy bit add with delta. + */ + delta = delta & 0xff; + while(delta) + { + delta >>= 1; + entropy++; + } + + pool->last_counter = event; + +#endif + + pool->entropy += entropy; //Update a entropy of the pool. +} + +/** + * Randpool function initialization. + * The entropy pool can be initialize also with + * a previous entropy pool. + */ +void randpool_init(EntropyPool *pool, void *_data, size_t len) +{ + uint8_t *data; + + data = (uint8_t *)_data; + + memset(pool, 0, sizeof(EntropyPool)); + pool->pos_get = MD2_DIGEST_LEN; + +#if CONFIG_RANDPOOL_TIMER + pool->last_counter = timer_clock(); +#endif + + if(data) + { + /* + * Initialize a entropy pool with a + * previous pool, and assume all pool as + * entropy. + */ + len = MIN(len,(size_t)CONFIG_SIZE_ENTROPY_POOL); + memcpy(pool->pool_entropy, data, len); + pool->entropy = len; + } + +} + +/** + * Get the actual value of entropy. + */ +size_t randpool_size(EntropyPool *pool) +{ + return pool->entropy; +} + +/** + * Get \param n_byte from entropy pool. If n_byte is larger than number + * byte of entropy in entropy pool, randpool_get continue + * to generate pseudocasual value from previous state of + * pool. + * \param n_byte number fo bytes to read. + * \param pool is the pool entropy context. + * \param _data is the pointer to write the random data to. + */ +void randpool_get(EntropyPool *pool, void *_data, size_t n_byte) +{ + Md2Context context; + size_t i = pool->pos_get; + size_t n = n_byte; + size_t pos_write = 0; //Number of block has been written in data. + size_t len = MIN((size_t)MD2_DIGEST_LEN, n_byte); + uint8_t *data; + + data = (uint8_t *)_data; + + /* Test if i + CONFIG_MD2_BLOCK_LEN is inside of entropy pool.*/ + ASSERT((MD2_DIGEST_LEN + i) < CONFIG_SIZE_ENTROPY_POOL); + + md2_init(&context); + + while(n > 0) + { + + /*Hash previous state of pool*/ + md2_update(&context, &pool->pool_entropy[i], MD2_DIGEST_LEN); + + memcpy(&data[pos_write], md2_end(&context), len); + + pos_write += len; //Update number of block has been written in data. + n -= len; //Number of byte copied in data. + + len = MIN(n,(size_t)MD2_DIGEST_LEN); + + i = (i + MD2_DIGEST_LEN) % CONFIG_SIZE_ENTROPY_POOL; + + /* If we haven't more entropy pool to hash, we stir it.*/ + if(i < MD2_DIGEST_LEN) + { + randpool_stir(pool); + i = pool->pos_get; + } + + } + + pool->pos_get = i; //Current number of byte we get from pool. + pool->entropy -= n_byte; //Update a entropy. + + /*If we get all entropy entropy is 0*/ + if(pool->entropy < 0) + pool->entropy = 0; + +} + +/** + * Return a pointer to entropy pool. + */ +uint8_t *randpool_pool(EntropyPool *pool) +{ + return pool->pool_entropy; +} + diff --git a/bertos/algo/randpool.h b/bertos/algo/randpool.h new file mode 100644 index 00000000..317ebe74 --- /dev/null +++ b/bertos/algo/randpool.h @@ -0,0 +1,72 @@ +/** + * \file + * + * + * \brief API function for to manage entropy pool. + * + * + * \version $Id$ + * \author Daniele Basile + */ + +#ifndef ALGO_RANDPOOL_H +#define ALGO_RANDPOOL_H + +#include +#include + + +/** + * Sturct data of entropy pool. + */ +typedef struct EntropyPool +{ + size_t entropy; ///< Actual value of entropy (byte). + size_t pos_add; ///< Number of byte idd in entropy pool. + size_t pos_get; ///< Number of byte get in entropy pool. + size_t counter; ///< Counter. + +#if CONFIG_RANDPOOL_TIMER + size_t last_counter; ///< Last timer value. +#endif + + uint8_t pool_entropy[CONFIG_SIZE_ENTROPY_POOL]; ///< Entropy pool. + +} EntropyPool; + + +void randpool_add(EntropyPool *pool, void *data, size_t entropy); +void randpool_init(EntropyPool *pool, void *_data, size_t len); +size_t randpool_size(EntropyPool *pool); +void randpool_get(EntropyPool *pool, void *data, size_t n_byte); +uint8_t *randpool_pool(EntropyPool *pool); + +#endif /* ALGO_RANDPOOL_H */ diff --git a/bertos/algo/rotating_hash.h b/bertos/algo/rotating_hash.h new file mode 100644 index 00000000..c154af1d --- /dev/null +++ b/bertos/algo/rotating_hash.h @@ -0,0 +1,82 @@ +/** + * \file + * + * + * \brief Rotating Hash algorithm (interface). + * + * This is a simple yet powerfull checksum algorithm. + * Instead of just xor-ing the data, rotating hash + * circular shift the checksum 4 place left before xoring. + * This is a bit more stronger than simply sum the data. + * + * \version $Id$ + * + * \author Francesco Sacchi + */ + + +#ifndef ALGO_ROTATING_H +#define ALGO_ROTATING_H + +#include + +typedef uint16_t rotating_t; + + +/** + * Init rotating checksum. + */ +INLINE void rotating_init(rotating_t *rot) +{ + *rot = 0; +} + +/** + * Update checksum pointed by \c rot with \c c data. + */ +INLINE void rotating_update1(uint8_t c, rotating_t *rot) +{ + *rot = (*rot << 4) ^ (*rot >> 12) ^ c; +} + +/** + * Update checksum pointed by \c rot with data supplied in \c buf. + */ +INLINE void rotating_update(const void *_buf, size_t len, rotating_t *rot) +{ + const uint8_t *buf = (const uint8_t *)_buf; + + while (len--) + rotating_update1(*buf++, rot); +} + + +#endif // ALGO_ROTATING_H diff --git a/bertos/algo/tea.c b/bertos/algo/tea.c new file mode 100644 index 00000000..f67d4c5e --- /dev/null +++ b/bertos/algo/tea.c @@ -0,0 +1,145 @@ +/** + * \file + * + * + * \brief TEA Tiny Encription Algorith functions (implementation). + * + * \version $Id$ + * \author Francesco Sacchi + * + * The Tiny Encryption Algorithm (TEA) by David Wheeler and Roger Needham + * of the Cambridge Computer Laboratory + * + * Placed in the Public Domain by David Wheeler and Roger Needham. + * + * **** ANSI C VERSION **** + * + * Notes: + * + * TEA is a Feistel cipher with XOR and and addition as the non-linear + * mixing functions. + * + * Takes 64 bits of data in v[0] and v[1]. Returns 64 bits of data in w[0] + * and w[1]. Takes 128 bits of key in k[0] - k[3]. + * + * TEA can be operated in any of the modes of DES. Cipher Block Chaining is, + * for example, simple to implement. + * + * n is the number of iterations. 32 is ample, 16 is sufficient, as few + * as eight may be OK. The algorithm achieves good dispersion after six + * iterations. The iteration count can be made variable if required. + * + * Note this is optimised for 32-bit CPUs with fast shift capabilities. It + * can very easily be ported to assembly language on most CPUs. + * + * delta is chosen to be the real part of (the golden ratio Sqrt(5/4) - + * 1/2 ~ 0.618034 multiplied by 2^32). + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2007/09/19 16:23:27 batt + *#* Fix doxygen warnings. + *#* + *#* Revision 1.1 2007/06/07 09:13:40 batt + *#* Add TEA enc/decryption algorithm. + *#* + *#* Revision 1.1 2007/01/10 17:30:10 batt + *#* Add cryptographic routines. + *#* + *#*/ + +#include "tea.h" +#include + +static uint32_t tea_func(uint32_t *in, uint32_t *sum, uint32_t *k) +{ + return ((*in << 4) + cpu_to_le32(k[0])) ^ (*in + *sum) ^ ((*in >> 5) + cpu_to_le32(k[1])); +} + +/** + * \brief TEA encryption function. + * This function encrypts v with k and returns the + * encrypted data in v. + * \param _v Array of two long values containing the data block. + * \param _k Array of four long values containing the key. + */ +void tea_enc(void *_v, void *_k) +{ + uint32_t y, z; + uint32_t sum = 0; + uint8_t n = ROUNDS; + uint32_t *v = (uint32_t *)_v; + uint32_t *k = (uint32_t *)_k; + + y=cpu_to_le32(v[0]); + z=cpu_to_le32(v[1]); + + while(n-- > 0) + { + sum += DELTA; + y += tea_func(&z, &sum, &(k[0])); + z += tea_func(&y, &sum, &(k[2])); + } + + v[0] = le32_to_cpu(y); + v[1] = le32_to_cpu(z); +} + +/** + * \brief TEA decryption function. + * This function decrypts v with k and returns the + * decrypted data in v. + * \param _v Array of two long values containing the data block. + * \param _k Array of four long values containing the key. + */ +void tea_dec(void *_v, void *_k) +{ + uint32_t y, z; + uint32_t sum = DELTA * ROUNDS; + uint8_t n = ROUNDS; + uint32_t *v = (uint32_t *)_v; + uint32_t *k = (uint32_t *)_k; + + y = cpu_to_le32(v[0]); + z = cpu_to_le32(v[1]); + + while(n-- > 0) + { + z -= tea_func(&y, &sum, &(k[2])); + y -= tea_func(&z, &sum, &(k[0])); + sum -= DELTA; + } + + v[0] = le32_to_cpu(y); + v[1] = le32_to_cpu(z); +} + diff --git a/bertos/algo/tea.h b/bertos/algo/tea.h new file mode 100644 index 00000000..97318012 --- /dev/null +++ b/bertos/algo/tea.h @@ -0,0 +1,57 @@ +/** + * \file + * + * + * \brief TEA Tiny Encription Algorith functions (interface). + * + * \version $Id$ + * \author Francesco Sacchi + * + * Documentation for TEA is available at + * http://www.cl.cam.ac.uk/ftp/users/djw3/tea.ps. + */ + +#ifndef ALGO_TEA_H +#define ALGO_TEA_H + +#include + +#define TEA_KEY_LEN 16 //!< TEA key size. +#define TEA_BLOCK_LEN 8 //!< TEA block length. + +#define DELTA 0x9E3779B9 //!< Magic value. (Golden number * 2^31) +#define ROUNDS 32 //!< Number of rounds. + +void tea_enc(void *_v, void *_k); +void tea_dec(void *_v, void *_k); + +#endif /* ALGO_TEA_H */ + diff --git a/bertos/appconfig_common.h b/bertos/appconfig_common.h new file mode 100644 index 00000000..746ff1a6 --- /dev/null +++ b/bertos/appconfig_common.h @@ -0,0 +1,245 @@ +/** + * \file + * + * + * \brief DevLib configuration options + * + * You should copy this header in your project and rename it to + * "config.h" and delete the CONFIG_ macros for the modules + * you're not using. + * + *

Working with multiple applications

+ * + * If your project is made of multiple DevLib-based applications, + * create a custom "config.h" file in each application subdirectory + * and play with the compiler include path to get the desired result. + * You can share common options by creationg a "config_common.h" header + * and including it from all your "config.h" copies. + * + *

Configuration style

+ * + * For improved compile-time checking of configuration options, + * the preferred way to use a \c CONFIG_ symbol is keeping it + * always defined with a value of either 0 or 1. This lets + * you write tests like this: + * + * \code + * #if CONFIG_FOO + * void foo(void) + * { + * if (CONFIG_BAR) + * bar(); + * } + * #endif // CONFIG_FOO + * \endcode + * + * In most cases, we rely on the optimizer to discard checks + * on constant values and performing dead-code elimination. + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#ifndef APPCONFIG_COMMON_H +#define APPCONFIG_COMMON_H + +/** kdebug console */ +#define CONFIG_KDEBUG_PORT 0 + +/** Baud-rate for the kdebug console */ +#define CONFIG_KDEBUG_BAUDRATE 19200 + +/** + * printf()-style formatter configuration. + * + * \sa PRINTF_DISABLED + * \sa PRINTF_NOMODIFIERS + * \sa PRINTF_REDUCED + * \sa PRINTF_NOFLOAT + * \sa PRINTF_FULL + */ +#define CONFIG_PRINTF PRINTF_FULL + +/** + * Multithreading kernel. + * + * \sa config_kern.h + */ +#define CONFIG_KERNEL 0 + +/** + * \name Serial driver parameters + * \{ + */ + /** [bytes] Size of the outbound FIFO buffer for port 0. */ + #define CONFIG_UART0_TXBUFSIZE 32 + + /** [bytes] Size of the inbound FIFO buffer for port 0. */ + #define CONFIG_UART0_RXBUFSIZE 64 + + /** [bytes] Size of the outbound FIFO buffer for port 1. */ + #define CONFIG_UART1_TXBUFSIZE 32 + + /** [bytes] Size of the inbound FIFO buffer for port 1. */ + #define CONFIG_UART1_RXBUFSIZE CONFIG_PROTOCOL_BUFLEN + + /** [bytes] Size of the outbound FIFO buffer for SPI port 0. */ + #define CONFIG_SPI0_TXBUFSIZE 16 + + /** [bytes] Size of the inbound FIFO buffer for SPI port 0. */ + #define CONFIG_SPI0_RXBUFSIZE 32 + + /** [bytes] Size of the outbound FIFO buffer for SPI port 1. */ + #define CONFIG_SPI1_TXBUFSIZE 16 + + /** [bytes] Size of the inbound FIFO buffer for SPI port 1. */ + #define CONFIG_SPI1_RXBUFSIZE 32 + + /** SPI data order (AVR only). */ + #define CONFIG_SPI_DATA_ORDER SER_MSB_FIRST + + /** SPI clock division factor (AVR only). */ + #define CONFIG_SPI_CLOCK_DIV 16 + + /** SPI clock polarity: 0 = normal low, 1 = normal high (AVR only). */ + #define CONFIG_SPI_CLOCK_POL 0 + + /** SPI clock phase: 0 = sample on first edge, 1 = sample on second clock edge (AVR only). */ + #define CONFIG_SPI_CLOCK_PHASE 0 + + /** Default transmit timeout (ms). Set to -1 to disable timeout support */ + #define CONFIG_SER_TXTIMEOUT -1 + + /** Default receive timeout (ms). Set to -1 to disable timeout support */ + #define CONFIG_SER_RXTIMEOUT -1 + + /** Use RTS/CTS handshake */ + #define CONFIG_SER_HWHANDSHAKE 0 + + /** Default baud rate (set to 0 to disable) */ + #define CONFIG_SER_DEFBAUDRATE 0 + + /** Enable ser_gets() and ser_gets_echo() */ + #define CONFIG_SER_GETS 0 + + /** Enable second serial port in emulator. */ + #define CONFIG_EMUL_UART1 0 + + /** + * Transmit always something on serial port 0 TX + * to avoid interference when sending burst of data, + * using AVR multiprocessor serial mode + */ + #define CONFIG_SER_TXFILL 0 + + #define CONFIG_SER_STROBE 0 +/*\}*/ + +/// Hardware timer selection for drv/timer.c +#define CONFIG_TIMER TIMER_ON_OUTPUT_COMPARE2 + +/// Debug timer interrupt using a strobe pin. +#define CONFIG_TIMER_STROBE 0 + +/// Enable ADS strobe. +#define CONFIG_ADC_STROBE 0 + +/// Enable watchdog timer. +#define CONFIG_WATCHDOG 0 + +/// EEPROM type for drv/eeprom.c +#define CONFIG_EEPROM_TYPE EEPROM_24XX256 + +/// Select bitmap pixel format. +#define CONFIG_BITMAP_FMT BITMAP_FMT_PLANAR_V_LSB + +/// Enable line clipping algorithm. +#define CONFIG_GFX_CLIPPING 1 + +/// Enable text rendering in bitmaps. +#define CONFIG_GFX_TEXT 1 + +/// Enable virtual coordinate system. +#define CONFIG_GFX_VCOORDS 1 + +/// Keyboard polling method +#define CONFIG_KBD_POLL KBD_POLL_SOFTINT + +/// Enable keyboard event delivery to observers +#define CONFIG_KBD_OBSERVER 0 + +/// Enable key beeps +#define CONFIG_KBD_BEEP 1 + +/// Enable long pression handler for keys +#define CONFIG_KBD_LONGPRESS 1 + +/** + * \name Type for the chart dataset + * \{ + */ +#define CONFIG_CHART_TYPE_X uint8_t +#define CONFIG_CHART_TYPE_Y uint8_t +/*\}*/ + +/// Enable button bar behind menus +#define CONFIG_MENU_MENUBAR 0 + +/// Enable smooth scrolling in menus +#define CONFIG_MENU_SMOOTH 1 + +/// Size of block for MD2 algorithm. +#define CONFIG_MD2_BLOCK_LEN 16 + +/// Use standard permutation in MD2 algorithm. +#define CONFIG_MD2_STD_PERM 0 + +/// Define a size, in byte, of entropy pool. +#define CONFIG_SIZE_ENTROPY_POOL 64 + +/// Turn on or off timer support in Randpool. +#define CONFIG_RANDPOOL_TIMER 1 + +/** + * ADC timing setting parameter + * + * - CONFIG_ADC_CLOCK is frequency clock for ADC conversion. + * - CONFIG_ADC_STARTUP_TIME minimum time for startup a conversion in micro second. + * - CONFIG_ADC_SHTIME minimum time for sample and hold in nano second. + * \{ + */ +#define CONFIG_ADC_CLOCK 4800000UL +#define CONFIG_ADC_STARTUP_TIME 20 +#define CONFIG_ADC_SHTIME 834 +/* \} */ + +#endif /* APPCONFIG_H */ diff --git a/bertos/cfg/arch_config.h b/bertos/cfg/arch_config.h new file mode 100644 index 00000000..01ed05d3 --- /dev/null +++ b/bertos/cfg/arch_config.h @@ -0,0 +1,54 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Set system configuration + */ + + +#ifndef ARCH_CONFIG_H +#define ARCH_CONFIG_H + +/** + * \name Architectures + * \{ + */ +#define ARCH_FOO (1<<0) +#define ARCH_BAR (1<<1) +#define ARCH_EMUL (1<<8) +/*\}*/ + +#endif /* ARCH_CONFIG_H */ diff --git a/bertos/cfg/compiler.h b/bertos/cfg/compiler.h new file mode 100644 index 00000000..a303dc77 --- /dev/null +++ b/bertos/cfg/compiler.h @@ -0,0 +1,528 @@ +/** + * \file + * + * + * \brief Additional support macros for compiler independance + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#ifndef BERTOS_COMPILER_H +#define BERTOS_COMPILER_H + +#include + + +#if defined __GNUC__ && defined __GNUC_MINOR__ + #define GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else + #define GNUC_PREREQ(maj, min) 0 +#endif + +/* Some CW versions do not allow enabling C99 from the settings panel. */ +#if defined(__MWERKS__) + #pragma c99 on +#endif + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + #define COMPILER_C99 1 +#else + #define COMPILER_C99 0 +#endif + + +/** Concatenate two different preprocessor tokens (allowing macros to expand) */ +#define PP_CAT(x,y) PP_CAT__(x,y) +#define PP_CAT__(x,y) x ## y +#define PP_CAT3(x,y,z) PP_CAT(PP_CAT(x,y),z) +#define PP_CAT4(x,y,z,w) PP_CAT(PP_CAT3(x,y,z),w) +#define PP_CAT5(x,y,z,w,j) PP_CAT(PP_CAT4(x,y,z,w),j) + +/** String-ize a token (allowing macros to expand) */ +#define PP_STRINGIZE(x) PP_STRINGIZE__(x) +#define PP_STRINGIZE__(x) #x + + +#if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) + + #pragma language=extended + + #if CPU_ARM + + #define COMPILER_VARIADIC_MACROS 1 + + #define INTERRUPT(x) __irq __arm void x (void) + #define INLINE static inline + + /* Include some standard C89/C99 stuff */ + #include + #include + #include + + #elif CPU_I196 + + // IAR has size_t as built-in type, but does not define this symbol. + #define _SIZE_T_DEFINED + + #define INTERRUPT(x) interrupt [x] + #define REGISTER shortad + #define INLINE /* unsupported */ + + /* + * Imported from . Unfortunately, we can't just include + * this header because it typedefs jmp_buf to be an array of chars. + * This would allow the compiler to place the buffer on an odd address. + * The CPU _should_ be able to perform word accesses to + * unaligned data, but there are *BUGS* in the 80196KC with + * some combinations of opcodes and addressing modes. One of + * these, "ST SP,[?GR]+" is used in the longjmp() implementation + * provided by the IAR compiler ANSI C library. When ?GR contains + * an odd address, surprisingly the CPU will copy the high order + * byte of the source operand (SP) in the low order byte of the + * destination operand (the memory location pointed to by ?GR). + * + * We also need to replace the library setjmp()/longjmp() with + * our own versions because the IAR implementation "forgets" to + * save the contents of local registers (?LR). + */ + struct _JMP_BUF + { + void *sp; /* Stack pointer */ + void *return_addr; /* Return address */ + int lr[6]; /* 6 local registers */ + }; + + typedef struct _JMP_BUF jmp_buf[1]; + + int setjmp(jmp_buf env); + void longjmp(jmp_buf env, int val); + + /* Fake bool support */ + #define true (1==1) + #define false (1!=1) + typedef unsigned char bool; + + #else + #error Unsupported CPU + #endif + +#elif defined(_MSC_VER) /* Win32 emulation support */ + + /* MSVC doesn't provide . */ + #ifndef __cplusplus + #define true (1==1) + #define false (1!=1) + typedef int bool; + #endif /* !__cplusplus */ + + /* These C99 functions are oddly named in MSVCRT32.lib */ + #define snprintf _snprintf + #define vsnprintf _vsnprintf + + /* MSVC doesn't support C99's __func__, but has a similar extension. */ + #define __func__ __FUNCTION__ + + /* MSVC doesn't support C99's inline keyword */ + #ifndef __cplusplus + #define INLINE __inline + #endif + +#elif defined(__GNUC__) + + /* Compiler features */ + #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */ + #define COMPILER_TYPEOF 1 + #define COMPILER_STATEMENT_EXPRESSIONS 1 + + /* GCC attributes */ + #define FORMAT(type,fmt,first) __attribute__((__format__(type, fmt, first))) + #define NORETURN __attribute__((__noreturn__)) + #define UNUSED_ARG(type,arg) __attribute__((__unused__)) type arg + #define UNUSED_VAR(type,name) __attribute__((__unused__)) type name + #define USED_VAR(type,name) __attribute__((__used__)) type name + #define INLINE static inline __attribute__((__always_inline__)) + #define LIKELY(x) __builtin_expect(!!(x), 1) + #define UNLIKELY(x) __builtin_expect(!!(x), 0) + #define PURE_FUNC __attribute__((pure)) + #define CONST_FUNC __attribute__((const)) + #define UNUSED_FUNC __attribute__((unused)) + #define USED_FUNC __attribute__((__used__)) + #define RESTRICT __restrict__ + #define MUST_CHECK __attribute__((warn_unused_result)) + #define PACKED __attribute__((packed)) + /** + * Force compiler to realod context variable. + */ + #define MEMORY_BARRIER asm volatile ("" : : : "memory") + + #if GNUC_PREREQ(3,1) + #define DEPRECATED __attribute__((__deprecated__)) + #endif + + #ifndef __cplusplus + #define ASSERT_TYPE_EQUAL(var1, var2) \ + STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2))) + #define ASSERT_TYPE_IS(var, type) \ + STATIC_ASSERT(__builtin_types_compatible_p(typeof(var), type)) + #endif + + /* Include some standard C89/C99 stuff */ + #include + #include + #include + #if !CPU_AVR + #include /* for ssize_t */ + #endif + + #ifndef __cplusplus + /* + * Disallow some C++ keywords as identifiers in C programs, + * for improved portability. + */ + #pragma GCC poison new delete class template typename + #pragma GCC poison private protected public operator + #pragma GCC poison friend mutable using namespace + #pragma GCC poison cin cout cerr clog + #endif + + + +#elif defined(__MWERKS__) + + /* Compiler features */ + #define COMPILER_VARIADIC_MACROS 1 + #define COMPILER_TYPEOF 1 + #define COMPILER_STATEMENT_EXPRESSIONS 1 + + #define typeof __typeof__ + + #define UNUSED_ARG(type,arg) type + + #include + #include + #include + + // CodeWarrior has size_t as built-in type, but does not define this symbol. + #define _SIZE_T_DEFINED + +#else + #error unknown compiler +#endif + + +/* Defaults for compiler extensions. */ + +/** + * \def COMPILER_VARIADIC_MACROS + * Support for macros with variable arguments. + */ +#ifndef COMPILER_VARIADIC_MACROS +#define COMPILER_VARIADIC_MACROS (COMPILER_C99 != 0) +#endif + +/** + * \def COMPILER_TYPEOF + * Support for dynamic type identification. + */ +#ifndef COMPILER_TYPEOF +#define COMPILER_TYPEOF 0 +#endif + +/** + * \def COMPILER_STATEMENT_EXPRESSIONS + * Support for statement expressions. + */ +#ifndef COMPILER_STATEMENT_EXPRESSIONS +#define COMPILER_STATEMENT_EXPRESSIONS 0 +#endif + +/* A few defaults for missing compiler features. */ +#ifndef INLINE +#define INLINE static inline +#endif +#ifndef NORETURN +#define NORETURN /* nothing */ +#endif +#ifndef FORMAT +#define FORMAT(type,fmt,first) /* nothing */ +#endif +#ifndef DEPRECATED +#define DEPRECATED /* nothing */ +#endif +#ifndef UNUSED_ARG +#define UNUSED_ARG(type,arg) type arg +#endif +#define UNUSED UNUSED_ARG /* OBSOLETE */ +#ifndef UNUSED_VAR +#define UNUSED_VAR(type,name) type name +#endif +#ifndef USED_VAR +#define USED_VAR(type,name) type name +#endif +#ifndef REGISTER +#define REGISTER /* nothing */ +#endif +#ifndef LIKELY +#define LIKELY(x) x +#endif +#ifndef UNLIKELY +#define UNLIKELY(x) x +#endif +#ifndef PURE_FUNC +#define PURE_FUNC /* nothing */ +#endif +#ifndef CONST_FUNC +#define CONST_FUNC /* nothing */ +#endif +#ifndef UNUSED_FUNC +#define UNUSED_FUNC /* nothing */ +#endif +#ifndef USED_FUNC +#define USED_FUNC /* nothing */ +#endif +#ifndef RESTRICT +#define RESTRICT /* nothing */ +#endif +#ifndef MUST_CHECK +#define MUST_CHECK /* nothing */ +#endif +#ifndef PACKED +#define PACKED /* nothing */ +#endif +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER /* nothing */ +#warning No memory barrier defined for select compiler. If you use the kernel check it. +#endif + + +/* Misc definitions */ +#ifndef NULL +#define NULL (void *)0 +#endif +#ifndef EOF +#define EOF (-1) +#endif + +/* Support for hybrid C/C++ applications. */ +#ifdef __cplusplus + #define EXTERN_C extern "C" + #define EXTERN_C_BEGIN extern "C" { + #define EXTERN_C_END } + #define EXTERN_CONST extern const + #define CONST_CAST(TYPE,EXPR) (const_cast(EXPR)) +#else + #define EXTERN_C extern + #define EXTERN_C_BEGIN /* nothing */ + #define EXTERN_C_END /* nothing */ + #define EXTERN_CONST const + #define CONST_CAST(TYPE,EXPR) ((TYPE)(EXPR)) /* FIXME: How can we suppress the warning in C? */ +#endif + + +#if defined(_MSC_VER) \ + || ((defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)) && CPU_I196) + /** + * \name ISO C99 fixed-size types + * + * These should be in , but a few compilers lack them. + * \{ + */ + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef short int int16_t; + typedef unsigned short int uint16_t; + typedef long int int32_t; /* _WIN64 safe */ + typedef unsigned long int uint32_t; /* _WIN64 safe */ + + #ifdef _MSC_VER + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #else + typedef long long int64_t; + typedef unsigned long long uint64_t; + #endif + /* \} */ +#else + /* This is the standard location. */ + #include +#endif + +#if CPU_AVR_ATMEGA8 + /* + * The ATmega8 has a very small Flash, so we can't afford + * to link in support routines for 32bit integer arithmetic. + */ + typedef int16_t ticks_t; /**< Type for time expressed in ticks. */ + typedef int16_t mtime_t; /**< Type for time expressed in milliseconds. */ + typedef int16_t utime_t; /**< Type for time expressed in microseconds. */ + #define SIZEOF_MTIME_T (16 / CPU_BITS_PER_CHAR) + #define SIZEOF_UTIME_T (16 / CPU_BITS_PER_CHAR) + #define MTIME_INFINITE 0x7FFFL +#else + typedef int32_t ticks_t; /**< Type for time expressed in ticks. */ + + typedef int32_t utime_t; /**< Type for time expressed in microseconds. */ + #define SIZEOF_UTIME_T (32 / CPU_BITS_PER_CHAR) + + #ifndef DEVLIB_MTIME_DEFINED + #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with */ + typedef int32_t mtime_t; /**< Type for time expressed in milliseconds. */ + #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR) + #define MTIME_INFINITE 0x7FFFFFFFL + #endif +#endif + +/** Bulk storage large enough for both pointers or integers. */ +typedef void * iptr_t; + +/** Bulk storage large enough for both pointers to constants or integers. */ +typedef const void * const_iptr_t; + +typedef unsigned char sigbit_t; /**< Type for signal bits. */ +typedef unsigned char sigmask_t; /**< Type for signal masks. */ +typedef unsigned char page_t; /**< Type for banked memory pages. */ + + +/** + * \name Standard type definitions. + * + * These should be in or , but many compilers + * and C libraries lack them. + * + * We check for some common definitions to avoid redefinitions: + * + * glibc, avr-libc: _SIZE_T_DEFINED, __ssize_t_defined + * Darwin libc: _BSD_SIZE_T_DEFINED_, _SIZE_T + * IAR ARM: _SIZE_T + * + * \{ + */ +#if !(defined(size_t) || defined(_SIZE_T_DEFINED) || defined(_BSD_SIZE_T_DEFINED_) \ + || defined(_SIZE_T)) + #if CPU_X86 + /* 32bit or 64bit (32bit for _WIN64). */ + typedef unsigned long size_t; + #else + #error Unknown CPU + #endif +#endif + +#if !(defined(ssize_t) || defined(_SSIZE_T) || defined(__ssize_t_defined)) + #if CPU_X86 + /* 32bit or 64bit (32bit for _WIN64). */ + typedef long ssize_t; + #elif CPU_ARM + typedef int ssize_t; + #elif CPU_AVR + /* 16bit (missing in avr-libc's sys/types.h). */ + typedef int ssize_t; + #else + #error Unknown CPU + #endif +#endif +/*\}*/ + + +/** + * \name Types for hardware registers. + * + * Only use these types for registers whose contents can + * be changed asynchronously by external hardware. + * + * \{ + */ +#if CPU_DSP56K + /* Registers can be accessed only through 16-bit pointers */ + typedef volatile uint16_t reg16_t; +#else + typedef volatile uint8_t reg8_t; + typedef volatile uint16_t reg16_t; + typedef volatile uint32_t reg32_t; +#endif +/*\}*/ + + +/* Quasi-ANSI macros */ +#ifndef offsetof + /** + * Return the byte offset of the member \a m in struct \a s. + * + * \note This macro should be defined in "stddef.h" and is sometimes + * compiler-specific (g++ has a builtin for it). + */ + #define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif +#ifndef countof + /** + * Count the number of elements in the static array \a a. + * + * \note This macro is non-standard, but implements a very common idiom + */ + #define countof(a) (sizeof(a) / sizeof(*(a))) +#endif + +/** + * Cast a member of a structure out to the containing structure. + * + * \param ptr the pointer to the member. + * \param type the type of the container struct this is embedded in. + * \param member the name of the member within the struct. + */ +#if COMPILER_TYPEOF && COMPILER_STATEMENT_EXPRESSIONS + #define containerof(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *_mptr = (ptr); /* type check */ \ + (type *)((char *)_mptr - offsetof(type, member)); \ + }) +#else + #define containerof(ptr, type, member) \ + ( (type *)((char *)(ptr) - offsetof(type, member)) ) +#endif + +/** Issue a compilation error if the \a condition is false */ +#define STATIC_ASSERT(condition) \ + UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1]) + +#ifndef ASSERT_TYPE_EQUAL + /** Ensure two variables have the same type. */ + #define ASSERT_TYPE_EQUAL(var1, var2) \ + do { (void)(&(var1) == &(var2)); } while(0) +#endif + +#ifndef ASSERT_TYPE_IS + /** Ensure variable is of specified type. */ + #define ASSERT_TYPE_IS(var, type) \ + do { (void)(&(var) == (type *)0); } while(0) +#endif + +#endif /* BERTOS_COMPILER_H */ diff --git a/bertos/cfg/debug.h b/bertos/cfg/debug.h new file mode 100644 index 00000000..a75b4d2d --- /dev/null +++ b/bertos/cfg/debug.h @@ -0,0 +1,313 @@ +/** + * \file + * + * + * \brief Simple debug facilities for hosted and embedded C/C++ applications. + * + * Debug output goes to stderr in hosted applications. + * Freestanding (AKA embedded) applications use \c drv/kdebug.c to output + * diagnostic messages to a serial terminal or a JTAG debugger. + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#ifndef DEVLIB_DEBUG_H +#define DEVLIB_DEBUG_H + +#include +#include + + +/* + * Defaults for rarely used config stuff. + */ +#ifndef CONFIG_KDEBUG_DISABLE_TRACE +#define CONFIG_KDEBUG_DISABLE_TRACE 0 +#endif + +#ifndef CONFIG_KDEBUG_ASSERT_NO_TEXT +#define CONFIG_KDEBUG_ASSERT_NO_TEXT 0 +#endif + +#if defined(__doxygen__) + /** + * Preprocessor symbol defined only for debug builds. + * + * The build infrastructure must arrange for _DEBUG to + * be predefined for all the source files being compiled. + * + * This is compatible with the MSVC convention for the + * default Debug and Release project targets. + */ + #define _DEBUG 1 +#endif + +#ifdef _DEBUG + + // STLport specific: enable extra checks + #define __STL_DEBUG 1 + + // MSVC specific: Enable memory allocation debug + #if defined(_MSC_VER) + #include + #endif + + /* + * On UNIX systems the extabilished practice is to define + * NDEBUG for release builds and nothing for debug builds. + */ + #ifdef NDEBUG + #undef NDEBUG + #endif + + /** + * This macro duplicates the old MSVC trick of redefining + * THIS_FILE locally to avoid the overhead of many duplicate + * strings in ASSERT(). + */ + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + /** + * This macro can be used to conditionally exclude one or more + * statements conditioned on \c _DEBUG, avoiding the clutter + * of ifdef/endif pairs. + * + * \code + * struct FooBar + * { + * int foo; + * bool bar; + * DB(int ref_count;) // Track number of users + * + * void release() + * { + * DB(--ref_count;) + * } + * }; + * \endcode + */ + #define DB(x) x + + #include /* CONFIG_KDEBUG_ASSERT_NO_TEXT */ + #include /* CPU_HARVARD */ + + /* These are implemented in drv/kdebug.c */ + void kdbg_init(void); + void kputchar(char c); + int kputnum(int num); + void kdump(const void *buf, size_t len); + void __init_wall(long *wall, int size); + + #if CPU_HARVARD + #include + void kputs_P(const char *PROGMEM str); + void kprintf_P(const char *PROGMEM fmt, ...) FORMAT(__printf__, 1, 2); + int __assert_P(const char *PROGMEM cond, const char *PROGMEM file, int line); + void __trace_P(const char *func); + void __tracemsg_P(const char *func, const char *PROGMEM fmt, ...); + int __invalid_ptr_P(void *p, const char *PROGMEM name, const char *PROGMEM file, int line); + int __check_wall_P(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line); + #define kputs(str) kputs_P(PSTR(str)) + #define kprintf(fmt, ...) kprintf_P(PSTR(fmt) ,## __VA_ARGS__) + #define __assert(cond, file, line) __assert_P(PSTR(cond), PSTR(file), (line)) + #define __trace(func) __trace_P(func) + #define __tracemsg(func, fmt, ...) __tracemsg_P(func, PSTR(fmt), ## __VA_ARGS__) + #define __invalid_ptr(p, name, file, line) __invalid_ptr_P((p), PSTR(name), PSTR(file), (line)) + #define __check_wall(wall, size, name, file, line) __check_wall_P(wall, size, PSTR(name), PSTR(file), (line)) + #else /* !CPU_HARVARD */ + void kputs(const char *str); + void kprintf(const char *fmt, ...) FORMAT(__printf__, 1, 2); + int __assert(const char *cond, const char *file, int line); + void __trace(const char *func); + void __tracemsg(const char *func, const char *fmt, ...) FORMAT(__printf__, 2, 3); + int __invalid_ptr(void *p, const char *name, const char *file, int line); + int __check_wall(long *wall, int size, const char *name, const char *file, int line); + #endif /* !CPU_HARVARD */ + + #if !CONFIG_KDEBUG_ASSERT_NO_TEXT + #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert(#x, THIS_FILE, __LINE__))) + #define ASSERT2(x, help) ((void)(LIKELY(x) ? 0 : __assert(help " (" #x ")", THIS_FILE, __LINE__))) + #else + #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert("", THIS_FILE, __LINE__))) + #define ASSERT2(x, help) ((void)ASSERT(x)) + #endif + + /** + * Check that the given pointer is either NULL or pointing to valid memory. + * + * The assumption here is that valid pointers never point to low + * memory regions. This helps catching pointers taken from + * struct/class memebers when the struct pointer was NULL. + */ + #define ASSERT_VALID_PTR(p) ((void)(LIKELY((p) >= 0x200) ? 0 : __invalid_ptr(p, #p, THIS_FILE, __LINE__))) + + /** + * Check that the given pointer is not pointing to invalid memory. + * + * \see ASSERT_VALID_PTR() + */ + #define ASSERT_VALID_PTR_OR_NULL(p) ((void)(LIKELY((p == NULL) || ((p) >= 0x200)) ? 0 : __invalid_ptr((p), #p, THIS_FILE, __LINE__))) + + #if !CONFIG_KDEBUG_DISABLE_TRACE + #define TRACE __trace(__func__) + #define TRACEMSG(msg,...) __tracemsg(__func__, msg, ## __VA_ARGS__) + #else + #define TRACE do {} while(0) + #define TRACEMSG(...) do {} while(0) + #endif + + /** + * \name Walls to detect data corruption + * \{ + */ + #define WALL_SIZE 8 + #define WALL_VALUE (long)0xABADCAFEL + #define DECLARE_WALL(name,size) long name[(size) / sizeof(long)]; + #define FWD_DECLARE_WALL(name,size) extern long name[(size) / sizeof(long)]; + #define INIT_WALL(name) __init_wall((name), countof(name)) + #define CHECK_WALL(name) __check_wall((name), countof(name), #name, THIS_FILE, __LINE__) + /*\}*/ + + /** + * Check that the given pointer actually points to an object + * of the specified type. + */ + #define ASSERT_VALID_OBJ(_t, _o) do { \ + ASSERT_VALID_PTR((_o)); \ + ASSERT(dynamic_cast<_t>((_o)) != NULL); \ + } + + /** + * \name Debug object creation and destruction. + * + * These macros help track some kinds of leaks in C++ programs. + * Usage is as follows: + * + * \code + * class Foo + * { + * DECLARE_INSTANCE_TRACKING(Foo) + * + * Foo() + * { + * NEW_INSTANCE(Foo); + * // ... + * } + * + * ~Foo() + * { + * DELETE_INSTANCE(Foo); + * // ... + * } + * }; + * + * // Put this in the implementation file of the class + * IMPLEMENT_INSTANCE_TRACKING(Foo) + * + * // Client code + * int main(void) + * { + * Foo *foo = new Foo; + * cout << GET_INSTANCE_COUNT(Foo) << endl; // prints "1" + * delete foo; + * ASSERT_ZERO_INSTANCES(Foo); // OK + * } + * \endcode + * \{ + */ + #define NEW_INSTANCE(CLASS) do { ++CLASS::__instances } while (0) + #define DELETE_INSTANCE(CLASS) do { --CLASS::__instances } while (0) + #define ASSERT_ZERO_INSTANCES(CLASS) ASSERT(CLASS::__instances == 0) + #define GET_INSTANCE_COUNT(CLASS) (CLASS::__instances) + #define DECLARE_INSTANCE_TRACKING(CLASS) static int __instances + #define IMPLEMENT_INSTANCE_TRACKING(CLASS) int CLASS::__instances = 0 + /*\}*/ + +#else /* !_DEBUG */ + + /* + * On UNIX systems the extabilished practice is to define + * NDEBUG for release builds and nothing for debug builds. + */ + #ifndef NDEBUG + #define NDEBUG 1 + #endif + + #define DB(x) /* nothing */ + #ifndef ASSERT + #define ASSERT(x) ((void)0) + #endif /* ASSERT */ + #define ASSERT2(x, help) ((void)0) + #define ASSERT_VALID_PTR(p) ((void)0) + #define ASSERT_VALID_PTR_OR_NULL(p) ((void)0) + #define ASSERT_VALID_OBJ(_t, _o) ((void)0) + #define TRACE do {} while (0) + #if COMPILER_VARIADIC_MACROS + #define TRACEMSG(x, ...) do {} while (0) + #else + INLINE void TRACEMSG(UNUSED_ARG(const char *, msg), ...) + { + /* NOP */ + } + #endif + + #define DECLARE_WALL(name, size) /* nothing */ + #define FWD_DECLARE_WALL(name, size) /* nothing */ + #define INIT_WALL(name) do {} while (0) + #define CHECK_WALL(name) do {} while (0) + + #define NEW_INSTANCE(CLASS) do {} while (0) + #define DELETE_INSTANCE(CLASS) do {} while (0) + #define ASSERT_ZERO_INSTANCES(CLASS) do {} while (0) + #define GET_INSTANCE_COUNT(CLASS) ERROR_ONLY_FOR_DEBUG + #define DECLARE_INSTANCE_TRACKING(CLASS) + #define IMPLEMENT_INSTANCE_TRACKING(CLASS) + + INLINE void kdbg_init(void) { /* nop */ } + INLINE void kputchar(UNUSED_ARG(char, c)) { /* nop */ } + INLINE int kputnum(UNUSED_ARG(int, num)) { return 0; } + INLINE void kputs(UNUSED_ARG(const char *, str)) { /* nop */ } + INLINE void kdump(UNUSED_ARG(const void *, buf), UNUSED_ARG(size_t, len)) { /* nop */ } + + #if defined(__cplusplus) && COMPILER_VARIADIC_MACROS + /* G++ can't inline functions with variable arguments... */ + #define kprintf(fmt,...) do { (void)(fmt); } while(0) + #else + /* ...but GCC can. */ + INLINE void kprintf(UNUSED_ARG(const char *, fmt), ...) { /* nop */ } + #endif + +#endif /* _DEBUG */ + +#endif /* DEVLIB_DEBUG_H */ diff --git a/bertos/cfg/macros.h b/bertos/cfg/macros.h new file mode 100644 index 00000000..1006fc42 --- /dev/null +++ b/bertos/cfg/macros.h @@ -0,0 +1,336 @@ +/** + * \file + * + * + * \brief Common and handy function macros + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Giovanni Bajo + */ +#ifndef CFG_MACROS_H +#define CFG_MACROS_H + +#include + +/* avr-gcc does not seem to support libstdc++ */ +#if defined(__cplusplus) && !CPU_AVR + /* Type-generic macros implemented with template functions. */ + #include + + template inline T ABS(T n) { return n >= 0 ? n : -n; } + #define MIN(a,b) std::min(a, b) + #define MAX(a,b) std::max(a, b) + #define SWAP(a,b) std::swap(a, b) +#elif (COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) + /* Type-generic macros implemented with statement expressions. */ + #define ABS(n) ({ \ + typeof(n) _n = (n); \ + (_n < 0) ? -_n : _n; \ + }) + #define MIN(a,b) ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + ASSERT_TYPE_EQUAL(_a, _b); \ + /** \ + * The (typeof(_a)) cast in necessary: \ + * result type of conditional expressions is \ + * *NOT* the type of the value returned but \ + * the type that would be produced if _a and _b \ + * were mixed in an expression. \ + * Even in _a and _b are of the same type, \ + * if mixed in an expression the type will be \ + * promoted to int! \ + */ \ + ((typeof(_a))((_a < _b) ? _a : _b)); \ + }) + #define MAX(a,b) ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + ASSERT_TYPE_EQUAL(_a, _b); \ + /** \ + * The (typeof(_a)) cast in necessary: \ + * result type of conditional expressions is \ + * *NOT* the type of the value returned but \ + * the type that would be produced if _a and _b \ + * were mixed in an expression. \ + * Even in _a and _b are of the same type, \ + * if mixed in an expression the type will be \ + * promoted to int! \ + */ \ + ((typeof(_a))((_a > _b) ? _a : _b)); \ + }) +#else /* !(COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) */ + /* Buggy macros for inferior compilers. */ + #define ABS(a) (((a) < 0) ? -(a) : (a)) + #define MIN(a,b) (((a) < (b)) ? (a) : (b)) + #define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* !(COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) */ + +/** Bound \a x between \a min and \a max. */ +#define MINMAX(min,x,max) (MIN(MAX(min, x), max)) + +#ifdef __cplusplus + /* Use standard implementation from */ + #define SWAP(a,b) std::swap(a, b) +#elif COMPILER_TYPEOF + /** + * Type-generic macro to swap \a a with \a b. + * + * \note Arguments are evaluated multiple times. + */ + #define SWAP(a, b) \ + do { \ + typeof(a) tmp; \ + ASSERT_TYPE_EQUAL(a, b); \ + tmp = (a); \ + (a) = (b); \ + (b) = tmp; \ + } while (0) +#else /* !COMPILER_TYPEOF */ + /* Sub-optimal implementation that only works with integral types. */ + #define SWAP(a, b) \ + do { \ + (a) ^= (b); \ + (b) ^= (a); \ + (a) ^= (b); \ + } while (0) + +#endif /* COMPILER_TYPEOF */ + +/** + * Macro to swap \a a with \a b, with explicit type \a T for dumb C89 compilers. + * + * \note Arguments are evaluated multiple times. + */ +#define SWAP_T(a, b, T) \ + do { \ + T tmp; \ + ASSERT_TYPE_IS(a, T); \ + ASSERT_TYPE_IS(b, T); \ + tmp = (a); \ + (a) = (b); \ + (b) = tmp; \ + } while (0) + + +#ifndef BV + /** Convert a bit value to a binary flag. */ + #define BV(x) (1<<(x)) +#endif + +/** Same as BV() but with 32 bit result */ +#define BV32(x) ((uint32_t)1<<(x)) + +/** Same as BV() but with 16 bit result */ +#define BV16(x) ((uint16_t)1<<(x)) + +/** Same as BV() but with 8 bit result */ +#define BV8(x) ((uint8_t)1<<(x)) + +/** + * Perform an integer division rounding the result to the nearest int value. + * \note \a divisor should preferibly be a costant, otherwise this macro generates + * 2 division. Also divisor is evaluated twice. + */ +#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor)) + +/** Round up \a x to an even multiple of the 2's power \a pad. */ +#define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1)) + +/* OBSOLETE */ +#define ROUND2 ROUND_UP2 + +/** + * \name Integer round macros. + * + * Round \a x to a multiple of \a base. + * \note If \a x is signed these macros generate a lot of code. + * \{ + */ +#define ROUND_DOWN(x, base) ( (x) - ((x) % (base)) ) +#define ROUND_UP(x, base) ( ((x) + (base) - 1) - (((x) + (base) - 1) % (base)) ) +#define ROUND_NEAREST(x, base) ( ((x) + (base) / 2) - (((x) + (base) / 2) % (base)) ) +/* \} */ + +/** Check if \a x is an integer power of 2. */ +#define IS_POW2(x) (!(bool)((x) & ((x)-1))) + +/** Calculate a compile-time log2 for a uint8_t */ +#define UINT8_LOG2(x) \ + ((x) < 2 ? 0 : \ + ((x) < 4 ? 1 : \ + ((x) < 8 ? 2 : \ + ((x) < 16 ? 3 : \ + ((x) < 32 ? 4 : \ + ((x) < 64 ? 5 : \ + ((x) < 128 ? 6 : 7))))))) + +/** Calculate a compile-time log2 for a uint16_t */ +#define UINT16_LOG2(x) \ + ((x < 256) ? UINT8_LOG2(x) : UINT8_LOG2((x) >> 8) + 8) + +/** Calculate a compile-time log2 for a uint32_t */ +#define UINT32_LOG2(x) \ + ((x < 65536UL) ? UINT16_LOG2(x) : UINT16_LOG2((x) >> 16) + 16) + +#if COMPILER_VARIADIC_MACROS + /** Count the number of arguments (up to 16). */ + #define PP_COUNT(...) \ + PP_COUNT__(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) + #define PP_COUNT__(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,count,...) \ + count +#endif + +#if COMPILER_VARIADIC_MACROS + /** + * \def BIT_CHANGE(reg, (mask, value), ...) + * + * This macro allows for efficient and compact bit toggling in a hardware + * register. It is meant to replace hand-coded cruft which toggles bits + * in sequence. + * + * It is possible to specify an unlimited pair of (mask, value) parameters. + * For instance: + * + * \code + * void set_timer(bool start) + * { + * BIT_CHANGE(REG_CTRL_TIMER, + * (TIMER_MODE, MODE_COUNT), + * (OVL_IRQ, 1), + * (CMP_IRQ, 1), + * (START, start) + * ); + * } + * \endcode + * + * The macro expansion will be roughly the following: + * + * \code + * REG_CTRL_TIMER = (REG_CTRL_TIMER & ~(TIMER_MODE|OVL_IRQ|CMP_IRQ|START) + * | (MODE_COUNT|OVL_IRQ|CMP_IRQ|(start ? START : 0)); + * \endcode + * + * It is up to the compiler to produce the optimal code. We checked that GCC produces + * the best code in most cases. We preferred this expansion over the use of a block + * with a local variable because CodeWarrior 6.1 was not able to remove completely the + * allocation of the local from the stack. + * + * \note This macro is available only in C99 because it makes use of variadic macros. + * It would be possible to make up an implementation with a slightly different syntax + * for use with C90 compilers, through Boost Preprocessor. + */ + + /** + * \def BIT_CHANGE_BV(reg, (bit, value), ...) + * + * Similar to BIT_CHANGE(), but get bits instead of masks (and applies BV() to convert + * them to masks). + */ + + #define BIT_EXTRACT_FLAG_0(bit, value) bit + #define BIT_EXTRACT_FLAG_1(bit, value) BV(bit) + #define BIT_EXTRACT_VALUE__(bit, value) value + + #define BIT_MASK_SINGLE__(use_bv, index, max, arg) \ + ((index < max) ? (PP_CAT(BIT_EXTRACT_FLAG_, use_bv) arg) : 0) \ + /**/ + + #define BIT_MASK_IF_SINGLE__(use_bv, index, max, arg) \ + (((index < max) && (BIT_EXTRACT_VALUE__ arg)) ? (PP_CAT(BIT_EXTRACT_FLAG_, use_bv) arg) : 0) \ + /**/ + + #define BIT_ITER__2(macro, use_bv, max, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, ...) \ + (macro(use_bv, 0, max, a0) | \ + macro(use_bv, 1, max, a1) | \ + macro(use_bv, 2, max, a2) | \ + macro(use_bv, 3, max, a3) | \ + macro(use_bv, 4, max, a4) | \ + macro(use_bv, 5, max, a5) | \ + macro(use_bv, 6, max, a6) | \ + macro(use_bv, 7, max, a7) | \ + macro(use_bv, 8, max, a8) | \ + macro(use_bv, 9, max, a9) | \ + macro(use_bv, 10, max, a10) | \ + macro(use_bv, 11, max, a11) | \ + macro(use_bv, 12, max, a12) | \ + macro(use_bv, 13, max, a13) | \ + macro(use_bv, 14, max, a14) | \ + macro(use_bv, 15, max, a15)) \ + /**/ + + #define BIT_ITER__(macro, use_bv, ...) \ + BIT_ITER__2(macro, use_bv, PP_COUNT(__VA_ARGS__), __VA_ARGS__, (0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1)) \ + /**/ + + #define BIT_MASKS__(use_bv, ...) \ + BIT_ITER__(BIT_MASK_SINGLE__, use_bv, __VA_ARGS__) + /**/ + + #define BIT_MASKS_CONDITIONAL__(use_bv, ...) \ + BIT_ITER__(BIT_MASK_IF_SINGLE__, use_bv, __VA_ARGS__) + /**/ + + #define BIT_CHANGE__(reg, use_bv, ...) \ + ((reg) = ((reg) & ~BIT_MASKS__(use_bv, __VA_ARGS__)) | BIT_MASKS_CONDITIONAL__(use_bv, __VA_ARGS__)) \ + /**/ + + #define BIT_CHANGE(reg, ...) BIT_CHANGE__(reg, 0, __VA_ARGS__) + #define BIT_CHANGE_BV(reg, ...) BIT_CHANGE__(reg, 1, __VA_ARGS__) + +#endif /* COMPILER_VARIADIC_MACROS */ + +/** + * Macro for rotating bit left or right. + * \{ + */ +#define ROTR(var, rot) (((var) >> (rot)) | ((var) << ((sizeof(var) * 8) - (rot)))) +#define ROTL(var, rot) (((var) << (rot)) | ((var) >> ((sizeof(var) * 8) - (rot)))) +/*\}*/ + +/** + * Make an id from 4 letters, useful for + * file formats and kfile ids. + */ +#define MAKE_ID(a,b,c,d) \ + ( ((uint32_t)(a) << 24) \ + | ((uint32_t)(b) << 16) \ + | ((uint32_t)(c) << 8) \ + | ((uint32_t)(d) << 0) ) + +/** + * Type for id generated by MAKE_ID(). + */ +typedef uint32_t id_t; + +#endif /* MACROS_H */ + diff --git a/bertos/cfg/module.h b/bertos/cfg/module.h new file mode 100644 index 00000000..8ada81a1 --- /dev/null +++ b/bertos/cfg/module.h @@ -0,0 +1,124 @@ +/** + * \file + * + * + * \brief Debug macros for inter-module dependency checking. + * + * These macros expand to nothing in release builds. In debug + * builds, they perform run-time dependency checks for modules. + * + * The usage pattern looks like this: + * + * \code + * MOD_DEFINE(phaser) + * + * void phaser_init(void) + * { + * MOD_CHECK(computer); + * MOD_CHECK(warp_core); + * + * [...charge weapons...] + * + * MOD_INIT(phaser); + * } + * + * void phaser_cleanup(void) + * { + * MOD_CLEANUP(phaser); + * + * [...disarm phaser...] + * } + * \endcode + * + * \version $Id$ + * \author Bernardo Innocenti + */ +#ifndef CFG_MODULE_H +#define CFG_MODULE_H + +#include + +/** + * Declare a global variable for module dependency check. + * + * \see MOD_INIT(), MOD_CHECK() + */ +#define MOD_DEFINE(module) DB(extern bool module ## _initialized; bool module ## _initialized;) + +/** + * Check that \a module was already initialized. + * + * Put this check just before accessing any facility + * provided by a module that requires prior initialization. + * + * \see MOD_INIT() + */ + +#define MOD_CHECK(module) \ +do { \ + DB(extern bool module ## _initialized;) \ + ASSERT(module ## _initialized); \ +} while (0) + +/** + * Mark module as initialized. + * + * Marking initialization requires the global data + * previously defined by MOD_DEFINE(). + * + * To prevent double initialization bugs, an initialized + * module must first be cleaned up with MOD_CLEANUP() before + * calling MOD_INIT() another time. + * + * \see MOD_CLEANUP(), MOD_CHECK(), MOD_DEFINE() + */ +#define MOD_INIT(module) \ +do { \ + ASSERT(!module ## _initialized); \ + DB(module ## _initialized = true;) \ +} while (0) + +/** + * Mark module as being no longer initialized. + * + * Marking initialization requires the global data + * previously defined by MOD_DEFINE(). + * + * \see MOD_INIT(), MOD_CHECK(), MOD_DEFINE() + */ +#define MOD_CLEANUP(module) \ +do { \ + ASSERT(module ## _initialized); \ + DB(module ## _initialized = false;) \ +} while (0) + +#endif /* CFG_MODULE_H */ + diff --git a/bertos/cfg/os.h b/bertos/cfg/os.h new file mode 100644 index 00000000..924daade --- /dev/null +++ b/bertos/cfg/os.h @@ -0,0 +1,172 @@ +/** + * \file + * + * + * \brief OS-specific definitions + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#ifndef DEVLIB_OS_H +#define DEVLIB_OS_H + +/** Macro to include OS-specific versions of the headers. */ +#define OS_HEADER(module) PP_STRINGIZE(PP_CAT3(module, _, OS_ID).h) +#define OS_CSOURCE(module) PP_STRINGIZE(PP_CAT3(module, _, OS_ID).c) + +/* + * OS autodetection (Some systems trigger multiple OS definitions) + */ +#ifdef _WIN32 + #define OS_WIN32 1 + #define OS_ID win32 + + // FIXME: Maybe disable Win32 exceptions? + typedef int cpuflags_t; + #define IRQ_DISABLE /* FIXME */ + #define IRQ_ENABLE /* FIXME */ + #define IRQ_SAVE_DISABLE(old_sigs) /* FIXME */ + #define IRQ_RESTORE(old_sigs) /* FIXME */ + +#else + #define OS_WIN32 0 +#endif + +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + #define OS_UNIX 1 + #define OS_POSIX 1 /* Not strictly UNIX, but no way to autodetect it. */ + #define OS_ID posix + + /* + * The POSIX moral equivalent of disabling IRQs is disabling signals. + */ + #include + typedef sigset_t cpuflags_t; + + #define SET_ALL_SIGNALS(sigs) \ + do { \ + sigfillset(&sigs); \ + sigdelset(&sigs, SIGINT); \ + sigdelset(&sigs, SIGSTOP); \ + sigdelset(&sigs, SIGCONT); \ + } while(0) + + #define IRQ_DISABLE \ + do { \ + sigset_t sigs; \ + SET_ALL_SIGNALS(sigs); \ + sigprocmask(SIG_BLOCK, &sigs, NULL); \ + } while (0) + + #define IRQ_ENABLE \ + do { \ + sigset_t sigs; \ + SET_ALL_SIGNALS(sigs); \ + sigprocmask(SIG_UNBLOCK, &sigs, NULL); \ + } while (0) + + #define IRQ_SAVE_DISABLE(old_sigs) \ + do { \ + sigset_t sigs; \ + SET_ALL_SIGNALS(sigs); \ + sigprocmask(SIG_BLOCK, &sigs, &old_sigs); \ + } while (0) + + #define IRQ_RESTORE(old_sigs) \ + do { \ + sigprocmask(SIG_SETMASK, &old_sigs, NULL); \ + } while (0) + + #define IRQ_ENABLED() \ + ({ \ + sigset_t sigs; \ + sigprocmask(SIG_SETMASK, NULL, &sigs); \ + sigismember(&sigs, SIGALRM) ? false : true; \ + }) + +#else + #define OS_UNIX 0 + #define OS_POSIX 0 +#endif + +#ifdef __linux__ + #define OS_LINUX 1 +#else + #define OS_LINUX 0 +#endif + +#if defined(__APPLE__) && defined(__MACH__) + #define OS_DARWIN 1 +#else + #define OS_DARWIN 0 +#endif + +/* + * We want Qt and other frameworks to look like OSes because you would + * tipically want their portable abstractions if you're using one of these. + */ +#if defined(_QT) + #define OS_QT 1 + #undef OS_ID + #define OS_ID qt +#else + #define OS_QT 0 +#endif + +/* + * Summarize hosted environments as OS_HOSTED and embedded + * environment with OS_EMBEDDED. + */ +#if OS_WIN32 || OS_UNIX || OS_DARWIN || OS_QT + #define OS_HOSTED 1 + #define OS_EMBEDDED 0 +#else + #define OS_HOSTED 0 + #define OS_EMBEDDED 1 + + /* Embedded environments fall back to CPU-specific code. */ + #define OS_ID CPU_ID +#endif + +/* Self-check for the detection */ +#if !defined(OS_ID) + #error OS_ID not defined +#endif +#if OS_HOSTED && OS_EMBEDDED + #error Both hosted and embedded OS environment +#endif +#if !OS_HOSTED && !OS_EMBEDDED + #error Neither hosted nor embedded OS environment +#endif + +#endif /* DEVLIB_OS_H */ diff --git a/bertos/config.mk b/bertos/config.mk new file mode 100644 index 00000000..cfe8ca6e --- /dev/null +++ b/bertos/config.mk @@ -0,0 +1,122 @@ +# +# $Id$ +# Copyright 2002,2003, 2004, 2006 Develer S.r.l. (http://www.develer.com/) +# All rights reserved. +# +# Author: Bernardo Innocenti +# Based on: GCC-AVR standard Makefile part 1, Volker Oth 1/2000 +# + +# +# Programmer type +# see local pgm_config.mk for programmer customization. +-include pgm_config.mk +DPROG ?= -V -c stk500 -P /dev/ttyS0 + +# Set to 1 to build for embedded devices. +# e.g. produce target.elf instead of target and target_nostrip +EMBEDDED_TARGET = 1 +#EMBEDDED_TARGET = 0 + +OPTCFLAGS = -ffunction-sections -fdata-sections +#OPTCFLAGS = -funsafe-loop-optimizations + +# For AVRStudio +#DEBUGCFLAGS = -gdwarf-2 + +# For GDB +DEBUGCFLAGS = -ggdb + +# +# define some variables based on the AVR base path in $(AVR) +# +#CROSS = avr- +CC = gcc +CXX = g++ +AS = $(CC) -x assembler-with-cpp +LD = $(CC) +LDXX = $(CXX) +OBJCOPY = objcopy +STRIP = strip +INSTALL = cp -a +RM = rm -f +RM_R = rm -rf +RN = mv +MKDIR_P = mkdir -p +SHELL = /bin/sh +CHECKER = sparse +DOXYGEN = doxygen +AVRDUDE = avrdude +MOC = moc-qt4 +FLEXCAT = $(top_srcdir)/tools/flexcat/flexcat + +# For conversion from ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) \ + --debugging \ + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 + +INCDIR = -I. -Ibertos -Ibertos/hw +LIBDIR = lib +OBJDIR = obj +OUTDIR = images + +# output format can be srec, ihex (avrobj is always created) +FORMAT = srec +#FORMAT = ihex + +# Compiler flags for generating dependencies +DEP_FLAGS = -MMD -MP + +# Compiler flags for generating source listings +LIST_FLAGS = -Wa,-anhlmsd=$(@:.o=.lst) + +# Linker flags for generating map files +ifeq ($(EMBEDDED_TARGET), 1) +MAP_FLAGS = -Wl,-Map=$(@:%.elf=%.map),--cref +else +MAP_FLAGS = +endif + +# Compiler warning flags for both C and C++ +WARNFLAGS = \ + -W -Wformat -Wall -Wundef -Wpointer-arith -Wcast-qual \ + -Wcast-align -Wwrite-strings -Wsign-compare \ + -Wmissing-noreturn \ + -Wextra -Wstrict-aliasing=2 \ +# -Wunsafe-loop-optimizations + +# Compiler warning flags for C only +C_WARNFLAGS = \ + -Wmissing-prototypes -Wstrict-prototypes + +# Default C preprocessor flags (for C, C++ and cpp+as) +CPPFLAGS = $(INCDIR) + +# Default C compiler flags +CFLAGS = $(OPTCFLAGS) $(DEBUGCFLAGS) $(WARNFLAGS) $(C_WARNFLAGS) \ + $(DEP_FLAGS) $(LIST_FLAGS) -std=gnu99 + +# Default C++ compiler flags +CXXFLAGS = $(OPTCFLAGS) $(DEBUGCFLAGS) $(WARNFLAGS) \ + $(DEP_FLAGS) $(LIST_FLAGS) + +# Default compiler assembly flags +CPPAFLAGS = $(DEBUGCFLAGS) -MMD + +# Default assembler flags +ASFLAGS = $(DEBUGCFLAGS) + +# Default linker flags +#LDFLAGS = $(MAP_FLAGS) + +#bernie: does not complain for missing symbols! +LDFLAGS = $(MAP_FLAGS) -Wl,--gc-sections + +# Flags for avrdude +AVRDUDEFLAGS = $(DPROG) + +# additional libs +LIB = -lm diff --git a/bertos/config_kern.h b/bertos/config_kern.h new file mode 100644 index 00000000..c703b4de --- /dev/null +++ b/bertos/config_kern.h @@ -0,0 +1,155 @@ +/** + * \file + * + * + * \brief Kernel configuration parameters + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.8 2006/07/19 12:56:24 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.7 2006/02/21 16:05:53 bernie + *#* Move from cfg/ to top-level. + *#* + *#* Revision 1.3 2005/11/04 16:20:01 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.2 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.1 2005/04/11 19:04:13 bernie + *#* Move top-level headers to cfg/ subdir. + *#* + *#* Revision 1.5 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.4 2004/08/24 16:19:38 bernie + *#* Add missing header. + *#* + *#* Revision 1.3 2004/07/30 14:24:16 rasky + *#* Task switching con salvataggio perfetto stato di interrupt (SR) + *#* Kernel monitor per dump informazioni su stack dei processi + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 17:48:35 bernie + *#* Add top-level files. + *#* + *#*/ +#ifndef CONFIG_KERN_H +#define CONFIG_KERN_H + +#include /* ARCH_EMUL */ + +/** + * \name Modules activation + * + * \{ + */ +/* Module/option Active Dependencies */ +#define CONFIG_KERN_SCHED (1) +#define CONFIG_KERN_SIGNALS (1 && CONFIG_KERN_SCHED) +#define CONFIG_KERN_TIMER (1) +#define CONFIG_KERN_HEAP (0) +#define CONFIG_KERN_SEMAPHORES (0 && CONFIG_KERN_SIGNALS) +#define CONFIG_KERN_MONITOR (1 && CONFIG_KERN_SCHED) +/*\}*/ + +/* EXPERIMENTAL */ +#define CONFIG_KERN_PREEMPTIVE (0 && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER) + +#define CONFIG_KERN_QUANTUM 50 /**< Time sharing quantum in timer ticks. */ + +#if (ARCH & ARCH_EMUL) + /* We need a large stack because system libraries are bloated */ + #define CONFIG_PROC_DEFSTACKSIZE 65536 +#else + /** + * Default stack size for each thread, in bytes. + * + * The goal here is to allow a minimal task to save all of its + * registers twice, plus push a maximum of 32 variables on the + * stack. + * + * The actual size computed by the default formula is: + * AVR: 102 + * i386: 156 + * ARM: 164 + * x86_64: 184 + * + * Note that on most 16bit architectures, interrupts will also + * run on the stack of the currently running process. Nested + * interrupts will greatly increases the amount of stack space + * required per process. Use irqmanager to minimize stack + * usage. + */ + #define CONFIG_PROC_DEFSTACKSIZE \ + (CPU_SAVED_REGS_CNT * 2 * sizeof(cpustack_t) \ + + 32 * sizeof(int)) +#endif + +/* OBSOLETE */ +#define CONFIG_KERN_DEFSTACKSIZE CONFIG_PROC_DEFSTACKSIZE + +/* Memory fill codes to help debugging */ +#if CONFIG_KERN_MONITOR + #include + #if (SIZEOF_CPUSTACK_T == 1) + /* 8bit cpustack_t */ + #define CONFIG_KERN_STACKFILLCODE 0xA5 + #define CONFIG_KERN_MEMFILLCODE 0xDB + #elif (SIZEOF_CPUSTACK_T == 2) + /* 16bit cpustack_t */ + #define CONFIG_KERN_STACKFILLCODE 0xA5A5 + #define CONFIG_KERN_MEMFILLCODE 0xDBDB + #elif (SIZEOF_CPUSTACK_T == 4) + /* 16bit cpustack_t */ + #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5UL + #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBUL + #elif (SIZEOF_CPUSTACK_T == 8) + /* 16bit cpustack_t */ + #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5A5A5A5A5UL + #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBDBDBDBDBUL + #else + #error No cpustack_t size supported! + #endif +#endif + + +#endif /* CONFIG_KERN_H */ diff --git a/bertos/doc/TracFooter.html b/bertos/doc/TracFooter.html new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/bertos/doc/TracFooter.html @@ -0,0 +1,2 @@ + + diff --git a/bertos/doc/TracHeader.html b/bertos/doc/TracHeader.html new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/bertos/doc/TracHeader.html @@ -0,0 +1,2 @@ + + diff --git a/bertos/drv/adc.c b/bertos/drv/adc.c new file mode 100644 index 00000000..7fbf7f2c --- /dev/null +++ b/bertos/drv/adc.c @@ -0,0 +1,75 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief ADC driver (implementation) + * + * \version $Id$ + * \author Francesco Sacchi + */ + + +#include +#include + +#include CPU_CSOURCE(adc) + +#include // ASSERT() +#include // MIN() +#include +#include + +/** + * Read the ADC channel \a ch. + */ +adcread_t adc_read(adc_ch_t ch) +{ + ASSERT(ch <= (adc_ch_t)ADC_MUX_MAXCH); + ch = MIN(ch, (adc_ch_t)ADC_MUX_MAXCH); + + adc_hw_select_ch(ch); + + return(adc_hw_read()); +} + +MOD_DEFINE(adc); + +/** + * Initialize the ADC hardware. + */ +void adc_init(void) +{ + adc_hw_init(); + + MOD_INIT(adc); +} diff --git a/bertos/drv/adc.h b/bertos/drv/adc.h new file mode 100644 index 00000000..91f1ebd6 --- /dev/null +++ b/bertos/drv/adc.h @@ -0,0 +1,69 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief ADC driver (interface) + * + * \version $Id$ + * \author Francesco Sacchi + */ + + +#ifndef DRV_ADC_H +#define DRV_ADC_H + +#include +#include +#include +#include CPU_HEADER(adc) + +/** Type for ADC return value. */ +typedef uint16_t adcread_t; + +/** Type for channel */ +typedef uint8_t adc_ch_t; + +#define adc_bits() ADC_BITS + +adcread_t adc_read(adc_ch_t ch); +void adc_init(void); + +/** + * Macro used to convert data from adc range (0...(2 ^ADC_BITS - 1)) to + * \a y1 ... \a y2 range. + * \note \a y1, \a y2 can be negative, and put in ascending or descending order as well. + * \note \a data and \a y2 are evaluated only once, \a y1 twice. + */ +#define ADC_RANGECONV(data, y1, y2) ((((data) * ((y2) - (y1))) / ((1 << ADC_BITS) - 1)) + (y1)) + +#endif /* DRV_ADC_H */ diff --git a/bertos/drv/buzzer.c b/bertos/drv/buzzer.c new file mode 100644 index 00000000..63cbc4a8 --- /dev/null +++ b/bertos/drv/buzzer.c @@ -0,0 +1,197 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Buzzer driver (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.19 2006/07/19 12:56:25 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.18 2006/02/17 21:15:25 bernie + *#* Add MOD_CHECK() checks. + *#* + *#* Revision 1.17 2006/02/10 12:30:18 bernie + *#* Push interrupt protection inside hw module. + *#* + *#* Revision 1.16 2005/11/04 16:19:33 bernie + *#* buz_init(): Restore IRQ protection as in project_bko. + *#* + *#* Revision 1.15 2005/06/27 21:25:50 bernie + *#* Modularize hardware access; Port to new timer interface. + *#* + *#* Revision 1.14 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.13 2005/02/18 11:20:15 bernie + *#* Use mware/event.h; Update copyright info. + *#* + *#* Revision 1.12 2004/12/13 12:07:06 bernie + *#* DISABLE_IRQSAVE/ENABLE_IRQRESTORE: Convert to IRQ_SAVE_DISABLE/IRQ_RESTORE. + *#* + *#* Revision 1.11 2004/12/08 09:11:53 bernie + *#* Rename time_t to mtime_t. + *#* + *#* Revision 1.10 2004/10/03 18:38:51 bernie + *#* Add missing AVR header; Fix header. + *#* + *#* Revision 1.9 2004/09/14 21:01:25 bernie + *#* Use new AVR port pin names. + *#*/ + +#include "buzzer.h" + +#include +#include + +#include + +#include +#include + + +/* Local vars */ +static Timer buz_timer; +static bool buz_timer_running; +static mtime_t buz_repeat_interval; +static mtime_t buz_repeat_duration; + + +/** + * Turn off buzzer, called by software timer + */ +static void buz_softint(void) +{ + if (IS_BUZZER_ON) + { + BUZZER_OFF; + if (buz_repeat_interval) + { + /* Wait for interval time */ + timer_setDelay(&buz_timer, ms_to_ticks(buz_repeat_interval)); + timer_add(&buz_timer); + } + else + buz_timer_running = false; + } + else if (buz_repeat_interval) + { + /* Wait for beep time */ + BUZZER_ON; + timer_setDelay(&buz_timer, ms_to_ticks(buz_repeat_duration)); + timer_add(&buz_timer); + } + else + buz_timer_running = false; +} + + +/** + * Beep for the specified ms time + */ +void buz_beep(mtime_t time) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + /* Remove the software interrupt if it was already queued */ + if (buz_timer_running) + timer_abort(&buz_timer); + + /* Turn on buzzer */ + BUZZER_ON; + + /* Add software interrupt to turn the buzzer off later */ + buz_timer_running = true; + timer_setDelay(&buz_timer, ms_to_ticks(time)); + timer_add(&buz_timer); + + IRQ_RESTORE(flags); +} + + +/** + * Start buzzer repetition + */ +void buz_repeat_start(mtime_t duration, mtime_t interval) +{ + buz_repeat_interval = interval; + buz_repeat_duration = duration; + buz_beep(duration); +} + + +/** + * Stop buzzer repetition + */ +void buz_repeat_stop(void) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + /* Remove the software interrupt if it was already queued */ + if (buz_timer_running) + { + timer_abort(&buz_timer); + buz_timer_running = false; + } + + buz_repeat_interval = 0; + BUZZER_OFF; + + IRQ_RESTORE(flags); +} + +MOD_DEFINE(buzzer) + +/** + * Initialize buzzer. + */ +void buz_init(void) +{ + MOD_CHECK(timer); + + BUZZER_HW_INIT; + + /* Init software interrupt. */ + timer_set_event_softint(&buz_timer, (Hook)buz_softint, 0); + + MOD_INIT(buzzer); +} diff --git a/bertos/drv/buzzer.h b/bertos/drv/buzzer.h new file mode 100644 index 00000000..7d8837c1 --- /dev/null +++ b/bertos/drv/buzzer.h @@ -0,0 +1,81 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Buzzer driver + */ + +/*#* + *#* $Log$ + *#* Revision 1.10 2006/07/19 12:56:25 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.9 2005/11/27 23:32:15 bernie + *#* Update copyright information. + *#* + *#* Revision 1.8 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.7 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.6 2004/12/08 09:11:53 bernie + *#* Rename time_t to mtime_t. + *#* + *#* Revision 1.5 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.4 2004/08/24 16:53:43 bernie + *#* Add missing headers. + *#* + *#* Revision 1.3 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.2 2004/05/23 18:21:53 bernie + *#* Trim CVS logs and cleanup header info. + *#* + *#*/ +#ifndef DRV_BUZZER_H +#define DRV_BUZZER_H + +#include + +extern void buz_init(void); +extern void buz_beep(mtime_t time); +extern void buz_repeat_start(mtime_t duration, mtime_t interval); +extern void buz_repeat_stop(void); + +#endif /* DRV_BUZZER_H */ diff --git a/bertos/drv/buzzerled.c b/bertos/drv/buzzerled.c new file mode 100644 index 00000000..7ce6f53c --- /dev/null +++ b/bertos/drv/buzzerled.c @@ -0,0 +1,123 @@ +/** + * \file + * + * + * \brief Generic library to handle buzzers and leds + * + * This library is divided into three different layers: + * + * - The topmost portable layer is buzzerled.[ch] which exposes a common API + * enable/disable the devices. Basically, it handles the asynchronism to + * implement bld_beep and bld_repeat. + * - The middle layer is CPU-specific and exposes a single main function which + * turns on/off each device. + * - The lower layer is board-specific and communicates with the middle layer + * with any required API. The idea is that devices can be tied to the CPU in + * many different ways (many different pins), so this part should describe + * which devices are present, and how they are connected. + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:25 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.5 2004/12/08 09:43:41 bernie + *#* Add a todo item. + *#* + *#* Revision 1.4 2004/08/25 14:12:08 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.3 2004/07/14 14:04:29 rasky + *#* Merge da SC: spostata bld_set inline perché si ottimizza parecchio tramite propagazione di costanti + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 18:36:05 bernie + *#* Import buzzerled driver. + *#* + *#*/ + +#include "buzzerled.h" +#include "timer.h" + +static struct Timer timers[NUM_BLDS]; +static bool timer_go[NUM_BLDS]; + +INLINE enum BLD_DEVICE hook_parm_to_device(void* parm) +{ + struct Timer* t = (struct Timer*)parm; + int num_bld = t - &timers[0]; + + ASSERT(num_bld >= 0); + ASSERT(num_bld < NUM_BLDS); + + return (enum BLD_DEVICE)num_bld; +} + +static void hook_turn_off(void* parm) +{ + enum BLD_DEVICE num_bld = hook_parm_to_device(parm); + bld_set(num_bld, false); +} + +void bld_init(void) +{ + bld_hw_init(); +} + +void bld_beep(enum BLD_DEVICE device, uint16_t duration) +{ + // \todo This is not reentrant for the same device. FIXME! + struct Timer *t = &timers[device]; + timer_set_delay(t, duration); + timer_set_event_softint(t, hook_turn_off, t); + timer_add(t); + + bld_set(device, true); +} + +void bld_beep_and_wait(enum BLD_DEVICE device, uint16_t duration) +{ + bld_set(device, true); + timer_delay(duration); + bld_set(device, false); +} + diff --git a/bertos/drv/buzzerled.h b/bertos/drv/buzzerled.h new file mode 100644 index 00000000..14fab030 --- /dev/null +++ b/bertos/drv/buzzerled.h @@ -0,0 +1,94 @@ +/** + * \file + * + * + * \brief Generic library to handle buzzers and leds + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +#ifndef DRV_BUZZERLED_H +#define DRV_BUZZERLED_H + +#include + +/** Include hw.h. We expect hw.h to define enum BLD_DEVICE, which must contain + * an enumarator for each device, plus a special symbol NUM_BLDS containing the + * number of devices. + */ +#include + + +/* Include hw-level implementation. This allows inlining of bld_set, which in turns + * should allow fast constant propagation for the common case (where the parameter + * device is a constant). + */ +#include CPU_HEADER(buzzerled) + + +/** Initialize the buzzerled library. + * + * \note This function must be called before any other function in the library. + */ +void bld_init(void); + + +/** Set or reset a device. + * + * \param device Device to be set + * \param enable Enable/disable status + */ +#define bld_set(device, enable) bld_hw_set(device, enable) + + +/** Enable a device for a certain interval of time + * + * \param device Device to be enabled + * \param duration Number of milliseconds the device must be enabled + * + * \note This function is non-blocking, so it will return immediately. + */ +void bld_beep(enum BLD_DEVICE device, uint16_t duration); + + +/** Enable a device for a certain interval of time and wait. + * + * \param device Device to be enabled + * \param duration Number of milliseconds the device must be enabled + * + * \note This function is blocking, so it will return after the specified period of time. + */ +void bld_beep_and_wait(enum BLD_DEVICE device, uint16_t duration); + +#endif /* DRV_BUZZERLED_H */ diff --git a/bertos/drv/dataflash.c b/bertos/drv/dataflash.c new file mode 100644 index 00000000..d9392f9a --- /dev/null +++ b/bertos/drv/dataflash.c @@ -0,0 +1,494 @@ +/** + * \file + * + * + * \brief Function library for AT45DBXX Data Flash memory. + * + * + * \version $Id: dataflash.c 20677 2008-02-19 14:29:52Z batt $ + * \author Daniele Basile + * \author Francesco Sacchi + */ + +#include "dataflash.h" +#include + +#include +#include +#include +#include +#include + +#if CONFIG_KERNEL +#include +#endif + +#include + +/** + * Array used to describe dataflash memory devices currently supported. + */ +static const DataflashInfo mem_info[] = +{ + { + /* AT45DB041B */ + .density_id = 0x07, + .page_size = 264, + .page_bits = 9, + .page_cnt = 2048, + .read_cmd = DFO_READ_FLASH_MEM_BYTE_B, + }, + { + /* AT45DB081D */ + .density_id = 0x09, + .page_size = 264, + .page_bits = 9, + .page_cnt = 4096, + .read_cmd = DFO_READ_FLASH_MEM_BYTE_D, + }, + { + /* AT45DB161D */ + .density_id = 0x0B, + .page_size = 528, + .page_bits = 10, + .page_cnt = 4096, + .read_cmd = DFO_READ_FLASH_MEM_BYTE_D, + }, + /* Add other memories here */ +}; + +STATIC_ASSERT(countof(mem_info) == DFT_CNT); + +/** + * Macro that toggle CS of dataflash. + * \note This is equivalent to fd->setCS(false) immediately followed by fd->setCS(true). + */ +INLINE void CS_TOGGLE(KFileDataflash *fd) +{ + fd->setCS(false); + fd->setCS(true); +} + +/** + * Send a generic command to dataflash memory. + * This function send only 4 byte: opcode, page address and + * byte address. + */ +static void send_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode) +{ + + /* + * Make sure to toggle CS signal in order, + * and reset dataflash command decoder. + */ + CS_TOGGLE(fd); + + + /* + * To send one command to data flash memory, we send 4 byte. + * First byte is opcode command, second and third byte are + * page address, in last byte we write a byte page address. + * (see datasheet for more detail). + * + * \note Generaly a defaul memory page size is more than 256 byte. + * In this case we need for addressing a byte in one page more than + * 8 bit, so we put in fourth byte low part of address byte, and + * hight part of address byte in third byte togheter low par of page + * address. + * + */ + + /* + * Send opcode. + */ + kfile_putc(opcode, fd->channel); + + /* + * Send page address. + */ + kfile_putc((uint8_t)(page_addr >> (16 - mem_info[fd->dev].page_bits)), fd->channel); + kfile_putc((uint8_t)((page_addr << (mem_info[fd->dev].page_bits - 8)) + (byte_addr >> 8)), fd->channel); + + /* + * Send byte page address. + */ + kfile_putc((uint8_t)byte_addr, fd->channel); +} + +/** + * Reset dataflash memory function. + * + * If \a fd->setReset function is not NULL, + * this function resets data flash memory + * with one pulse reset long about 10usec. + * + */ +static void dataflash_reset(KFileDataflash *fd) +{ + fd->setCS(false); + + if (fd->setReset) + { + fd->setReset(true); + timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH)); + fd->setReset(false); + timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH)); + } +} + + +/** + * Read status register of dataflah memory. + */ +static uint8_t dataflash_stat(KFileDataflash *fd) +{ + /* + * Make sure to toggle CS signal + * and reset dataflash command decoder. + */ + CS_TOGGLE(fd); + + kfile_putc(DFO_READ_STATUS, fd->channel); + + return kfile_getc(fd->channel); +} + + +/** + * Send one command to data flash memory, and + * return status register value. + * + */ +static uint8_t dataflash_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode) +{ + uint8_t stat; + + send_cmd(fd, page_addr, byte_addr, opcode); + + CS_TOGGLE(fd); + + /* + * We chech data flash memory state, and wait until busy-flag + * is high. + */ + while (!(dataflash_stat(fd) & BUSY_BIT)) + { + #if CONFIG_KERNEL + proc_switch(); + #endif + } + + stat = dataflash_stat(fd); + + kfile_flush(fd->channel); // Flush channel + /* + * Data flash has completed a bus cycle, so disable CS. + */ + fd->setCS(false); + + return stat; +} + +/** + * Read \a len bytes from main data flash memory or buffer data + * flash memory, and put it in \a *block. + */ +static void dataflash_readBlock(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflash_size_t len) +{ + send_cmd(fd, page_addr, byte_addr, opcode); + + if (opcode == DFO_READ_FLASH_MEM_BYTE_B) + { + /* + * Send 24 don't care bits. + */ + uint8_t dummy[] = { 0, 0, 0 }; + kfile_write(fd->channel, dummy, sizeof(dummy)); + } + + kfile_putc(0, fd->channel); //Send 8 don't care bit. + kfile_read(fd->channel, block, len); //Read len bytes ad put in block buffer. + kfile_flush(fd->channel); // Flush channel + fd->setCS(false); +} + + +/** + * Write \a len bytes in dataflash memory buffer. + * + * \note Is not possible to write directly in dataflash main memory. + * To perform a write in main memory you must first write in dataflash buffer + * memory and then send a command to write the page in main memory. + */ +static void dataflash_writeBlock(KFileDataflash *fd, dataflash_offset_t offset, DataFlashOpcode opcode, const uint8_t *block, dataflash_size_t len) +{ + ASSERT(offset + len <= mem_info[fd->dev].page_size); + + send_cmd(fd, 0x00, offset, opcode); + + kfile_write(fd->channel, block, len); //Write len bytes. + kfile_flush(fd->channel); // Flush channel + + fd->setCS(false); +} + + +/** + * Load selct page from dataflash memory to buffer. + */ +static void dataflash_loadPage(KFileDataflash *fd, dataflash_page_t page_addr) +{ + dataflash_cmd(fd, page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1); +} + +/** + * Flush select page (stored in buffer) in data flash main memory page. + */ +static int dataflash_flush(KFile *_fd) +{ + KFileDataflash *fd = KFILEDATAFLASH(_fd); + if (fd->page_dirty) + { + dataflash_cmd(fd, fd->current_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E); + + fd->page_dirty = false; + + kprintf("Flushing page <%ld>\n", fd->current_page); + } + return 0; +} + +/* Kfile interface section */ + +/** + * Close file \a fd. + */ +static int dataflash_close(struct KFile *_fd) +{ + dataflash_flush(_fd); + TRACE; + return 0; +} + +/** + * Reopen dataflash file \a fd. + */ +static KFile *dataflash_reopen(KFile *_fd) +{ + KFileDataflash *fd = KFILEDATAFLASH(_fd); + dataflash_close(_fd); + + fd->current_page = 0; + fd->fd.seek_pos = 0; + + /* Load selected page from dataflash memory */ + dataflash_loadPage(fd, fd->current_page); + + TRACE; + return &fd->fd; +} + + +/** + * Read in \a buf \a size bytes from dataflash memmory. + * + * \note For reading data flash memory, we + * check flag page_dirty, if is true (that mean + * we have written a byte in buffer memory) we + * flush current page in main memory and + * then read from memory, else we read byte + * directly from data flash main memory. + * + * \return the number of bytes read. + */ +static size_t dataflash_read(struct KFile *_fd, void *buf, size_t size) +{ + KFileDataflash *fd = KFILEDATAFLASH(_fd); + + dataflash_offset_t byte_addr; + dataflash_page_t page_addr; + uint8_t *data = (uint8_t *)buf; + + + ASSERT(fd->fd.seek_pos + size <= fd->fd.size); + size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos); + + kprintf("Reading at pos[%lu]\n", fd->fd.seek_pos); + + /* + * We select page and offest from absolute address. + */ + page_addr = fd->fd.seek_pos / mem_info[fd->dev].page_size; + byte_addr = fd->fd.seek_pos % mem_info[fd->dev].page_size; + + kprintf("[page-<%ld>, byte-<%ld>]", page_addr, byte_addr); + + /* + * Flush current page in main memory if + * we had been written a byte in memory + */ + dataflash_flush(&fd->fd); + + /* + * Read byte in main page data flash memory. + */ + dataflash_readBlock(fd, page_addr, byte_addr, mem_info[fd->dev].read_cmd, data, size); + + fd->fd.seek_pos += size; + kprintf("Read %ld bytes\n", size); + + return size; +} + +/** + * Write \a _buf in dataflash memory + * + * \note For writing \a _buf in dataflash memory, we must + * first write in buffer data flash memory. At the end of write, + * we can put page in dataflash main memory. + * If we write in two contiguous pages, we put in main memory current + * page and then reload the page which we want to write. + * + * \return the number of bytes write. + */ +static size_t dataflash_write(struct KFile *_fd, const void *_buf, size_t size) +{ + KFileDataflash *fd = KFILEDATAFLASH(_fd); + + dataflash_offset_t offset; + dataflash_page_t new_page; + size_t total_write = 0; + + const uint8_t *data = (const uint8_t *) _buf; + + ASSERT(fd->fd.seek_pos + size <= fd->fd.size); + size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos); + + kprintf("Writing at pos[%lu]\n", fd->fd.seek_pos); + + while (size) + { + /* + * We select page and offest from absolute address. + */ + new_page = fd->fd.seek_pos / mem_info[fd->dev].page_size; + offset = fd->fd.seek_pos % mem_info[fd->dev].page_size; + + + size_t wr_len = MIN(size, mem_info[fd->dev].page_size - offset); + + kprintf(" [page-<%ld>, byte-<%ld>]",new_page, offset); + + if (new_page != fd->current_page) + { + /* Flush current page in main memory*/ + dataflash_flush(&fd->fd); + /* Load select page memory from data flash memory*/ + dataflash_loadPage(fd, new_page); + + fd->current_page = new_page; + kprintf(" >> Load page: <%ld> ", new_page); + } + /* + * Write byte in current page, and set true + * page_dirty flag. + */ + dataflash_writeBlock(fd, offset, DFO_WRITE_BUFF1, data, wr_len); + fd->page_dirty = true; + + data += wr_len; + fd->fd.seek_pos += wr_len; + size -= wr_len; + total_write += wr_len; + } + + kprintf("written %lu bytes\n", total_write); + return total_write; +} + +MOD_DEFINE(dataflash); + +/** + * Dataflash init function. + * This function initialize \a fd with SPI channel \a ch and test if data flash memory + * density is the same specified by device \a dev. + * \a setCS is a callback used to set/reset CS line. + * \a setReset is a callback used to set/reset the dataflash (can be NULL if reset is unconnected) + * \return true if ok, false if memory density read from dataflash is not compliant with the + * configured one. + */ +bool dataflash_init(KFileDataflash *fd, KFile *ch, DataflashType dev, dataflash_setCS_t *setCS, dataflash_setReset_t *setReset) +{ + uint8_t stat; + + MOD_CHECK(dataflash_hw); + + ASSERT(fd); + ASSERT(ch); + ASSERT(setCS); + ASSERT(dev < DFT_CNT); + + memset(fd, 0, sizeof(*fd)); + DB(fd->fd._type = KFT_DATAFLASH); + fd->dev = dev; + fd->channel = ch; + fd->setReset = setReset; + fd->setCS = setCS; + + // Setup data flash programming functions. + fd->fd.reopen = dataflash_reopen; + fd->fd.close = dataflash_close; + fd->fd.read = dataflash_read; + fd->fd.write = dataflash_write; + fd->fd.seek = kfile_genericSeek; + fd->fd.flush = dataflash_flush; + + dataflash_reset(fd); + + stat = dataflash_stat(fd); + + /* + * 2,3,4,5 bits of 1 byte status register + * indicate a device density of dataflash memory + * (see datasheet for more detail.) + */ + if (GET_ID_DESITY_DEVICE(stat) != mem_info[fd->dev].density_id) + return false; + + fd->current_page = 0; + fd->fd.seek_pos = 0; + fd->fd.size = mem_info[fd->dev].page_size * mem_info[fd->dev].page_cnt; + + /* Load selected page from dataflash memory */ + dataflash_loadPage(fd, fd->current_page); + MOD_INIT(dataflash); + return true; +} diff --git a/bertos/drv/dataflash.h b/bertos/drv/dataflash.h new file mode 100644 index 00000000..61858167 --- /dev/null +++ b/bertos/drv/dataflash.h @@ -0,0 +1,187 @@ +/** + * \file + * + * + * \brief Function library for AT45DB081D Flash memory. + * + * + * \version $Id: dataflash.h 20677 2008-02-19 14:29:52Z batt $ + * \author Daniele Basile + */ + + +#ifndef DRV_DATAFLASH_H +#define DRV_DATAFLASH_H + +#include +#include + +#include + + +/** + * Type definitions for dflash memory. + * \{ + */ +typedef uint32_t dataflash_page_t; +typedef uint32_t dataflash_offset_t; +typedef uint32_t dataflash_size_t; +/*\}*/ + +/** + * + */ +typedef void (dataflash_setReset_t)(bool); +typedef void (dataflash_setCS_t)(bool); + +/** + * Memory definitions. + * + * List of supported memory devices by this drive. + * Every time we call dataflash_init() we check device id to + * ensure we choose the right memory configuration. + * (see dataflash.c for more details). + */ +typedef enum DataflashType +{ + DFT_AT45DB041B, + DFT_AT45DB081D, + DFT_AT45DB161D, + DFT_CNT +} DataflashType; + + +/** + * Dataflash KFile context structure. + */ +typedef struct KFileDataflash +{ + KFile fd; ///< File descriptor. + KFile *channel; ///< Dataflash comm channel (usually SPI). + DataflashType dev; ///< Memory device type; + dataflash_page_t current_page; ///< Current loaded dataflash page. + bool page_dirty; ///< True if current_page is dirty (needs to be flushed). + dataflash_setReset_t *setReset; ///< Callback used to set reset pin of dataflash. + dataflash_setCS_t *setCS; ///< Callback used to set CS pin of dataflash. +} KFileDataflash; + +/** + * ID for dataflash. + */ +#define KFT_DATAFLASH MAKE_ID('D', 'F', 'L', 'H') + +/** + * Convert + ASSERT from generic KFile to KFileDataflash. + */ +INLINE KFileDataflash * KFILEDATAFLASH(KFile *fd) +{ + ASSERT(fd->_type == KFT_DATAFLASH); + return (KFileDataflash *)fd; +} + +#define RESET_PULSE_WIDTH 10 ///< Width of reset pulse in usec. +#define BUSY_BIT 0x80 ///< Select a busy bit in status register. +#define CMP_BIT 0x40 ///< Select a compare bit in status register. + +/** + * Select bits 2-5 of status register. These + * bits indicate device density (see datasheet for + * more details). + */ +#define GET_ID_DESITY_DEVICE(reg_stat) (((reg_stat) & 0x3C) >> 2) + +/** + * Data flash opcode commands. + */ +typedef enum DataFlashOpcode { + /** + * Dataflash read commands. + * \{ + */ + DFO_READ_FLASH_MEM_BYTE_D = 0x0B, ///< Continuos array read for D type memories. + DFO_READ_FLASH_MEM_BYTE_B = 0xE8, ///< Continuos array read for B type memories. + + DFO_READ_FLASH_MEM = 0xD2, ///< Main memory page read. + DFO_READ_BUFF1 = 0xD4, ///< SRAM buffer 1 read. + DFO_READ_BUFF2 = 0xD6, ///< SRAM buffer 2 read. + /* \}*/ + + /** + * Program and erase commands data flash. + * \{ + */ + DFO_WRITE_BUFF1 = 0x84, ///< SRAM buffer 1 write. + DFO_WRITE_BUFF2 = 0x87, ///< SRAM buffer 2 write. + DFO_WRITE_BUFF1_TO_MEM_E = 0x83, ///< Buffer 1 to main memory page program with built-in erase. + DFO_WRITE_BUFF2_TO_MEM_E = 0x86, ///< Buffer 2 to main memory page program with built-in erase. + DFO_WRITE_BUFF1_TO_MEM = 0x88, ///< Buffer 1 to main memory page program without built-in erase. + DFO_WRITE_BUFF2_TO_MEM = 0x89, ///< Buffer 2 to main memory page program without built-in erase. + DFO_ERASE_PAGE = 0x81, ///< Erase page. + DFO_ERASE_BLOCK = 0x50, ///< Erase block. + DFO_ERASE_SECTOR = 0x7C, ///< Erase sector. + DFO_WRITE_MEM_TR_BUFF1 = 0x82, ///< Write main memory page through buffer 1. + DFO_WRITE_MEM_TR_BUFF2 = 0x85, ///< Write main memory page through buffer 2. + /* \}*/ + + /** + * Additional dataflash commands. + * \{ + */ + DFO_MOV_MEM_TO_BUFF1 = 0x53, ///< Transfer main mmemory to buffer 1. + DFO_MOV_MEM_TO_BUFF2 = 0x55, ///< Transfer main mmemory to buffer 2. + DFO_CMP_MEM_TO_BUFF1 = 0x60, ///< Compare main mmemory with buffer 1. + DFO_CMP_MEM_TO_BUFF2 = 0x61, ///< Compare main mmemory with buffer 2. + DFO_ARW_MEM_TR_BUFF1 = 0x58, ///< Auto page rewrite through buffer 1. + DFO_ARW_MEM_TR_BUFF2 = 0x59, ///< Auto page rewrite through buffer 2 + DFO_PWR_DOWN = 0xB9, ///< Deep power-down. + DFO_RESUME_PWR_DOWN = 0xAB, ///< Resume from deep power-down. + DFO_READ_STATUS = 0xD7, ///< Read status register. + DFO_ID_DEV = 0x9F ///< Read manufacturer and device ID. + /* \}*/ +} DataFlashOpcode; + + +/** + * Structure used to describe a dataflash memory. + */ +typedef struct DataflashInfo +{ + uint8_t density_id; ///< Density id, used to check memory type. + dataflash_size_t page_size; ///< Page size, in bytes. + uint8_t page_bits; ///< Number of bits needed to access a page. + uint16_t page_cnt; ///< Number of pages on memory. + DataFlashOpcode read_cmd; ///< Command to be used to perform a continuous array. +} DataflashInfo; + + +bool dataflash_init(KFileDataflash *fd, KFile *ch, DataflashType type, dataflash_setCS_t *setCS, dataflash_setReset_t *setReset); + +#endif /* DRV_DATAFLASH_H */ diff --git a/bertos/drv/eeprom.c b/bertos/drv/eeprom.c new file mode 100644 index 00000000..4e7f615f --- /dev/null +++ b/bertos/drv/eeprom.c @@ -0,0 +1,341 @@ +/** + * \file + * + * + * \brief Driver for the 24xx16 and 24xx256 I2C EEPROMS (implementation) + * + * \note This implementation is AVR specific. + * + * \version $Id$ + * \author Stefano Fedrigo + * \author Bernardo Innocenti + */ + +#include "eeprom.h" + +#include +#include // CONFIG_EEPROM_VERIFY +#include // MIN() +#include +#include CPU_HEADER(twi) +#include +#include // cpu_to_be16() + +#include // memset() + + +// Configuration sanity checks +#if !defined(CONFIG_EEPROM_VERIFY) || (CONFIG_EEPROM_VERIFY != 0 && CONFIG_EEPROM_VERIFY != 1) + #error CONFIG_EEPROM_VERIFY must be defined to either 0 or 1 +#endif + +/** + * EEPROM ID code + */ +#define EEPROM_ID 0xA0 + +/** + * This macros form the correct slave address for EEPROMs + */ +#define EEPROM_ADDR(x) (EEPROM_ID | (((uint8_t)(x)) << 1)) + + + + +/** + * Copy \c count bytes from buffer \c buf to + * eeprom at address \c addr. + */ +static bool eeprom_writeRaw(e2addr_t addr, const void *buf, size_t count) +{ + bool result = true; + ASSERT(addr + count <= EEPROM_SIZE); + + while (count && result) + { + /* + * Split write in multiple sequential mode operations that + * don't cross page boundaries. + */ + size_t size = + MIN(count, (size_t)(EEPROM_BLKSIZE - (addr & (EEPROM_BLKSIZE - 1)))); + + #if CONFIG_EEPROM_TYPE == EEPROM_24XX16 + /* + * The 24LC16 uses the slave address as a 3-bit + * block address. + */ + uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07); + uint8_t blk_offs = (uint8_t)addr; + + result = + twi_start_w(EEPROM_ADDR(blk_addr)) + && twi_send(&blk_offs, sizeof blk_offs) + && twi_send(buf, size); + + #elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 + + // 24LC256 wants big-endian addresses + uint16_t addr_be = cpu_to_be16(addr); + + result = + twi_start_w(EEPROM_ID) + && twi_send((uint8_t *)&addr_be, sizeof addr_be) + && twi_send(buf, size); + + #else + #error Unknown device type + #endif + + twi_stop(); + + // DEBUG + //kprintf("addr=%d, count=%d, size=%d, *#?=%d\n", + // addr, count, size, + // (EEPROM_BLKSIZE - (addr & (EEPROM_BLKSIZE - 1))) + //); + + /* Update count and addr for next operation */ + count -= size; + addr += size; + buf = ((const char *)buf) + size; + } + + if (!result) + TRACEMSG("Write error!"); + return result; +} + + +#if CONFIG_EEPROM_VERIFY +/** + * Check that the contents of an EEPROM range + * match with a provided data buffer. + * + * \return true on success. + */ +static bool eeprom_verify(e2addr_t addr, const void *buf, size_t count) +{ + uint8_t verify_buf[16]; + bool result = true; + + while (count && result) + { + /* Split read in smaller pieces */ + size_t size = MIN(count, sizeof verify_buf); + + /* Read back buffer */ + if (eeprom_read(addr, verify_buf, size)) + { + if (memcmp(buf, verify_buf, size) != 0) + { + TRACEMSG("Data mismatch!"); + result = false; + } + } + else + { + TRACEMSG("Read error!"); + result = false; + } + + /* Update count and addr for next operation */ + count -= size; + addr += size; + buf = ((const char *)buf) + size; + } + + return result; +} +#endif /* CONFIG_EEPROM_VERIFY */ + + +bool eeprom_write(e2addr_t addr, const void *buf, size_t count) +{ +#if CONFIG_EEPROM_VERIFY + int retries = 5; + + while (retries--) + if (eeprom_writeRaw(addr, buf, count) + && eeprom_verify(addr, buf, count)) + return true; + + return false; + +#else /* !CONFIG_EEPROM_VERIFY */ + return eeprom_writeRaw(addr, buf, count); +#endif /* !CONFIG_EEPROM_VERIFY */ +} + + +/** + * Copy \c count bytes at address \c addr + * from eeprom to RAM to buffer \c buf. + * + * \return true on success. + */ +bool eeprom_read(e2addr_t addr, void *buf, size_t count) +{ + ASSERT(addr + count <= EEPROM_SIZE); + +#if CONFIG_EEPROM_TYPE == EEPROM_24XX16 + /* + * The 24LC16 uses the slave address as a 3-bit + * block address. + */ + uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07); + uint8_t blk_offs = (uint8_t)addr; + + bool res = + twi_start_w(EEPROM_ADDR(blk_addr)) + && twi_send(&blk_offs, sizeof blk_offs) + && twi_start_r(EEPROM_ADDR(blk_addr)) + && twi_recv(buf, count); + +#elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 + + // 24LC256 wants big-endian addresses + addr = cpu_to_be16(addr); + + bool res = + twi_start_w(EEPROM_ID) + && twi_send((uint8_t *)&addr, sizeof(addr)) + && twi_start_r(EEPROM_ID) + && twi_recv(buf, count); +#else + #error Unknown device type +#endif + + twi_stop(); + + if (!res) + TRACEMSG("Read error!"); + return res; +} + + +/** + * Write a single character \a c at address \a addr. + */ +bool eeprom_write_char(e2addr_t addr, char c) +{ + return eeprom_write(addr, &c, 1); +} + + +/** + * Read a single character at address \a addr. + * + * \return the requested character or -1 in case of failure. + */ +int eeprom_read_char(e2addr_t addr) +{ + char c; + + if (eeprom_read(addr, &c, 1)) + return c; + else + return -1; +} + + +/** + * Erase specified part of eeprom, writing 0xFF. + * + * \param addr starting address + * \param count length of block to erase + */ +void eeprom_erase(e2addr_t addr, size_t count) +{ + uint8_t buf[EEPROM_BLKSIZE]; + memset(buf, 0xFF, sizeof buf); + + // Clear all but struct hw_info at start of eeprom + while (count) + { + // Long operation, reset watchdog + wdt_reset(); + + size_t size = MIN(count, sizeof buf); + eeprom_write(addr, buf, size); + addr += size; + count -= size; + } +} + + +/** + * Initialize TWI module. + */ +void eeprom_init(void) +{ + twi_init(); +} + + +#ifdef _DEBUG + +#include + +void eeprom_test(void) +{ + static const char magic[14] = "Humpty Dumpty"; + char buf[sizeof magic]; + size_t i; + + // Write something to EEPROM using unaligned sequential writes + for (i = 0; i < 42; ++i) + { + wdt_reset(); + eeprom_write(i * sizeof magic, magic, sizeof magic); + } + + // Read back with single-byte reads + for (i = 0; i < 42 * sizeof magic; ++i) + { + wdt_reset(); + eeprom_read(i, buf, 1); + kprintf("EEPROM byte read: %c (%d)\n", buf[0], buf[0]); + ASSERT(buf[0] == magic[i % sizeof magic]); + } + + // Read back again using sequential reads + for (i = 0; i < 42; ++i) + { + wdt_reset(); + memset(buf, 0, sizeof buf); + eeprom_read(i * sizeof magic, buf, sizeof magic); + kprintf("EEPROM seq read @ 0x%x: '%s'\n", i * sizeof magic, buf); + ASSERT(memcmp(buf, magic, sizeof magic) == 0); + } +} + +#endif // _DEBUG diff --git a/bertos/drv/eeprom.h b/bertos/drv/eeprom.h new file mode 100644 index 00000000..21ae105a --- /dev/null +++ b/bertos/drv/eeprom.h @@ -0,0 +1,88 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Stefano Fedrigo + * \author Bernardo Innocenti + * + * \brief Driver for the 24xx16 and 24xx256 I2C EEPROMS (interface) + */ + +#ifndef DRV_EEPROM_H +#define DRV_EEPROM_H + +#include +#include + +/** + * \name Values for CONFIG_EEPROM_TYPE + * \{ + */ +#define EEPROM_24XX16 1 +#define EEPROM_24XX256 2 +/*\}*/ + +#if CONFIG_EEPROM_TYPE == EEPROM_24XX16 + #define EEPROM_BLKSIZE 0x10 ///< Eeprom block size (16byte) + #define EEPROM_SIZE 0x800 ///< Eeprom total size (2kB) +#elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 + #define EEPROM_BLKSIZE 0x40 ///< Eeprom block size (64byte) + #define EEPROM_SIZE 0x8000 ///< Eeprom total size (32kB) +#else + #error Unsupported EEPROM type. +#endif + +/// Type for EEPROM addresses +typedef uint16_t e2addr_t; + +/** + * Macro for E2Layout offset calculation + * + * \note We can't just use offsetof() here because we could use + * non-constant expressions to access array elements. + * + * \note 'type' is the structure type holding eeprom layout + * and must be defined in user files. + */ +#define e2addr(type, field) ((e2addr_t)&(((type *)0)->field)) + + +bool eeprom_write(e2addr_t addr, const void *buf, size_t count); +bool eeprom_read(e2addr_t addr, void *buf, size_t count); +bool eeprom_write_char(e2addr_t addr, char c); +int eeprom_read_char(e2addr_t addr); +void eeprom_erase(e2addr_t addr, size_t count); +void eeprom_init(void); +void eeprom_test(void); + +#endif /* DRV_EEPROM_H */ diff --git a/bertos/drv/flash25.c b/bertos/drv/flash25.c new file mode 100644 index 00000000..2f90d52f --- /dev/null +++ b/bertos/drv/flash25.c @@ -0,0 +1,439 @@ +/** + * \file + * + * + * \brief Function library for serial Flash memory. + * + * Module provide a kfile interface, that ensure an abstraction + * from comunication channel and give a standard interface. + * Typicaly this kind of memory use an SPI bus, but you should + * use another comunication channel you have defined. + * + * \version $Id$ + * \author Daniele Basile + */ + +#include + +#include +#include + +#include +#include + +#if CONFIG_KERNEL +#include +#endif + +/* + * We use a spi bus, thus include hardware specific definition. + * If you use another channel you must redefine this macros. + */ +#include "hw_spi.h" + +#include + +/** + * Global definition of channel handler (usually SPI). + */ +static KFile *channel; + +/** + * Wait until flash memory is ready. + */ +static void flash25_waitReady(void) +{ + uint8_t stat; + + while (1) + { + CS_ENABLE(); + + kfile_putc(FLASH25_RDSR, channel); + stat = kfile_getc(channel); + + CS_DISABLE(); + + if (!(stat & RDY_BIT)) + break; + #if CONFIG_KERNEL + else + proc_switch(); + #endif + } +} + +/** + * Send a single command to serial flash memory. + */ +static void flash25_sendCmd(Flash25Opcode cmd) +{ + CS_ENABLE(); + + kfile_putc(cmd, channel); + + CS_DISABLE(); +} + +/** + * flash25 init function. + * This function init a comunication channel and + * try to read manufacturer id of serial memory, + * then check if is equal to selected type. + */ +static bool flash25_pin_init(void) +{ + uint8_t device_id; + uint8_t manufacturer; + + SPI_HW_INIT(); + + CS_ENABLE(); + /* + * Send read id productor opcode on + * comunication channel + * TODO:controllare se ha senso + */ + kfile_putc(FLASH25_RDID, channel); + + manufacturer = kfile_getc(channel); + device_id = kfile_getc(channel); + + CS_DISABLE(); + + if((FLASH25_MANUFACTURER_ID == manufacturer) && + (FLASH25_DEVICE_ID == device_id)) + return true; + else + return false; +} + +/** + * Reopen a serial memory interface. + * + * For serial memory this function reinit only + * the size and seek_pos in kfile stucture. + * Return a kfile pointer, after assert check. + */ +static KFile * flash25_reopen(struct KFile *fd) +{ + KFILE_ASSERT_GENERIC(fd); + + fd->seek_pos = 0; + fd->size = FLASH25_MEM_SIZE; + + kprintf("flash25 file opened\n"); + return fd; +} + +/** + * Close a serial memory interface. + * + * For serial memory this funtion do nothing, + * and return always 0. + */ +static int flash25_close(UNUSED_ARG(struct KFile *,fd)) +{ + kprintf("flash25 file closed\n"); + return 0; +} + +/** + * Read \a _buf lenght \a size byte from serial flash memmory. + * + * For read in serial flash memory we + * enble cs pin and send one byte of read opcode, + * and then 3 byte of address of memory cell we + * want to read. After the last byte of address we + * can read data from so pin. + * + * \return the number of bytes read. + */ +static size_t flash25_read(struct KFile *fd, void *buf, size_t size) +{ + uint8_t *data = (uint8_t *)buf; + + KFILE_ASSERT_GENERIC(fd); + + ASSERT(fd->seek_pos + size <= fd->size); + size = MIN((uint32_t)size, fd->size - fd->seek_pos); + + //kprintf("Reading at addr[%lu], size[%d]\n", fd->seek_pos, size); + CS_ENABLE(); + + kfile_putc(FLASH25_READ, channel); + + + /* + * Address that we want to read. + */ + kfile_putc((fd->seek_pos >> 16) & 0xFF, channel); + kfile_putc((fd->seek_pos >> 8) & 0xFF, channel); + kfile_putc(fd->seek_pos & 0xFF, channel); + + kfile_read(channel, data, size); + + CS_DISABLE(); + + fd->seek_pos += size; + + return size; +} + +/** + * Write \a _buf in serial flash memory + * + * Before to write data into flash we must enable + * memory writing. To do this we send a WRE command opcode. + * After this command the flash is ready to be write, and so + * we send a PROGRAM opcode followed to 3 byte of + * address memory, at the end of last address byte + * we can send the data. + * When we finish to send all data, we disable cs + * and flash write received data bytes on its memory. + * + * \note: WARNING: you could write only on erased memory section! + * Each write time you could write max a memory page size, + * because if you write more than memory page size the + * address roll over to first byte of page. + * + * \return the number of bytes write. + */ +static size_t flash25_write(struct KFile *fd, const void *_buf, size_t size) +{ + flash25Offset_t offset; + flash25Size_t total_write = 0; + flash25Size_t wr_len; + const uint8_t *data = (const uint8_t *) _buf; + + KFILE_ASSERT_GENERIC(fd); + ASSERT(fd->seek_pos + size <= fd->size); + + size = MIN((flash25Size_t)size, fd->size - fd->seek_pos); + + while (size) + { + offset = fd->seek_pos % (flash25Size_t)FLASH25_PAGE_SIZE; + wr_len = MIN((flash25Size_t)size, FLASH25_PAGE_SIZE - (flash25Size_t)offset); + + kprintf("[seek_pos-<%lu>, offset-<%d>]\n", fd->seek_pos, offset); + + /* + * We check serial flash memory state, and wait until ready-flag + * is high. + */ + flash25_waitReady(); + + /* + * Start write cycle. + * We could write only data not more long than one + * page size. + * + * To write on serial flash memory we must first + * enable write with a WREN opcode command, before + * the PROGRAM opcode. + * + * \note: the same byte cannot be reprogrammed without + * erasing the whole sector first. + */ + flash25_sendCmd(FLASH25_WREN); + + CS_ENABLE(); + kfile_putc(FLASH25_PROGRAM, channel); + + /* + * Address that we want to write. + */ + kfile_putc((fd->seek_pos >> 16) & 0xFF, channel); + kfile_putc((fd->seek_pos >> 8) & 0xFF, channel); + kfile_putc(fd->seek_pos & 0xFF, channel); + + kfile_write(channel, data, wr_len); + + CS_DISABLE(); + + data += wr_len; + fd->seek_pos += wr_len; + size -= wr_len; + total_write += wr_len; + } + + kprintf("written %u bytes\n", total_write); + return total_write; +} + +/** + * Sector erase function. + * + * Erase a select \p sector of serial flash memory. + * + * \note A sector size is FLASH25_SECTOR_SIZE. + * This operation could take a while. + */ +void flash25_sectorErase(Flash25Sector sector) +{ + + /* + * Erase a sector could take a while, + * for debug we measure that time + * see datasheet to compare this time. + */ + DB(ticks_t start_time = timer_clock()); + + CS_ENABLE(); + + /* + * To erase a sector of serial flash memory we must first + * enable write with a WREN opcode command, before + * the SECTOR_ERASE opcode. Sector is automatically + * determinate if any address within the sector + * is selected. + */ + kfile_putc(FLASH25_WREN, channel); + kfile_putc(FLASH25_SECTORE_ERASE, channel); + + /* + * Address inside the sector that we want to + * erase. + */ + kfile_putc(sector, channel); + + CS_DISABLE(); + + /* + * We check serial flash memory state, and wait until ready-flag + * is hight. + */ + flash25_waitReady(); + + DB(kprintf("Erased sector [%d] in %d ms\n", sector, ticks_to_ms(timer_clock() - start_time))); + +} + +/** + * Chip erase function. + * + * Erase all sector of serial flash memory. + * + * \note This operation could take a while. + */ +void flash25_chipErase(void) +{ + /* + * Erase all chip could take a while, + * for debug we measure that time + * see datasheet to compare this time. + */ + DB(ticks_t start_time = timer_clock()); + + /* + * To erase serial flash memory we must first + * enable write with a WREN opcode command, before + * the CHIP_ERASE opcode. + */ + flash25_sendCmd(FLASH25_WREN); + flash25_sendCmd(FLASH25_CHIP_ERASE); + + /* + * We check serial flash memory state, and wait until ready-flag + * is high. + */ + flash25_waitReady(); + + DB(kprintf("Erased all memory in %d ms\n", ticks_to_ms(timer_clock() - start_time))); + +} + +/** + * Init data flash memory interface. + */ +void flash25_init(struct KFile *fd, struct KFile *_channel) +{ + //Set kfile struct type as a generic kfile structure. + DB(fd->_type = KFT_GENERIC); + + // Set up data flash programming functions. + fd->reopen = flash25_reopen; + fd->close = flash25_close; + fd->read = flash25_read; + fd->write = flash25_write; + fd->seek = kfile_genericSeek; + + /* + * Init a local channel structure and flash kfile interface. + */ + channel = _channel; + flash25_reopen(fd); + + /* + * Init data flash memory and micro pin. + */ + if (!flash25_pin_init()) + ASSERT(0); +} + +#if CONFIG_TEST + +/** + * Test function for flash25. + * + * \note: This implentation use a SPI channel. + */ +bool flash25_test(KFile *channel) +{ + KFile fd; + uint8_t test_buf[256]; + + /* + * Init a spi kfile interface and + * flash driver. + */ + flash25_init(&fd, channel); + + kprintf("Init serial flash\n"); + + flash25_chipErase(); + + flash25_sectorErase(FLASH25_SECT1); + flash25_sectorErase(FLASH25_SECT2); + flash25_sectorErase(FLASH25_SECT3); + flash25_sectorErase(FLASH25_SECT4); + + /* + * Launche a kfile test interface. + */ + kprintf("Kfile test start..\n"); + if (!kfile_test(&fd, test_buf, NULL, sizeof(test_buf))) + return false; + + return true; +} +#endif /* CONFIG_TEST */ diff --git a/bertos/drv/flash25.h b/bertos/drv/flash25.h new file mode 100644 index 00000000..e45dbed4 --- /dev/null +++ b/bertos/drv/flash25.h @@ -0,0 +1,118 @@ +/** + * \file + * + * + * \brief Function library for serial Flash memory. + * + * + * \version $Id$ + * \author Daniele Basile + */ + + +#ifndef DRV_FLASH25_H +#define DRV_FLASH25_H + +#include +#include + + +#include + +/** + * Type definition for serial flash memory. + */ +typedef uint32_t flash25Addr_t; +typedef uint32_t flash25Size_t; +typedef uint8_t flash25Offset_t; + + +/** + * Memory definition. + * + * \note Below are defined valid serial flash memory support to + * this drive. Every time we call flash25_init() function we check + * if memory defined are right (see flash25.c form more detail). + * \{ + */ +#define FLASH25_AT25F2048 1 + +#if CONFIG_FLASH25 == FLASH25_AT25F2048 + #define FLASH25_MANUFACTURER_ID 0x1F // ATMEL + #define FLASH25_DEVICE_ID 0x63 // Device ID + #define FLASH25_PAGE_SIZE 256 // Page size in byte + #define FLASH25_NUM_SECTOR 4 // Number of section in serial memory + #define FLASH25_SECTOR_SIZE 65536UL // Section size in byte + #define FLASH25_MEM_SIZE FLASH25_NUM_SECTOR * FLASH25_SECTOR_SIZE + #define FLASH25_NUM_PAGE FLASH25_MEM_SIZE / FLASH25_PAGE_SIZE +#elif + #error Nothing memory defined in CONFIG_FLASH25 are support. +#endif + +#define RDY_BIT 0x1 // Statuts of write cycle +/* \} */ + +/** + * Serial flash opcode commands. + */ +typedef enum { + FLASH25_WREN = 0x6, ///< Set write enable latch + FLASH25_WRDI = 0x4, ///< Reset enable write latch + FLASH25_RDSR = 0x5, ///< Read status register + FLASH25_WRSR = 0x1, ///< Write status register + FLASH25_READ = 0x3, ///< Read data from memory array + FLASH25_PROGRAM = 0x2, ///< Program data into memory array + FLASH25_SECTORE_ERASE = 0x52, ///< Erase one sector in memory array + FLASH25_CHIP_ERASE = 0x62, ///< Erase all sector in memory array + FLASH25_RDID = 0x15 ///< Read Manufacturer and product ID +} Flash25Opcode; + +/** + * Serial flash sector memory address. + */ +#if CONFIG_FLASH25 != FLASH25_AT25F2048 + #error Nothing memory defined in CONFIG_FLASH25 are support. +#endif + +typedef enum { + FLASH25_SECT1 = 0x0, ///< Sector 1 (0x0 -0xFFFF) + FLASH25_SECT2 = 0x10000, ///< Sector 2 (0x10000 -0x1FFFF) + FLASH25_SECT3 = 0x20000, ///< Sector 3 (0x20000 -0x2FFFF) + FLASH25_SECT4 = 0x30000, ///< Sector 4 (0x30000 -0x3FFFF) +} Flash25Sector; + +void flash25_init(struct KFile *fd, struct KFile *_channel); +void flash25_chipErase(void); +void flash25_sectorErase(Flash25Sector sector); +bool flash25_test(KFile *channel); + +#endif /* DRV_FLASH25_H */ + diff --git a/bertos/drv/kbd.c b/bertos/drv/kbd.c new file mode 100644 index 00000000..f54ebf91 --- /dev/null +++ b/bertos/drv/kbd.c @@ -0,0 +1,500 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * \author Francesco Sacchi + * + * \brief Keyboard driver (implementation) + */ + +#include + +#include +#include + +#include +#include +#include + +/* Configuration sanity checks */ +#if !defined(CONFIG_KBD_POLL) || (CONFIG_KBD_POLL != KBD_POLL_SOFTINT && CONFIG_KBD_POLL != CONFIG_POLL_FREERTOS) + #error CONFIG_KBD_POLL must be defined to either KBD_POLL_SOFTINT or CONFIG_POLL_FREERTOS +#endif +#if !defined(CONFIG_KBD_BEEP) || (CONFIG_KBD_BEEP != 0 && CONFIG_KBD_BEEP != 1) + #error CONFIG_KBD_BEEP must be defined to either 0 or 1 +#endif +#if !defined(CONFIG_KBD_OBSERVER) || (CONFIG_KBD_OBSERVER != 0 && CONFIG_KBD_OBSERVER != 1) + #error CONFIG_KBD_OBSERVER must be defined to either 0 or 1 +#endif +#if !defined(CONFIG_KBD_LONGPRESS) || (CONFIG_KBD_LONGPRESS != 0 && CONFIG_KBD_LONGPRESS != 1) + #error CONFIG_KBD_LONGPRESS must be defined to either 0 or 1 +#endif + +#if CONFIG_KBD_BEEP + #include +#endif + +#define KBD_CHECK_INTERVAL 10 /**< (ms) Timing for kbd softint */ +#define KBD_DEBOUNCE_TIME 30 /**< (ms) Debounce time */ +#define KBD_BEEP_TIME 5 /**< (ms) Duration of keybeep */ + +#define KBD_REPEAT_DELAY 400 /**< (ms) Keyboard repeat delay for first character */ +#define KBD_REPEAT_RATE 100 /**< (ms) Initial interchar delay for keyboard repeat */ +#define KBD_REPEAT_MAXRATE 20 /**< (ms) Minimum delay for keyboard repeat */ +#define KBD_REPEAT_ACCEL 5 /**< (ms) Keyboard repeat speed increase */ + +#define KBD_LNG_DELAY 1000 /**< (ms) Keyboard long pression keys delay */ + + +/** Status for keyboard repeat state machine */ +static enum { KS_IDLE, KS_REPDELAY, KS_REPEAT } kbd_rptStatus; + + +static volatile keymask_t kbd_buf; /**< Single entry keyboard buffer */ +static volatile keymask_t kbd_cnt; /**< Number of keypress events in \c kbd_buf */ +static keymask_t kbd_rpt_mask; /**< Mask of repeatable keys. */ + +#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT +static Timer kbd_timer; /**< Keyboard softtimer */ +#endif + +static List kbd_rawHandlers; /**< Raw keyboard handlers */ +static List kbd_handlers; /**< Cooked keyboard handlers */ + +static KbdHandler kbd_defHandler; /**< The default keyboard handler */ +static KbdHandler kbd_debHandler; /**< The debounce keyboard handler */ +static KbdHandler kbd_rptHandler; /**< Auto-repeat keyboard handler */ + +#if CONFIG_KBD_LONGPRESS +static KbdHandler kbd_lngHandler; /**< Long pression keys handler */ +#endif + +#if CONFIG_KBD_OBSERVER + #include + Subject kbd_subject; +#endif + + +/** + * Poll keyboard and dispatch keys to handlers. + * + * Read the key states and invoke all keyboard + * handlers to process the new state. + * + * Call this function periodically using a software + * timer, an interrupt or a process. + */ +static void kbd_poll(void) +{ + /** Currently depressed key */ + static keymask_t current_key; + + struct KbdHandler *handler; + keymask_t key = kbd_readkeys(); + + /* Call raw input handlers */ + FOREACH_NODE(handler, &kbd_rawHandlers) + key = handler->hook(key); + + /* If this key was not previously pressed */ + if (key != current_key) + { + /* Remember last key */ + current_key = key; + + /* Call cooked input handlers */ + FOREACH_NODE(handler, &kbd_handlers) + key = handler->hook(key); + } +} + +#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT + +/** + * Keyboard soft-irq handler. + */ +static void kbd_softint(UNUSED_ARG(iptr_t, arg)) +{ + kbd_poll(); + timer_add(&kbd_timer); +} + +#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS + +#include "FreeRTOS.h" +#include "task.h" + +static portTASK_FUNCTION(kbd_task, arg) +{ + for (;;) + { + kbd_poll(); + timer_delay(KBD_CHECK_INTERVAL); + } +} + +#endif /* CONFIG_KBD_POLL */ + +/** + * \brief Read a key from the keyboard buffer. + * + * When a key is kept depressed between calls of this function a value + * is returned only after the time specified with KBD_REPAT_DELAY to + * avoid too fast keyboard repeat. + * + * \note Calls \c schedule() internally. + * + * \note This function is \b not interrupt safe! + * + * \return The mask of depressed keys or 0 if no keys are depressed. + * + */ +keymask_t kbd_peek(void) +{ + keymask_t key = 0; + +// FIXME: make it optional + /* Let other tasks run for a while */ + extern void schedule(void); + schedule(); + + /* Extract an event from the keyboard buffer */ + IRQ_DISABLE; + if (kbd_cnt) + { + --kbd_cnt; + key = kbd_buf; + } + IRQ_ENABLE; + + return key; +} + +/** + * Wait for a keypress and return the mask of depressed keys. + * + * \note This function is \b not interrupt safe! + */ +keymask_t kbd_get(void) +{ + keymask_t key; + + while (!(key = kbd_peek())) {} + + return key; +} + + +/** + * Wait up to \c timeout ms for a keypress + * and return the mask of depressed keys, or K_TIMEOUT + * if the timeout was reacked. + */ +keymask_t kbd_get_timeout(mtime_t timeout) +{ + keymask_t key; + + ticks_t start = timer_clock(); + ticks_t stop = ms_to_ticks(timeout); + do + { + if ((key = kbd_peek())) + return key; + } + while (timer_clock() - start < stop); + + return K_TIMEOUT; +} + + +void kbd_addHandler(struct KbdHandler *handler) +{ + KbdHandler *node; + List *list; + + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + /* Choose between raw and coocked handlers list */ + list = (handler->flags & KHF_RAWKEYS) ? + &kbd_rawHandlers : &kbd_handlers; + + /* + * Search for the first node whose priority + * is lower than the timer we want to add. + */ + FOREACH_NODE(node,list) + if (node->pri < handler->pri) + break; + + /* Enqueue handler in the handlers chain */ + INSERT_BEFORE(&handler->link, &node->link); + + IRQ_RESTORE(flags); +} + + +void kbd_remHandler(struct KbdHandler *handler) +{ + /* Remove the handler */ + ATOMIC(REMOVE(&handler->link)); +} + + +/** + * This is the default key handler, called after + * all other handlers have had their chance to + * do their special processing. This handler + * pushes all input in the keyboard FIFO buffer. + */ +static keymask_t kbd_defHandlerFunc(keymask_t key) +{ + if (key) + { + /* Force a single event in kbd buffer */ + kbd_buf = key; + kbd_cnt = 1; + + #if CONFIG_KBD_OBSERVER + observer_notify(&kbd_subject, KBD_EVENT_KEY, &key); + #endif + + #if CONFIG_KBD_BEEP + if (!(key & K_REPEAT)) + buz_beep(KBD_BEEP_TIME); + #endif + } + + /* Eat all input */ + return 0; +} + +/** + * Handle keyboard debounce + */ +static keymask_t kbd_debHandlerFunc(keymask_t key) +{ + /** Buffer for debounce */ + static keymask_t debounce_key; + + /** Timer for keyboard debounce */ + static ticks_t debounce_time; + + /** Key aquired after debounce */ + static keymask_t new_key; + + + ticks_t now = timer_clock(); + + if (key != debounce_key) + { + /* Reset debounce timer */ + debounce_key = key; + debounce_time = now; + } + else if ((new_key != debounce_key) + && (now - debounce_time > ms_to_ticks(KBD_DEBOUNCE_TIME))) + { + new_key = debounce_key; + debounce_time = now; + } + + return new_key; +} + +#if CONFIG_KBD_LONGPRESS +/** + * Handle long pression keys. + */ +static keymask_t kbd_lngHandlerFunc(keymask_t key) +{ + static ticks_t start; + ticks_t now = timer_clock(); + + if (key & K_LNG_MASK) + { + if (now - start > ms_to_ticks(KBD_LNG_DELAY)) + key |= K_LONG; + } + else + start = now; + return key; +} +#endif + +/** + * Set current mask of repeatable keys. + */ +keymask_t kbd_setRepeatMask(keymask_t mask) +{ + keymask_t oldmask = kbd_rpt_mask; + ATOMIC(kbd_rpt_mask = mask); + return oldmask; +} + +/** + * Handle keyboard repeat + */ +static keymask_t kbd_rptHandlerFunc(keymask_t key) +{ + /* Timer for keyboard repeat events. */ + static ticks_t repeat_time; + + /* Current repeat rate (for acceleration). */ + static ticks_t repeat_rate; /** Current repeat rate (for acceleration) */ + + ticks_t now = timer_clock(); + + switch (kbd_rptStatus) + { + case KS_IDLE: + if (key & kbd_rpt_mask) + { + repeat_time = now; + kbd_rptStatus = KS_REPDELAY; + } + break; + + case KS_REPDELAY: + if (key & kbd_rpt_mask) + { + if (now - repeat_time > ms_to_ticks(KBD_REPEAT_DELAY)) + { + key = (key & kbd_rpt_mask) | K_REPEAT; + repeat_time = now; + repeat_rate = ms_to_ticks(KBD_REPEAT_RATE); + kbd_rptStatus = KS_REPEAT; + } + else + key = 0; + } + else + kbd_rptStatus = KS_IDLE; + break; + + case KS_REPEAT: + if (key & kbd_rpt_mask) + { + if (now - repeat_time > repeat_rate) + { + /* Enqueue a new event in the buffer */ + key = (key & kbd_rpt_mask) | K_REPEAT; + repeat_time = now; + + /* Repeat rate acceleration */ + if (repeat_rate > ms_to_ticks(KBD_REPEAT_MAXRATE)) + repeat_rate -= ms_to_ticks(KBD_REPEAT_ACCEL); + } + else + key = 0; + } + else + kbd_rptStatus = KS_IDLE; + + break; + } + + return key; +} + + +MOD_DEFINE(kbd) + +/** + * Initialize keyboard ports and softtimer + */ +void kbd_init(void) +{ +#if CONFIG_KBD_BEEP + MOD_CHECK(buzzer); +#endif + + KBD_HW_INIT; + + /* Init handlers lists */ + LIST_INIT(&kbd_handlers); + LIST_INIT(&kbd_rawHandlers); + + /* Add debounce keyboard handler */ + kbd_debHandler.hook = kbd_debHandlerFunc; + kbd_debHandler.pri = 100; /* high priority */ + kbd_debHandler.flags = KHF_RAWKEYS; + kbd_addHandler(&kbd_debHandler); + + #if CONFIG_KBD_LONGPRESS + /* Add long pression keyboard handler */ + kbd_lngHandler.hook = kbd_lngHandlerFunc; + kbd_lngHandler.pri = 90; /* high priority */ + kbd_lngHandler.flags = KHF_RAWKEYS; + kbd_addHandler(&kbd_lngHandler); + #endif + + /* Add repeat keyboard handler */ + kbd_rptHandler.hook = kbd_rptHandlerFunc; + kbd_rptHandler.pri = 80; /* high priority */ + kbd_rptHandler.flags = KHF_RAWKEYS; + kbd_addHandler(&kbd_rptHandler); + + /* Add default keyboard handler */ + kbd_defHandler.hook = kbd_defHandlerFunc; + kbd_defHandler.pri = -128; /* lowest priority */ + kbd_addHandler(&kbd_defHandler); + +#if CONFIG_KBD_OBSERVER + observer_InitSubject(&kbd_subject); +#endif + +#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT + + MOD_CHECK(timer); + + /* Add kbd handler to soft timers list */ + event_initSoftInt(&kbd_timer.expire, kbd_softint, NULL); + timer_setDelay(&kbd_timer, ms_to_ticks(KBD_CHECK_INTERVAL)); + timer_add(&kbd_timer); + +#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS + + /* Create a timer specific thread */ + xTaskCreate(kbd_task, "kbd", CONFIG_STACK_KBD, + NULL, CONFIG_PRI_KBD, NULL); + +#else + #error "Define keyboard poll method" +#endif + + MOD_INIT(kbd); +} diff --git a/bertos/drv/kbd.h b/bertos/drv/kbd.h new file mode 100644 index 00000000..c1904716 --- /dev/null +++ b/bertos/drv/kbd.h @@ -0,0 +1,96 @@ +/** + * \file + * + * + * \brief Keyboard driver (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * \author Francesco Sacchi + */ + +#ifndef DRV_KBD_H +#define DRV_KBD_H + +#include +#include +#include +#include // CONFIG_KBD_OBSERVER + +/** + * \name Keyboard polling modes. + * + * Define CONFIG_KBD_POLL to one of these. + * + * \{ + */ +#define KBD_POLL_SOFTINT 1 +#define KBD_POLL_FREERTOS 2 +/* \} */ + +/** + * Keyboard handler descriptor + */ +typedef struct KbdHandler +{ + Node link; + keymask_t (*hook)(keymask_t); /**< Hook function */ + int8_t pri; /**< Priority in input queue */ + uint8_t flags; /**< See below for definitions */ +} KbdHandler; + +#define KHF_RAWKEYS BV(0) /**< Handler gets raw key events */ + + +void kbd_init(void); +keymask_t kbd_peek(void); +keymask_t kbd_get(void); +keymask_t kbd_get_timeout(mtime_t timeout); +void kbd_addHandler(struct KbdHandler *handler); +void kbd_remHandler(struct KbdHandler *handler); +keymask_t kbd_setRepeatMask(keymask_t mask); + +#if CONFIG_KBD_OBSERVER + struct Subject; + + /** Subject structure for keyboard observers. */ + extern struct Subject kbd_subject; + + enum + { + /* Event for key presses. */ + KBD_EVENT_KEY = 0x100 + }; +#endif + +#endif /* DRV_KBD_H */ diff --git a/bertos/drv/kdebug.c b/bertos/drv/kdebug.c new file mode 100644 index 00000000..c461b728 --- /dev/null +++ b/bertos/drv/kdebug.c @@ -0,0 +1,289 @@ +/** + * \file + * + * + * \brief General pourpose debug support for embedded systems (implementation). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#include +#include +#include + +#include /* for BV() */ +#include + +#include +#warning what about these? +//#include /* for CLOCK_FREQ */ +//#include /* Required for bus macros overrides */ + +#include /* for _formatted_write() */ +#include + +#ifdef _DEBUG + +#if CPU_HARVARD && !defined(_PROGMEM) + #error This module build correctly only in program memory! +#endif + + +#if OS_HOSTED + #include + #define KDBG_WAIT_READY() do { /*nop*/ } while(0) + #define KDBG_WRITE_CHAR(c) putc((c), stderr) + #define KDBG_MASK_IRQ(old) do { (void)(old); } while(0) + #define KDBG_RESTORE_IRQ(old) do { /*nop*/ } while(0) + typedef char kdbg_irqsave_t; /* unused */ + + #define kdbg_hw_init() do {} while (0) ///< Not needed + + #if CONFIG_KDEBUG_PORT == 666 + #error BITBANG debug console missing for this platform + #endif +#else + #include CPU_CSOURCE(kdebug) +#endif + + +void kdbg_init(void) +{ + /* Init debug hw */ + kdbg_hw_init(); + kputs("\n\n*** BeRTOS DBG START ***\n"); +} + + +/** + * Output one character to the debug console + */ +static void __kputchar(char c, UNUSED_ARG(void *, unused)) +{ + /* Poll while serial buffer is still busy */ + KDBG_WAIT_READY(); + + /* Send '\n' as '\r\n' for dumb terminals */ + if (c == '\n') + { + KDBG_WRITE_CHAR('\r'); + KDBG_WAIT_READY(); + } + + KDBG_WRITE_CHAR(c); +} + + +void kputchar(char c) +{ + /* Mask serial TX intr */ + kdbg_irqsave_t irqsave; + KDBG_MASK_IRQ(irqsave); + + __kputchar(c, 0); + + /* Restore serial TX intr */ + KDBG_RESTORE_IRQ(irqsave); +} + + +static void PGM_FUNC(kvprintf)(const char * PGM_ATTR fmt, va_list ap) +{ +#if CONFIG_PRINTF + /* Mask serial TX intr */ + kdbg_irqsave_t irqsave; + KDBG_MASK_IRQ(irqsave); + + PGM_FUNC(_formatted_write)(fmt, __kputchar, 0, ap); + + /* Restore serial TX intr */ + KDBG_RESTORE_IRQ(irqsave); +#else + /* A better than nothing printf() surrogate. */ + PGM_FUNC(kputs)(fmt); +#endif /* CONFIG_PRINTF */ +} + +void PGM_FUNC(kprintf)(const char * PGM_ATTR fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + PGM_FUNC(kvprintf)(fmt, ap); + va_end(ap); +} + +void PGM_FUNC(kputs)(const char * PGM_ATTR str) +{ + char c; + + /* Mask serial TX intr */ + kdbg_irqsave_t irqsave; + KDBG_MASK_IRQ(irqsave); + + while ((c = PGM_READ_CHAR(str++))) + __kputchar(c, 0); + + KDBG_RESTORE_IRQ(irqsave); +} + + +/** + * Cheap function to print small integers without using printf(). + */ +int kputnum(int num) +{ + int output_len = 0; + int divisor = 10000; + int digit; + + do + { + digit = num / divisor; + num %= divisor; + + if (digit || output_len || divisor == 1) + { + kputchar(digit + '0'); + ++output_len; + } + } + while (divisor /= 10); + + return output_len; +} + + +static void klocation(const char * PGM_ATTR file, int line) +{ + PGM_FUNC(kputs)(file); + kputchar(':'); + kputnum(line); + PGM_FUNC(kputs)(PGM_STR(": ")); +} + +int PGM_FUNC(__assert)(const char * PGM_ATTR cond, const char * PGM_ATTR file, int line) +{ + klocation(file, line); + PGM_FUNC(kputs)(PGM_STR("Assertion failed: ")); + PGM_FUNC(kputs)(cond); + kputchar('\n'); + BREAKPOINT; + return 1; +} + +/* + * Unfortunately, there's no way to get __func__ in + * program memory, so we waste quite a lot of RAM in + * AVR and other Harvard processors. + */ +void PGM_FUNC(__trace)(const char *name) +{ + PGM_FUNC(kprintf)(PGM_STR("%s()\n"), name); +} + +void PGM_FUNC(__tracemsg)(const char *name, const char * PGM_ATTR fmt, ...) +{ + va_list ap; + + PGM_FUNC(kprintf)(PGM_STR("%s(): "), name); + va_start(ap, fmt); + PGM_FUNC(kvprintf)(fmt, ap); + va_end(ap); + kputchar('\n'); +} + +int PGM_FUNC(__invalid_ptr)(void *value, const char * PGM_ATTR name, const char * PGM_ATTR file, int line) +{ + klocation(file, line); + PGM_FUNC(kputs)(PGM_STR("Invalid ptr: ")); + PGM_FUNC(kputs)(name); + #if CONFIG_PRINTF + PGM_FUNC(kprintf)(PGM_STR(" = 0x%p\n"), value); + #else + (void)value; + kputchar('\n'); + #endif + return 1; +} + + +void __init_wall(long *wall, int size) +{ + while(size--) + *wall++ = WALL_VALUE; +} + + +int PGM_FUNC(__check_wall)(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line) +{ + int i, fail = 0; + + for (i = 0; i < size; i++) + { + if (wall[i] != WALL_VALUE) + { + klocation(file, line); + PGM_FUNC(kputs)(PGM_STR("Wall broken: ")); + PGM_FUNC(kputs)(name); + #if CONFIG_PRINTF + PGM_FUNC(kprintf)(PGM_STR("[%d] (0x%p) = 0x%lx\n"), i, wall + i, wall[i]); + #else + kputchar('\n'); + #endif + fail = 1; + } + } + + return fail; +} + + +#if CONFIG_PRINTF + +/** + * Dump binary data in hex + */ +void kdump(const void *_buf, size_t len) +{ + const unsigned char *buf = (const unsigned char *)_buf; + + while (len--) + kprintf("%02X", *buf++); + kputchar('\n'); +} + +#endif /* CONFIG_PRINTF */ + +#endif /* _DEBUG */ diff --git a/bertos/drv/lcd_gfx.h b/bertos/drv/lcd_gfx.h new file mode 100644 index 00000000..63fe28d2 --- /dev/null +++ b/bertos/drv/lcd_gfx.h @@ -0,0 +1,37 @@ +/** + * \file + * + * + * \version $Id: lcd_gfx.h,v 1.6 2006/07/19 12:56:25 bernie Exp $ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief Displaytech 32122A LCD driver + */ +#ifndef LCD_GFX_H +#define LCD_GFX_H + +/* Predefined LCD PWM contrast values */ +#define LCD_DEF_PWM 145 +#define LCD_MAX_PWM 505 +#define LCD_MIN_PWM 130 + +/* Display bitmap dims */ +#define LCD_WIDTH 128 +#define LCD_HEIGHT 64 + +/* fwd decl */ +struct Bitmap; + +extern struct Bitmap lcd_bitmap; + +void lcd_init(void); +void lcd_setPwm(int duty); +void lcd_blitBitmap(struct Bitmap *bm); + +#endif /* LCD_GFX_H */ diff --git a/bertos/drv/lcd_gfx_qt.cpp b/bertos/drv/lcd_gfx_qt.cpp new file mode 100644 index 00000000..e42be22d --- /dev/null +++ b/bertos/drv/lcd_gfx_qt.cpp @@ -0,0 +1,164 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Custom control for graphics LCD emulation (interface) + */ + +#include "lcd_gfx_qt.h" +#include +#include +#include // CONFIG_BITMAP_FMT + +#include +#include +#include +#include + +// Display colors +#define LCD_FG_COLOR 0x0, 0x0, 0x0 +#define LCD_BG_COLOR 0xBB, 0xCC, 0xBB + + +EmulLCD::EmulLCD(QWidget *parent, const char *name) : + QFrame(parent, name, Qt::WRepaintNoErase | Qt::WResizeNoErase), + fg_color(LCD_FG_COLOR), + bg_color(LCD_BG_COLOR) +{ + // initialize bitmap + memset(raster, 0xAA, sizeof(raster)); + + // set widget frame + setFrameStyle(QFrame::Panel | QFrame::Sunken); + frame_width = frameWidth(); +} + + +EmulLCD::~EmulLCD() +{ + // nop +} + + +QSizePolicy EmulLCD::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, false); +} + + +QSize EmulLCD::sizeHint() const +{ + return QSize( + WIDTH + frame_width * 2, + HEIGHT + frame_width * 2); +} + + +void EmulLCD::paintEvent(QPaintEvent * /*event*/) +{ + QPainter p(this); + QImage img(raster, WIDTH, HEIGHT, 1, NULL, 0, QImage::BigEndian); + + p.setBackgroundMode(Qt::OpaqueMode); + p.setPen(fg_color); + p.setBackgroundColor(bg_color); + p.drawImage(frame_width, frame_width, img); +} + +void EmulLCD::writeRaster(uint8_t *new_raster) +{ +#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB + + /* Straight copy */ + memcpy(raster, new_raster, sizeof(raster)); + +#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB + + /* Rotation */ + for (int y = 0; y < HEIGHT; ++y) + { + for (int xbyte = 0; xbyte < WIDTH/8; ++xbyte) + { + uint8_t v = 0; + for (int xbit = 0; xbit < 8; ++xbit) + v |= (new_raster[(xbyte * 8 + xbit) + (y / 8) * WIDTH] & (1 << (y%8)) ) + ? 0 : (1 << (7 - xbit)); + + raster[y * ((WIDTH + 7) / 8) + xbyte] = v; + } + } + +#else + #error Unsupported bitmap format +#endif + + repaint(); +} + + + +#include +#include + +DECLARE_WALL(wall_before_raster, WALL_SIZE) +/** + * Raster buffer to draw into. + * + * Bits in the bitmap bytes have vertical orientation, + * as required by the LCD driver. + */ +static uint8_t lcd_raster[RAST_SIZE(EmulLCD::WIDTH, EmulLCD::HEIGHT)]; +DECLARE_WALL(wall_after_raster, WALL_SIZE) + +/** Default LCD bitmap */ +struct Bitmap lcd_bitmap; + +/*extern "C"*/ void lcd_init(void) +{ + //FIXME INIT_WALL(wall_before_raster); + //FIXME INIT_WALL(wall_after_raster); + gfx_bitmapInit(&lcd_bitmap, lcd_raster, EmulLCD::WIDTH, EmulLCD::HEIGHT); + gfx_bitmapClear(&lcd_bitmap); +} + +/*extern "C"*/ void lcd_blitBitmap(Bitmap *bm) +{ + //FIXME CHECK_WALL(wall_before_raster); + //FIXME CHECK_WALL(wall_after_raster); + emul->emulLCD->writeRaster(bm->raster); +} + +#include "lcd_gfx_qt_moc.cpp" + diff --git a/bertos/drv/lcd_gfx_qt.h b/bertos/drv/lcd_gfx_qt.h new file mode 100644 index 00000000..7893dc73 --- /dev/null +++ b/bertos/drv/lcd_gfx_qt.h @@ -0,0 +1,105 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Custom control for graphics LCD emulation (interface) + */ + +/*#* + *#* $Log$ + *#* Revision 1.5 2006/05/28 12:17:57 bernie + *#* Drop almost all the Qt3 cruft. + *#* + *#* Revision 1.4 2006/02/20 02:00:40 bernie + *#* Port to Qt 4.1. + *#* + *#* Revision 1.3 2006/02/15 09:13:16 bernie + *#* Switch to BITMAP_FMT_PLANAR_V_LSB. + *#* + *#* Revision 1.2 2006/02/10 12:33:51 bernie + *#* Make emulator display a bit larger. + *#* + *#* Revision 1.1 2006/01/16 03:51:35 bernie + *#* Add LCD Qt emulator. + *#* + *#*/ + +#ifndef DRV_LCD_GFX_QT_H +#define DRV_LCD_GFX_QT_H + +#include +#include + +// fwd decls +class QSizePolicy; +class QPaintEvent; +class QResizeEvent; + + +class EmulLCD : public QFrame +{ + Q_OBJECT + +public: +// Attributes + enum { WIDTH = 128, HEIGHT = 64 }; + +// Construction + EmulLCD(QWidget *parent = 0, const char *name = 0); + virtual ~EmulLCD(); + +// Base class overrides +protected: + virtual QSizePolicy sizePolicy() const; + virtual QSize sizeHint() const; + virtual void paintEvent(QPaintEvent *event); + +// Operations +public: + void writeRaster(uint8_t *raster); + +// Implementation +protected: + /// Frame thickness + int frame_width; + + /// LCD colors + QColor fg_color, bg_color; + + /// Pixel storage + unsigned char raster[(WIDTH * HEIGHT) / 8]; +}; + +#endif // DRV_LCD_GFX_QT_H diff --git a/bertos/drv/lcd_gfx_test.c b/bertos/drv/lcd_gfx_test.c new file mode 100644 index 00000000..121555f7 --- /dev/null +++ b/bertos/drv/lcd_gfx_test.c @@ -0,0 +1,98 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief dot-matrix LCD test. + */ + +/*#* + *#* $Log$ + *#* Revision 1.3 2006/01/17 23:00:26 bernie + *#* Don't use hardcoded coordinates. + *#* + *#* Revision 1.2 2006/01/17 02:31:57 bernie + *#* Test gfx with the usual pentagons. + *#* + *#* Revision 1.1 2006/01/16 03:51:35 bernie + *#* Add LCD Qt emulator. + *#* + *#*/ + +#include +#include +#include + +static void magic(struct Bitmap *bitmap, coord_t x, coord_t y) +{ + static const coord_t coords[] = { 120, 34, 90, 90, 30, 90, 0, 34, 60, 0, 90, 90, 0, 34, 120, 34, 30, 90, 60, 0 }; + unsigned int i; + + gfx_moveTo(bitmap, coords[countof(coords)-2]/2 + x, coords[countof(coords)-1]/3 + y); + for (i = 0; i < countof(coords); i += 2) + gfx_lineTo(bitmap, coords[i]/2 + x, coords[i+1]/3 + y); +} + +int main(int argc, char *argv[]) +{ + emul_init(&argc, argv); + lcd_init(); + + coord_t x = 0, y = LCD_WIDTH / 2; + coord_t xdir = +1, ydir = -1; + Bitmap *bm = &lcd_bitmap; + + for(;;) + { + gfx_bitmapClear(bm); + gfx_setClipRect(bm, 0, 0, bm->width, bm->height); + gfx_rectDraw(bm, 10, 10, bm->width-10, bm->height-10); + gfx_setClipRect(bm, 11, 11, bm->width-11, bm->height-11); + magic(bm, x, y); + + x += xdir; + y += ydir; + if (x >= bm->width) xdir = -1; + if (x <= -50) xdir = +1; + if (y >= bm->height) ydir = -1; + if (y <= -50) ydir = +1; + + lcd_blit_bitmap(bm); + emul_idle(); + usleep(10000); + } + + emul_cleanup(); + return 0; +} diff --git a/bertos/drv/lcd_hd44.c b/bertos/drv/lcd_hd44.c new file mode 100644 index 00000000..1c2e52f7 --- /dev/null +++ b/bertos/drv/lcd_hd44.c @@ -0,0 +1,457 @@ +/** + * \file + * + * + * \brief LM044L type LCD hardware module (impl.) + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#include "lcd_hd44.h" +#include "hw_lcd.h" +#include +#include + +#if defined(LCD_READ_H) && defined(LCD_READ_L) && defined(LCD_WRITE_H) && defined(LCD_WRITE_L) + #define CONFIG_LCD_4BIT 1 +#elif defined(LCD_READ) && defined(LCD_WRITE) + #define CONFIG_LCD_4BIT 0 +#else + #error Incomplete or missing LCD_READ/LCD_WRITE macros +#endif + +/** Flag di stato del display */ +#define LCDF_BUSY BV(7) + +#if CONFIG_LCD_ADDRESS_FAST == 1 +#define lcd_address(x) lcd_address[x] +/** + * Addresses of LCD display character positions, expanded + * for faster access (DB7 = 1). + */ +static const uint8_t lcd_address[] = +{ + /* row 0 */ + 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, + 0x8C, 0x8D, 0x8E, 0x8F, +#if LCD_COLS > 16 + 0x90, 0x91, 0x92, 0x93, +#endif + + /* row 1 */ + 0xC0, 0xC1, 0xC2, 0xC3, + 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, + 0xCC, 0xCD, 0xCE, 0xCF, +#if LCD_COLS > 16 + 0xD0, 0xD1, 0xD2, 0xD3, +#endif + +#if LCD_ROWS > 2 + /* row 2 */ + 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, + 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, +#if LCD_COLS > 16 + 0xA4, 0xA5, 0xA6, 0xA7, +#endif + + /* row 3 */ + 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, + 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, +#if LCD_COLS > 16 + 0xE4, 0xE5, 0xE6, 0xE7, +#endif + +#endif /* LCD_ROWS > 2 */ +}; + +STATIC_ASSERT(countof(lcd_address) == LCD_ROWS * LCD_COLS); +#else /* CONFIG_LCD_ADDRESS_FAST == 0 */ + +static const uint8_t col_address[] = +{ + 0x80, + 0xC0, +#if LCD_ROWS > 2 + 0x94, + 0xD4 +#endif +}; +STATIC_ASSERT(countof(col_address) == LCD_ROWS); +/** + * Addresses of LCD display character positions, calculated runtime to save RAM + */ +static uint8_t lcd_address(uint8_t addr) +{ + return col_address[addr / LCD_COLS] + addr % LCD_COLS; +} +#endif /* CONFIG_LCD_ADDRESS_FAST */ + +/** + * Current display position. We remember this to optimize + * LCD output by avoiding to set the address every time. + */ +static lcdpos_t lcd_current_addr; + + +#if !defined(ARCH_EMUL) || !(ARCH & ARCH_EMUL) +/* __________________ + * RS + * + * R/W __________________ + * _______ + * ENA _____/ \____ + * + * DATA -<================ + */ +INLINE void lcd_dataWrite(uint8_t data) +{ +#if CONFIG_LCD_4BIT + /* Write high nibble */ + LCD_WRITE_H(data); + LCD_SET_E; + LCD_DELAY_WRITE; + LCD_CLR_E; + LCD_DELAY_WRITE; + + /* Write low nibble */ + LCD_WRITE_L(data); + LCD_SET_E; + LCD_DELAY_WRITE; + LCD_CLR_E; + LCD_DELAY_WRITE; + +#else /* !CONFIG_LCD_4BIT */ + + /* Write data */ + LCD_WRITE(data); + LCD_SET_E; + LCD_DELAY_WRITE; + LCD_CLR_E; + LCD_DELAY_WRITE; + +#endif /* !CONFIG_LCD_4BIT */ +} + +/* __________________ + * RS + * ____________ + * R/W __/ \__ + * _______ + * ENA _____/ \____ + * ______ ____ + * DATA X/ \====/ + */ +INLINE uint8_t lcd_dataRead(void) +{ + uint8_t data; + + LCD_SET_RD; + LCD_DB_IN; /* Set bus as input! */ + LCD_DELAY_READ; + +#if CONFIG_LCD_4BIT + + /* Read high nibble */ + LCD_SET_E; + LCD_DELAY_READ; + data = LCD_READ_H; + LCD_CLR_E; + LCD_DELAY_READ; + + /* Read low nibble */ + LCD_SET_E; + LCD_DELAY_READ; + data |= LCD_READ_L; + LCD_CLR_E; + LCD_DELAY_READ; + +#else /* !CONFIG_LCD_4BIT */ + + /* Read data */ + LCD_SET_E; + LCD_DELAY_READ; + data = LCD_READ; + LCD_CLR_E; + LCD_DELAY_READ; + +#endif /* !CONFIG_LCD_4BIT */ + + LCD_CLR_RD; + LCD_DB_OUT; /* Reset bus as output! */ + + return data; +} + +/* ___ __ + * RS \___________/ + * + * READ __________________ + * _______ + * ENA _____/ \____ + * + * DATA --<=============== + */ +INLINE void lcd_regWrite(uint8_t data) +{ + LCD_CLR_RS; + lcd_dataWrite(data); + LCD_SET_RS; +} + +/* __ _ + * RS \_____________/ + * ___________ + * READ ___/ \__ + * _______ + * ENA _____/ \____ + * ______ ____ + * DATA X/ \====/ + */ +INLINE uint8_t lcd_regRead(void) +{ + uint8_t data; + + LCD_CLR_RS; + data = lcd_dataRead(); + LCD_SET_RS; + return data; +} + +#if CONFIG_LCD_4BIT + +INLINE void lcd_mode4Bit(void) +{ + LCD_CLR_RS; + + LCD_WRITE_H(LCD_CMD_SETFUNC); + LCD_SET_E; + LCD_DELAY_WRITE; + LCD_CLR_E; + LCD_DELAY_WRITE; + + LCD_SET_RS; +} + +#endif /* CONFIG_LCD_4BIT */ + +#else /* ARCH_EMUL */ + +extern void Emul_LCDWriteReg(uint8_t d); +extern uint8_t Emul_LCDReadReg(void); +extern void Emul_LCDWriteData(uint8_t d); +extern uint8_t Emul_LCDReadData(void); + +#define lcd_regWrite(d) Emul_LCDWriteReg(d) +#define lcd_regRead(d) Emul_LCDReadReg() +#define lcd_dataWrite(d) Emul_LCDWriteData(d) +#define lcd_dataRead(d) Emul_LCDReadData() + +#endif /* ARCH_EMUL */ + + +/** + * Wait until the LCD busy flag clears. + */ +void lcd_waitBusy(void) +{ + for (;;) + { + uint8_t val = lcd_regRead(); + if (!(val & LCDF_BUSY)) + break; + } +} + + +/** + * Move the cursor to \a addr, only if not already there. + */ +void lcd_moveTo(uint8_t addr) +{ + if (addr != lcd_current_addr) + { + lcd_waitBusy(); + lcd_regWrite(lcd_address(addr)); + lcd_current_addr = addr; + } +} + + +/** + * Write a value in LCD data register, waiting for the busy flag. + */ +void lcd_setReg(uint8_t val) +{ + lcd_waitBusy(); + lcd_regWrite(val); +} + +#include +/** + * Write the character \a c on display address \a addr. + * + * NOTE: argh, the HD44 lcd type is a bad beast: our + * move/write -> write optimization requires this mess + * because display lines are interleaved! + */ +void lcd_putc(uint8_t addr, uint8_t c) +{ + if (addr != lcd_current_addr) + lcd_setReg(lcd_address(addr)); + + lcd_waitBusy(); + lcd_dataWrite(c); + lcd_current_addr = addr + 1; + + /* If we are at end of display wrap the address to 0 */ + if (lcd_current_addr == LCD_COLS * LCD_ROWS) + lcd_current_addr = 0; + + /* If we are at the end of a row put the cursor at the beginning of the next */ + if (!(lcd_current_addr % LCD_COLS)) + lcd_setReg(lcd_address(lcd_current_addr)); +} + + +/** + * Remap the glyph of a character. + * + * glyph - bitmap of 8x8 bits. + * code - must be 0-7 for the Hitachi LCD-II controller. + */ +void lcd_remapChar(const char *glyph, char code) +{ + int i; + + /* Set CG RAM address */ + lcd_setReg((uint8_t)((1<<6) | (code << 3))); + + /* Write bitmap data */ + for (i = 0; i < 8; i++) + { + lcd_waitBusy(); + lcd_dataWrite(glyph[i]); + } + + /* Move back to original address */ + lcd_setReg(lcd_address(lcd_current_addr)); +} + + +#if 0 /* unused */ +void lcd_remapfont(void) +{ + static const char lcd_glyphs[8] = + { + 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x04, 0x00 /* up arrow */ + }; + int i; + + for (i = 0; i < 15; i++) + lcd_remapChar(i, bernie_char); + + + lcd_setAddr(lcd_DefLayer, 0); + for (i = 0; i < 80; i++) + lcd_putCharUnlocked(i); +} +#endif /* unused */ + +void lcd_hw_init(void) +{ + lcd_bus_init(); + + timer_delay(50); + +#if CONFIG_LCD_4BIT + lcd_mode4Bit(); + timer_delay(2); +#endif /* CONFIG_LCD_4BIT */ + + lcd_regWrite(LCD_CMD_SETFUNC); + timer_delay(2); + + lcd_regWrite(LCD_CMD_DISPLAY_ON); + timer_delay(2); + + lcd_regWrite(LCD_CMD_CLEAR); + timer_delay(2); + +#if !CONFIG_LCD_4BIT + lcd_regWrite(LCD_CMD_RESET_DDRAM); // 4 bit mode doesn't allow char reprogramming +#endif + lcd_regWrite(LCD_CMD_DISPLAYMODE); + timer_delay(2); +} + +#if CONFIG_TEST + +void lcd_hw_test(void) +{ + lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 3); + timer_delay(1); + kprintf("3 -> %02X\n", lcd_regRead()); + timer_delay(1); + + for (int i = 0; i < 10; i++) + { + lcd_dataWrite('c'); + timer_delay(1); + kprintf("addr = %02X\n", lcd_regRead()); + timer_delay(1); + } + + lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x4a); + timer_delay(1); + kprintf("4A -> %02X\n", lcd_regRead()); + timer_delay(1); + + lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x52); + timer_delay(1); + kprintf("52 -> %02X\n", lcd_regRead()); + timer_delay(1); + + lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x1F); + timer_delay(1); + kprintf("1F -> %02X\n", lcd_regRead()); + timer_delay(1); +} + +#endif /* CONFIG_TEST */ diff --git a/bertos/drv/lcd_hd44.h b/bertos/drv/lcd_hd44.h new file mode 100644 index 00000000..0ebba974 --- /dev/null +++ b/bertos/drv/lcd_hd44.h @@ -0,0 +1,92 @@ +/** + * \file + * + * + * \brief Hitachi HD44780 and clones LCD module (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#ifndef DRV_LCD_HD44_H +#define DRV_LCD_HD44_H + +#include +#include /* For stdint types */ + +/** + * \name Display dimensions (in chars) + * \{ + */ +#define LCD_ROWS 2 +#define LCD_COLS 16 +/* \} */ + +/** + * \name Hitachi HD44 commands. + * \{ + */ +#define LCD_CMD_DISPLAY_INI 0x30 + +#if CONFIG_LCD_4BIT + #define LCD_CMD_SETFUNC 0x28 /**< 4 bits, 2 lines, 5x7 dots */ +#else + #define LCD_CMD_SETFUNC 0x38 /**< 8 bits, 2 lines, 5x7 dots */ +#endif + +#define LCD_CMD_DISPLAY_ON 0x0F /**< Switch on display */ +#define LCD_CMD_DISPLAY_OFF 0x08 /**< Switch off display */ +#define LCD_CMD_CLEAR 0x01 /**< Clear display */ +#define LCD_CMD_CURSOR_BLOCK 0x0D /**< Show cursor (block) */ +#define LCD_CMD_CURSOR_LINE 0x0F /**< Show cursor (line) */ +#define LCD_CMD_CURSOR_OFF 0x0C /**< Hide cursor */ +#define LCD_CMD_DISPLAYMODE 0x06 +#define LCD_CMD_SET_CGRAMADDR 0x40 +#define LCD_CMD_RESET_DDRAM 0x80 +#define LCD_CMD_SET_DDRAMADDR 0x80 +#define LCD_CMD_DISPLAY_SHIFT 0x18 +#define LCD_CMD_MOVESHIFT_LEFT 0x00 +#define LCD_CMD_MOVESHIFT_RIGHT 0x04 +/*\}*/ + +/** Type for combined LCD cursor position (x,y). */ +typedef uint8_t lcdpos_t; + +void lcd_waitBusy(void); +void lcd_moveTo(uint8_t addr); +void lcd_setReg(uint8_t val); +void lcd_putc(uint8_t a, uint8_t c); +void lcd_remapChar(const char *glyph, char code); +void lcd_hw_init(void); +void lcd_hw_test(void); + +#endif /* DRV_LCD_HD44_H */ diff --git a/bertos/drv/lcd_lm44_qt.cpp b/bertos/drv/lcd_lm44_qt.cpp new file mode 100644 index 00000000..a8942699 --- /dev/null +++ b/bertos/drv/lcd_lm44_qt.cpp @@ -0,0 +1,362 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Custom Qt widget for emulating a graphics LCD display (implementation) + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/01/16 03:51:35 bernie + *#* Add LCD Qt emulator. + *#* + *#*/ + +#include +#include +#include +#include +#include "EmulLCD.h" +#include "Emul.h" + + +// Display colors +#define LCD_FG_COLOR 0x0, 0x0, 0x0 +#define LCD_BG_COLOR 0xBB, 0xCC, 0xBB + + +EmulLCD::EmulLCD(QWidget *parent, const char *name) : + QFrame(parent, name, WRepaintNoErase | WResizeNoErase), + lcd_font("courier", 18), + fg_color(LCD_FG_COLOR), + bg_color(LCD_BG_COLOR), + cr_row(0), + cr_col(0), + cgramaddr(-1), + show_cursor(true) +{ + // initialize DDRAM + memcpy(ddram, + "01234567890123456789" + "abcdefghijhlmnopqrst" + "ABCDEFGHIJKLMNOPQRST" + "!@#$%^&*()_+|{}':?><", + sizeof(ddram)); + + // setup font + lcd_font.setFixedPitch(true); + setFont(lcd_font); + + // get exact font size + QFontMetrics fm(lcd_font); + font_width = fm.width(QChar(' ')); + font_height = fm.height(); + + // set widget frame + setFrameStyle(QFrame::Panel | QFrame::Sunken); +// setLineWidth(2); + frame_width = frameWidth(); +} + + +EmulLCD::~EmulLCD() +{ + // nop +} + + +QSizePolicy EmulLCD::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, false); +} + + +QSize EmulLCD::sizeHint() const +{ + return QSize( + font_width * COLS + frame_width * 2, + font_height * ROWS + frame_width * 2); +} + + +void EmulLCD::drawContents(QPainter *p) +{ + RedrawText(*p); +} + + +void EmulLCD::SetPainter(QPainter & p) +{ + p.setBackgroundMode(OpaqueMode); + p.setPen(fg_color); + p.setBackgroundColor(bg_color); +} + + +void EmulLCD::RedrawText(QPainter & p) +{ + int r, c; + + SetPainter(p); + + for (r = 0; r < ROWS; r++) + for (c = 0; c < COLS; c++) + PrintChar(p, r, c); +} + + +void EmulLCD::PrintChar(QPainter & p, int row, int col) +{ + // Fetch char from DD RAM + unsigned char c = ddram[row][col]; + + // Map some Hitachi characters to ISO Latin1 + switch(c) + { + case 0xDF: + c = 0xBA; // "degrees" glyph + break; + + case 0xE4: + c = 0xB5; // "micro" glyph + break; + + default: // all others + break; + } + + // Draw char on display + int x = col * font_width + frame_width; + int y = row * font_height + frame_width; + bool restore_colors = false; + + if (show_cursor && (row == cr_row) && (col == cr_col)) + { + // Exchange FG/BG colors + p.setPen(bg_color); + p.setBackgroundColor(fg_color); + restore_colors = true; + } + + p.drawText(x, y, x + font_width, y + font_height, 0 /*tf*/, + QString(QChar(c)), 1); + + if (restore_colors) + { + // Restore FG/BG colors + p.setPen(fg_color); + p.setBackgroundColor(bg_color); + } +} + + +void EmulLCD::MoveCursor(int r, int c) +{ + // Save old cursor position + int old_row = cr_row; + int old_col = cr_col; + + // Move the cursor + cgramaddr = -1; + cr_row = r; + cr_col = c; + + if (show_cursor && (old_col != cr_col || old_row != cr_row)) + { + QPainter p(this); + SetPainter(p); + + // Draw new cursor + PrintChar(p, cr_row, cr_col); + + // Erase old cursor + PrintChar(p, old_row, old_col); + } +} + + +void EmulLCD::ShowCursor(bool show) +{ + show_cursor = show; + + // Draw (or erase) cursor + QPainter p(this); + SetPainter(p); + PrintChar(p, cr_row, cr_col); +} + + +void EmulLCD::AdvanceCursor() +{ + // Move the cursor + if (cr_col == COLS - 1) + { + if (cr_row == ROWS - 1) + MoveCursor(0, 0); + else + MoveCursor(cr_row + 1, 0); + } + else + MoveCursor(cr_row, cr_col + 1); +} + + +void EmulLCD::PutChar(unsigned char c) +{ + if (cgramaddr != -1) + { + // Write data in CGRAM + cgram[cgramaddr] = c; + + // Auto increment CGRAM address + cgramaddr = (cgramaddr + 1) & 0x3F; + } + else + { + // Writing in DDRAM + ddram[cr_row][cr_col] = c; + + // Update display + { + QPainter p(this); + SetPainter(p); + PrintChar(p, cr_row, cr_col); + } + AdvanceCursor(); + } +} + + +char EmulLCD::GetChar() +{ + char c = ddram[cr_row][cr_col]; + AdvanceCursor(); + return c; +} + + +void EmulLCD::Clear() +{ + memset(ddram, ' ', sizeof(ddram)); + cr_row = cr_col = 0; + + QPainter p(this); + RedrawText(p); +} + + +void EmulLCD::SetCGRamAddr(unsigned char addr) +{ + cgramaddr = addr & (sizeof(cgram) - 1); +} + + +// Hitachi LM044L register-level emulation + +#define INI_DISPLAY 0x30 +#define INI_OP_DISP 0x38 /* 8 bits, 2 lines, 5x7 dots */ +#define ON_DISPLAY 0x0F /* Switch on display */ +#define OFF_DISPLAY 0x08 /* Switch off display */ +#define CLR_DISPLAY 0x01 /* Clear display */ +#define CURSOR_BLOCK 0x0D /* Show cursor (block) */ +#define CURSOR_LINE 0x0F /* Show cursor (line) */ +#define CURSOR_OFF 0x0C /* Hide cursor */ +#define MODE_DISPL 0x06 +#define SHIFT_DISPLAY 0x18 +#define MOVESHIFT_LEFT 0x00 +#define MOVESHIFT_RIGHT 0x04 +#define LCD_CGRAMADDR (1<<6) +#define LCD_DDRAMADDR (1<<7) + + +extern "C" void Emul_LCDWriteReg(unsigned char d) +{ + static const unsigned char lcd_rowaddress[EmulLCD::ROWS] = { 0x80, 0xC0, 0x94, 0xD4 }; + + switch(d) + { + case CLR_DISPLAY: + emul->emulLCD->Clear(); + break; + + case CURSOR_BLOCK: + case CURSOR_LINE: + emul->emulLCD->ShowCursor(true); + break; + + case CURSOR_OFF: + emul->emulLCD->ShowCursor(false); + break; + + default: + // Set DDRAM address? + if (d & LCD_DDRAMADDR) + { + for (int i = 0; i < EmulLCD::ROWS; i++) + { + if ((d >= lcd_rowaddress[i]) && (d < lcd_rowaddress[i] + EmulLCD::COLS)) + { + emul->emulLCD->MoveCursor(i, d - lcd_rowaddress[i]); + break; + } + } + } + else if (d & LCD_CGRAMADDR) + emul->emulLCD->SetCGRamAddr(d); + break; + } +} + + +extern "C" unsigned char Emul_LCDReadReg(void) +{ + return 0; /* This LCD model is never busy ;-) */ +} + + +extern "C" void Emul_LCDWriteData(unsigned char d) +{ + emul->emulLCD->PutChar(d); +} + + +extern "C" unsigned char Emul_LCDReadData(void) +{ + return emul->emulLCD->GetChar(); +} + +#include "EmulLCD.moc" + diff --git a/bertos/drv/lcd_lm44_qt.h b/bertos/drv/lcd_lm44_qt.h new file mode 100644 index 00000000..da01e62e --- /dev/null +++ b/bertos/drv/lcd_lm44_qt.h @@ -0,0 +1,109 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Custom Qt widget for emulating a graphics LCD display (implementation) + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/01/16 03:51:35 bernie + *#* Add LCD Qt emulator. + *#* + *#*/ + +#ifndef EMULLCD_H +#define EMULLCD_H + +#include +#include +#include + +// fwd decls +class QSizePolicy; +class QPaintEvent; +class QResizeEvent; + +/** + * Qt widget to emulate a dot-matrix LCD display. + */ +class EmulLCD : public QFrame +{ + Q_OBJECT + +public: +// Attributes + enum { COLS = 20, ROWS = 4 }; + +// Construction + EmulLCD(QWidget *parent = 0, const char *name = 0); + virtual ~EmulLCD(); + +// Base class overrides +protected: + virtual QSizePolicy sizePolicy() const; + virtual QSize sizeHint() const; + virtual void drawContents(QPainter *p); + +// Operations +public: + void MoveCursor (int col, int row); + void ShowCursor (bool show = true); + void PutChar (unsigned char c); + char GetChar (); + void Clear (); + void SetCGRamAddr (unsigned char addr); + +// Implementation +protected: + void SetPainter(QPainter & p); + void RedrawText(QPainter & p); + void PrintChar(QPainter & p, int row, int col); + void AdvanceCursor(); + + QFont lcd_font; ///< Display character font + QColor fg_color, bg_color; ///< LCD colors + int font_width, font_height; ///< Font dimensions + int frame_width; ///< Frame width (and height) + int cr_row, cr_col; ///< Cursor position + int cgramaddr; ///< CGRAM Address (-1 disabled) + unsigned char ddram[ROWS][COLS];///< Display data RAM + unsigned char cgram[8*8]; ///< CGRAM + bool show_cursor; ///< Cursor enabled? +}; + +#endif // !defined(EMULLCD_H) + diff --git a/bertos/drv/lcd_text.c b/bertos/drv/lcd_text.c new file mode 100644 index 00000000..8e519280 --- /dev/null +++ b/bertos/drv/lcd_text.c @@ -0,0 +1,499 @@ +/** + * \file + * + * + * \brief Generic text LCD driver (impl.). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/09/20 20:02:43 marco + *#* Replaced ISLISTEMPTY with LIST_EMPTY + *#* + *#* Revision 1.3 2006/07/19 12:56:25 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.2 2006/02/24 00:27:14 bernie + *#* Use new naming convention for list macros. + *#* + *#* Revision 1.1 2005/11/04 18:00:42 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.11 2005/06/14 14:43:43 bernie + *#* Add DevLib headers. + *#* + *#* Revision 1.10 2005/06/06 17:41:57 batt + *#* Add lcd_layerSet function. + *#* + *#* Revision 1.9 2005/06/01 16:40:07 batt + *#* Remove debug string. + *#* + *#* Revision 1.8 2005/06/01 16:38:04 batt + *#* Adapt to changes in mware/list.h. + *#* + *#* Revision 1.7 2005/06/01 10:45:22 batt + *#* lcd_setAddr(): Bugfix boundary condition; Misc cleanup. + *#* + *#* Revision 1.6 2005/06/01 10:36:23 batt + *#* Layer: Rename member variables and Doxygenize. + *#* + *#* Revision 1.5 2005/05/27 11:05:58 batt + *#* Do not write on lcd if layer is hidden. + *#*/ + +#include "lcd_text.h" +#include "lcd_hd44.h" +#include // timer_delay() +#include // _formatted_write() +#include // LIST_EMPTY() +#include // BV() +#include + +#include // strlen() + + +/** Maximum number of layers. */ +#define LCD_LAYERS 6 + +#if CONFIG_KERNEL + /** Semaphore to arbitrate access to the display. */ + static struct Semaphore lcd_semaphore; + #define LOCK_LCD sem_obtain(&lcd_semaphore) + #define UNLOCK_LCD sem_release(&lcd_semaphore) +#else /* !CONFIG_KERNEL */ + #define LOCK_LCD do {} while (0) + #define UNLOCK_LCD do {} while (0) +#endif /* !CONFIG_KERNEL */ + +DECLARE_LIST_TYPE(Layer); + +Layer *lcd_DefLayer; +static Layer lcd_LayersPool[LCD_LAYERS]; +static LIST_TYPE(Layer) lcd_Layers; +static LIST_TYPE(Layer) lcd_FreeLayers; + +/** + * Current cursor status. + * + * One of LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK or LCD_CMD_CURSOR_LINE. + */ +static uint8_t lcd_CursorStatus; + +/** Current cursor position, encoded as a Cursor position and status. */ +static lcdpos_t lcd_CursorAddr; + + +void lcd_setAddr(Layer *layer, lcdpos_t addr) +{ + /* Sanity check: wrap around to display limits */ + while (addr >= LCD_ROWS * LCD_COLS) + addr -= LCD_ROWS * LCD_COLS; + + layer->addr = addr; +} + +#if CONFIG_KERNEL + +void lcd_lock(void) +{ + LOCK_LCD; +} + + +void lcd_unlock(void) +{ + UNLOCK_LCD; +} + +#endif /* CONFIG_KERNEL */ + + +/** + * Write one character to the display at the current + * cursor prosition, then move the cursor right. The + * cursor is wrapped to the next line when it moves + * beyond the end of the current line. + * + * \note Does _NOT_ lock the display semaphore. + */ +static void lcd_putCharUnlocked(char c, Layer *layer) +{ + Layer *l2; + lcdpos_t addr = layer->addr; + + /* Store character in layer buffer */ + layer->buf[addr] = c; + + /* Move to next character */ + if (++layer->addr >= LCD_COLS * LCD_ROWS) + layer->addr = 0; + + /* Do not write on LCD if layer is hidden. */ + if (layer->pri == LAYER_HIDDEN) + return; + + /* + * Check if this location is obscured by + * other layers above us. + */ + for (l2 = layer->pred; l2->pred; l2 = l2->pred) + { + if (l2->buf[addr]) + { + /* DB(kprintf("layer %04x obs %04x at %d\n", l2, layer, addr);) */ + return; + } + } + + /* Write character */ + if (c) + lcd_putc(addr, c); + else + /* FIXME: should look for layers beneath! */ + lcd_putc(addr, ' '); +} + + +void lcd_putChar(char c, Layer *layer) +{ + LOCK_LCD; + lcd_putCharUnlocked(c, layer); + UNLOCK_LCD; +} + +void lcd_layerSet(Layer *layer, char c) +{ + int i; + + LOCK_LCD; + lcd_setAddr(layer, 0); + for (i = 0; i < LCD_COLS * LCD_ROWS; i++) + lcd_putCharUnlocked(c, layer); + UNLOCK_LCD; +} + + +void lcd_clear(Layer *layer) +{ + lcd_layerSet(layer, 0); +} + + +void lcd_clearLine(Layer *layer, int y) +{ + int i; + + LOCK_LCD; + lcd_setAddr(layer, LCD_POS(0, y)); + for (i = 0; i < LCD_COLS; i++) + lcd_putCharUnlocked(0, layer); + UNLOCK_LCD; +} + + +void lcd_moveCursor(lcdpos_t addr) +{ + LOCK_LCD; + lcd_moveTo(addr); + UNLOCK_LCD; +} + + +char lcd_setCursor(char mode) +{ + static const char cursor_cmd[3] = + { + LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK, LCD_CMD_CURSOR_LINE + }; + char oldmode = lcd_CursorStatus; + + LOCK_LCD; + lcd_CursorStatus = mode; + lcd_setReg(cursor_cmd[(int)mode]); + if (mode) + lcd_moveCursor(lcd_CursorAddr); + UNLOCK_LCD; + + return oldmode; +} + + +int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap) +{ + int len; + + LOCK_LCD; + + /* + * Se il cursore era acceso, spegnilo durante + * l'output per evitare che salti alla posizione + * in cui si scrive. + */ + if (lcd_CursorStatus) + lcd_setReg(LCD_CMD_CURSOR_OFF); + + /* Spostamento del cursore */ + lcd_setAddr(layer, addr); + + if (mode & LCD_CENTER) + { + int pad; + + /* + * NOTE: calculating the string lenght BEFORE it gets + * printf()-formatted. Real lenght may differ. + */ + pad = (LCD_COLS - strlen(format)) / 2; + while (pad--) + lcd_putCharUnlocked(' ', layer); + } + + len = _formatted_write(format, (void (*)(char, void *))lcd_putCharUnlocked, layer, ap); + + if (mode & (LCD_FILL | LCD_CENTER)) + while (layer->addr % LCD_COLS) + lcd_putCharUnlocked(' ', layer); + + /* + * Riaccendi il cursore e riportalo alla + * vecchia posizione + */ + if (lcd_CursorStatus) + lcd_setCursor(lcd_CursorStatus); + + UNLOCK_LCD; + + return len; +} + + +int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...) +{ + int len; + va_list ap; + + va_start(ap, format); + len = lcd_vprintf(layer, addr, mode, format, ap); + va_end(ap); + + return len; +} + + +/** + * Internal function to move a layer between two positions. + * + * \note The layer must be *already* enqueued in some list. + * \note The display must be already locked! + */ +static void lcd_enqueueLayer(Layer *layer, char pri) +{ + Layer *l2; + + /* Remove layer from whatever list it was in before */ + REMOVE(layer); + + layer->pri = pri; + + /* + * Search for the first layer whose priority + * is less or equal to the layer we are adding. + */ + FOREACH_NODE(l2, &lcd_Layers) + if (l2->pri <= pri) + break; + + /* Enqueue layer */ + INSERT_BEFORE(layer, l2); +} + +Layer *lcd_newLayer(char pri) +{ + Layer *layer; + + LOCK_LCD; + + if (LIST_EMPTY(&lcd_FreeLayers)) + { + UNLOCK_LCD; + //ASSERT(false); + return NULL; + } + + layer = (Layer *)LIST_HEAD(&lcd_FreeLayers); + layer->addr = 0; + memset(layer->buf, 0, LCD_ROWS * LCD_COLS); + + lcd_enqueueLayer(layer, pri); + + UNLOCK_LCD; + return layer; +} + +/** + * Redraw the display (internal). + * + * \note The display must be already locked. + */ +static void lcd_refresh(void) +{ + lcdpos_t addr; + Layer *l; + + for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) + { + FOREACH_NODE(l, &lcd_Layers) + { + //kprintf("%d %x %p\n", addr, l->buf[0], l); + if (l->pri == LAYER_HIDDEN) + break; + + if (l->buf[addr]) + { + /* Refresh location */ + lcd_putc(addr, l->buf[addr]); + goto done; + } + } + + /* Draw background */ + lcd_putc(addr, ' '); + done: + ; + } +} + +/** + * Rearrange layer depth and refresh display accordingly. + * + * \note Setting a priority of LAYER_HIDDEN makes the layer invisible. + */ +void lcd_setLayerDepth(Layer *layer, char pri) +{ + if (pri != layer->pri) + { + LOCK_LCD; + lcd_enqueueLayer(layer, pri); + /* Vile but simple */ + lcd_refresh(); + UNLOCK_LCD; + } +} + +void lcd_deleteLayer(Layer *layer) +{ + LOCK_LCD; + +/* We use lcd_refresh() instead. Much simpler than this mess, but slower. */ +#if 0 + Layer *l2; + lcdpos_t addr; + + /* Repair damage on underlaying layers */ + for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) + { + /* If location was covered by us */ + if (layer->buf[addr]) + { + /* ...and it wasn't covered by others above us... */ + for (l2 = layer->pred; l2->pred; l2 = l2->pred) + if (l2->buf[addr]) + /* can't just break here! */ + goto not_visible; + + /* ...scan underlaying layers to repair damage */ + for (l2 = layer->succ; l2->succ; l2 = l2->succ) + if (l2->buf[addr]) + { + /* Refresh character */ + lcd_putc(addr, l2->buf[addr]); + + /* No need to search on deeper layers */ + break; + } + + not_visible: + ; + } + } +#endif + + // Remove layer from lcd_Layers list. + REMOVE(layer); + + /* Put layer back into free list */ + ADDHEAD(&lcd_FreeLayers, layer); + + lcd_refresh(); + + UNLOCK_LCD; +} + + +static void lcd_setDefLayer(Layer *layer) +{ + lcd_DefLayer = layer; +} + +#include +void lcd_init(void) +{ + int i; + + LIST_INIT(&lcd_Layers); + LIST_INIT(&lcd_FreeLayers); + for (i = 0; i < LCD_LAYERS; ++i) + ADDHEAD(&lcd_FreeLayers, &lcd_LayersPool[i]); + + lcd_setDefLayer(lcd_newLayer(0)); + + lcd_hw_init(); + + lcd_setCursor(0); +} + +#if CONFIG_TEST +void lcd_test(void) +{ + int i; + + for (i = 0; i < LCD_ROWS * LCD_COLS; ++i) + { + lcd_putCharUnlocked('0' + (i % 10), lcd_DefLayer); + timer_delay(100); + } +} +#endif /* CONFIG_TEST */ + diff --git a/bertos/drv/lcd_text.h b/bertos/drv/lcd_text.h new file mode 100644 index 00000000..d05cfcd2 --- /dev/null +++ b/bertos/drv/lcd_text.h @@ -0,0 +1,147 @@ +/** + * \file + * + * + * \brief Generic text LCD driver (interface). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.3 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.2 2006/02/23 10:59:14 bernie + *#* Documentation fixes. + *#* + *#* Revision 1.1 2005/11/04 18:00:42 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.5 2005/06/14 14:43:43 bernie + *#* Add DevLib headers. + *#* + *#* Revision 1.4 2005/06/06 17:41:57 batt + *#* Add lcd_layerSet function. + *#* + *#* Revision 1.3 2005/06/01 10:36:23 batt + *#* Layer: Rename member variables and Doxygenize. + *#* + *#* Revision 1.2 2005/05/26 08:31:23 batt + *#* Add layer hiding/showing. + *#* + *#* Revision 1.1 2005/05/24 09:17:58 batt + *#* Move drivers to top-level. + *#*/ + +#ifndef DRV_LCD_H +#define DRV_LCD_H + +#include "lcd_hd44.h" + +#include +#include +#include + +#include // vprintf() + + +/* flags for lcd_printf() */ +#define LCD_NORMAL 0 /* Scrittura normale */ +#define LCD_FILL BV(0) /* Fill rest of line with spaces */ +#define LCD_CENTER BV(1) /* Center string in line */ +#define LCD_NOCURSOR BV(2) /* Scrittura senza spostamento cursore */ + +/** Special priority value for lcd_setLayerDepth(). */ +#define LAYER_HIDDEN -128 + +/* Compute LCD address from x/y coordinates */ +#define LCD_POS(x,y) ((lcdpos_t)((uint8_t)(x) + (uint8_t)(y) * (uint8_t)LCD_COLS)) +#define LCD_ROW0 (LCD_COLS * 0) +#define LCD_ROW1 (LCD_COLS * 1) +#define LCD_ROW2 (LCD_COLS * 2) +#define LCD_ROW3 (LCD_COLS * 3) + +/** + * Overwrapping layer context. + */ +typedef struct _Layer +{ + /** + * Active layers are linked together in a list + * sorted in top to bottom order. + */ + DECLARE_NODE_ANON(struct _Layer) + + /** Current XY address into this layer, for write operations. */ + lcdpos_t addr; + + /** Priority of this layer (greater in front of lesser). */ + char pri; + + /** + * Layer backing store buffer. + * + * All writes through the layer are copied into this buffer. + * Characters cells with value 0 are transparent with respect + * to other layers in the background. + */ + char buf[LCD_COLS * LCD_ROWS]; +} Layer; + + +/* Global variables */ +extern Layer *lcd_DefLayer; + +/* Function prototypes */ +extern void lcd_init(void); +extern void lcd_test(void); + +extern void lcd_moveCursor(lcdpos_t addr); +extern char lcd_setCursor(char state); + +extern void lcd_setAddr(Layer *layer, lcdpos_t addr); +extern void lcd_putChar(char c, Layer *layer); +extern int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap) FORMAT(printf, 4, 0); +extern int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...) FORMAT(printf, 4, 5); +extern void lcd_clear(Layer *layer); +extern void lcd_layerSet(Layer *layer, char c); +extern void lcd_clearLine(Layer *layer, int y); + +extern void lcd_setLayerDepth(Layer *layer, char pri); +extern Layer *lcd_newLayer(char pri); +extern void lcd_deleteLayer(Layer *layer); +extern void lcd_lock(void); +extern void lcd_unlock(void); + +#endif /* DRV_LCD_H */ diff --git a/bertos/drv/mcp41.c b/bertos/drv/mcp41.c new file mode 100644 index 00000000..12c566f5 --- /dev/null +++ b/bertos/drv/mcp41.c @@ -0,0 +1,81 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief MCP41xxx digital potentiomenter driver (implementation) + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#include + +#include +#include + +#include +#include +#include + +static Serial *spi_ser; + +/** + * Set resitance for digital pot \a dev + */ +void mcp41_setResistance(Mcp41Dev dev, mcp41_res_t res) +{ + MCP41_ON(dev); + /* send command byte */ + ser_putchar(MCP41_WRITE_DATA, spi_ser); + ser_putchar(((MCP41_HW_MAX * (uint32_t)res) + (MCP41_MAX / 2)) / MCP41_MAX, spi_ser); + ser_drain(spi_ser); + + MCP41_OFF(dev); +} + + +/** + * Initialize mcp41 potentiometer driver + */ +void mcp41_init(Serial *spi_port) +{ + Mcp41Dev dev; + + /* Init all potentiometer ports */ + for (dev = 0; dev < MCP41_CNT; dev++) + { + SET_MCP41_DDR(dev); + MCP41_OFF(dev); + } + + spi_ser = spi_port; +} diff --git a/bertos/drv/mcp41.h b/bertos/drv/mcp41.h new file mode 100644 index 00000000..266b539b --- /dev/null +++ b/bertos/drv/mcp41.h @@ -0,0 +1,59 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief MCP41xxx digital potentiomenter driver (interface) + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#ifndef DRV_MCP41_H +#define DRV_MCP41_H + +#include +#include +#include + +#define MCP41_WRITE_DATA 0x11 +#define MCP41_HW_MAX 255 +#define MCP41_MAX 999 + +/** + * Type for digital potentiometer resistance. + */ +typedef uint16_t mcp41_res_t; + +void mcp41_setResistance(Mcp41Dev dev, mcp41_res_t res); +void mcp41_init(Serial *spi_port); + +#endif /* DRV_MCP41_H */ diff --git a/bertos/drv/ntc.c b/bertos/drv/ntc.c new file mode 100644 index 00000000..2469c88f --- /dev/null +++ b/bertos/drv/ntc.c @@ -0,0 +1,161 @@ +/** + * \file + * + * + * \brief Driver for NTC (reads a temperature through an ADC) + * + * \version $Id$ + * + * \author Giovanni Bajo + * \author Francesco Sacchi + * + * + * This module handles an external NTC bound to an AD converter. As usual, + * it relies on a low-level API (ntc_hw_*) (see below): + * + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 17:59:47 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.1 2005/05/24 09:17:58 batt + *#* Move drivers to top-level. + *#*/ + +#include +#include +#include + +#include + +DB(bool ntc_initialized;) + +/** + * Find in a table of values \a orig_table of size \a size, the index which + * value is less or equal to \a val. + * + * \retval 0 When \a val is higher than the first table entry. + * \retval size When \a val is lower than the last table entry. + * \retval 1..size-1 When \a val is within the table. + */ +static size_t upper_bound(const res_t *orig_table, size_t size, res_t val) +{ + const res_t *table = orig_table; + + while (size) + { + size_t pos = size / 2; + if (val > table[pos]) + size = pos; + else + { + table += pos+1; + size -= pos+1; + } + } + + return table - orig_table; +} + + +/** + * Read the temperature for the NTC channel \a dev. + * First read the resistence of the NTC through ntc_hw_read(), then, + * for the conversion from resistance to temperature, since the formula + * varies from device to device, we implemented a generic system using + * a table of data which maps temperature (index) to resistance (data). + * The range of the table (min/max temperature) and the step + * (temperature difference between two consecutive elements of the table) + * is variable and can be specified. Notice that values inbetween the + * table elements are still possible as the library does a linear + * interpolation using the actual calculated resistance to find out + * the exact temperature. + * + * The low-level API provides a function to get access to a description + * of the NTC (ntc_hw_getInfo()), including the resistance table. + * + */ +deg_t ntc_read(NtcDev dev) +{ + const NtcHwInfo* hw = ntc_hw_getInfo(dev); + const res_t* r = hw->resistances; + + float rx; + size_t i; + deg_t degrees; + + rx = ntc_hw_read(dev); + + + i = upper_bound(r, hw->num_resistances, rx); + ASSERT(i <= hw->num_resistances); + + if (i >= hw->num_resistances) + return NTC_SHORT_CIRCUIT; + else if (i == 0) + return NTC_OPEN_CIRCUIT; + + /* + * Interpolated value in 0.1 degrees multiplied by 10: + * delta t step t + * ---------- = ---------------- + * (rx - r[i]) (r[i-1] - r [i]) + */ + float tmp; + tmp = 10 * hw->degrees_step * (rx - r[i]) / (r[i - 1] - r[i]); + + /* + * degrees = integer part corresponding to the superior index + * in the table multiplied by 10 + * - decimal part interpolated (already multiplied by 10) + */ + degrees = (i * hw->degrees_step + hw->degrees_min) * 10 - (int)(tmp); + + //kprintf("dev= %d, I=%d, degrees = %d\n", dev, i , degrees); + + return degrees; +} + + +/** + * Init NTC hardware. + */ +void ntc_init(void) +{ + NTC_HW_INIT; + DB(ntc_initialized = true;) +} + diff --git a/bertos/drv/ntc.h b/bertos/drv/ntc.h new file mode 100644 index 00000000..8267d51f --- /dev/null +++ b/bertos/drv/ntc.h @@ -0,0 +1,105 @@ +/** + * \file + * + * + * \brief Driver for NTC (reads a temperature through an ADC) + * + * \version $Id$ + * + * \author Giovanni Bajo + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 17:59:47 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.3 2005/06/10 08:56:47 batt + *#* Avoid calling DEG_T_TO_DEG(). + *#* + *#* Revision 1.2 2005/06/10 08:54:58 batt + *#* Rename deg_t conversion macros to accomplish coding standard. + *#* + *#* Revision 1.1 2005/05/24 09:17:58 batt + *#* Move drivers to top-level. + *#*/ + +#ifndef DRV_NTC_H +#define DRV_NTC_H + +#include +#include +#include + +#define NTC_OPEN_CIRCUIT -32768 +#define NTC_SHORT_CIRCUIT 32767 + +typedef int16_t deg_t; /** type for celsius degrees deg_t = °C * 10 */ + +/** Macro for converting from deg to deg_t type */ +#define DEG_TO_DEG_T(x) ((deg_t)((x) * 10)) + +/** Macro for converting from deg_t to celsius degrees (returns only the integer part) */ +#define DEG_T_TO_INTDEG(x) ((x) / 10) + +/** Macro for converting from deg_t to celsius degrees (returns only the decimal part) */ +#define DEG_T_TO_DECIMALDEG(x) ((x) % 10) + +/** Macro for converting from deg_t to celsius degrees (returns type is float) */ +#define DEG_T_TO_FLOATDEG(x) ((x) / 10.0) + + +typedef uint32_t res_t; /** type for resistor res_t = Ohm * 100 */ +typedef float amp_t; /** type for defining amplifications amp_t = A, where A is a pure number */ + +DB(extern bool ntc_initialized;) + + +/** Describe a NTC chip */ +typedef struct NtcHwInfo +{ + const res_t *resistances; ///< resistances of the NTC (ohms * 100) + size_t num_resistances; ///< number of resistances + deg_t degrees_min; ///< degrees corresponding to the first entry in the table (celsius * 10) + deg_t degrees_step; ///< difference in degrees between two consecutive elements in the table (celsius * 10) +} NtcHwInfo; + +/** Initialize the NTC module */ +void ntc_init(void); + +/** Read a single temperature value from the NTC */ +deg_t ntc_read(NtcDev dev); + +#endif /* DRV_NTC_H */ diff --git a/bertos/drv/phase.c b/bertos/drv/phase.c new file mode 100644 index 00000000..e30f4668 --- /dev/null +++ b/bertos/drv/phase.c @@ -0,0 +1,192 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Phase control driver (implementation) + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#include + + +#include +#include +#include +#include + + +#include +#include + +#include + +/** Array of triacs */ +static Triac triacs[TRIAC_CNT]; + +DB(bool phase_initialized;) + +/** + * Zerocross interrupt, call when 220V cross zero. + * + * This function turn off all triacs that have duty < 100% + * and arm the triac timers for phase control. + * This function is frequency adaptive so can work both at 50 or 60Hz. + */ +DEFINE_ZEROCROSS_ISR() +{ + ticks_t period, now; + static ticks_t prev_time; + TriacDev dev; + + now = timer_clock_unlocked(); + period = now - prev_time; + + for (dev = 0; dev < TRIAC_CNT; dev++) + { + /* Only turn off triac if duty is != 100% */ + if (triacs[dev].duty != TRIAC_MAX_DUTY) + TRIAC_OFF(dev); + /* Compute delay from duty */ + timer_setDelay(&triacs[dev].timer, DIV_ROUND(period * (TRIAC_MAX_DUTY - triacs[dev].duty), TRIAC_MAX_DUTY)); + + /* This check avoids inserting the same timer twice + * in case of an intempestive zerocross or spike */ + if (triacs[dev].running) + { + timer_abort(&triacs[dev].timer); + //kprintf("[%lu]\n", timer_clock()); + } + + triacs[dev].running = true; + timer_add(&triacs[dev].timer); + } + prev_time = now; +} + + + +/** + * Set duty of the triac channel \a dev (interrupt safe). + */ +void phase_setDuty(TriacDev dev, triac_duty_t duty) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + phase_setDutyUnlock(dev,duty); + + IRQ_RESTORE(flags); +} + + + +/** + * Set duty of the triac channel \a dev (NOT INTERRUPT SAFE). + */ +void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty) +{ + triacs[dev].duty = MIN(duty, (triac_duty_t)TRIAC_MAX_DUTY); +} + + + +/** + * Set power of the triac channel \a dev (interrupt safe). + * + * This function approsimate the sine wave to a triangular wave to compute + * RMS power. + */ +void phase_setPower(TriacDev dev, triac_power_t power) +{ + bool greater_fifty = false; + triac_duty_t duty; + + power = MIN(power, (triac_power_t)TRIAC_MAX_POWER); + + if (power > TRIAC_MAX_POWER / 2) + { + greater_fifty = true; + power = TRIAC_MAX_POWER - power; + } + + duty = TRIAC_POWER_K * sqrt(power); + + if (greater_fifty) + duty = TRIAC_MAX_DUTY - duty; + phase_setDuty(dev, duty); +} + + + +/** + * Soft int for each \a _dev triac. + * + * The triacs are turned on at different time to achieve phase control. + */ +static void phase_softint(void *_dev) +{ + TriacDev dev = (TriacDev)_dev; + + /* Only turn on if duty is !=0 */ + if (triacs[dev].duty) + TRIAC_ON(dev); + triacs[dev].running = false; +} + + + +/** + * Initialize phase control driver + */ +void phase_init(void) +{ + cpuflags_t flags; + TriacDev dev; + + /* Init timers and ensure that all triac are off */ + for (dev = 0; dev < TRIAC_CNT; dev++) + { + triacs[dev].duty = 0; + triacs[dev].running = false; + SET_TRIAC_DDR(dev); + TRIAC_OFF(dev); + timer_set_event_softint(&triacs[dev].timer, (Hook)phase_softint, (void *)dev); + } + IRQ_SAVE_DISABLE(flags); + + /* Init zero cross interrupt */ + PHASE_HW_INIT; + DB(phase_initialized = true;) + IRQ_RESTORE(flags); +} diff --git a/bertos/drv/phase.h b/bertos/drv/phase.h new file mode 100644 index 00000000..f4e760ea --- /dev/null +++ b/bertos/drv/phase.h @@ -0,0 +1,119 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Phase control driver (interface) + * + * \version $Id$ + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:06:44 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.1 2005/05/24 09:17:58 batt + *#* Move drivers to top-level. + *#* + *#* Revision 1.9 2005/05/09 16:34:14 batt + *#* Change some function names to accomplish coding standard; Add debug phase_initialized; Change duty_t and power_t to uint16_t. + *#* + *#* Revision 1.8 2005/05/02 12:37:33 batt + *#* Split hw triac map in phase_map.h. + *#* + *#* Revision 1.7 2005/05/02 09:05:03 batt + *#* Rename duty_t and power_t in triac_duty_t and triac_power_t + *#* + *#* Revision 1.6 2005/04/28 15:10:11 batt + *#* Use timer API to add and set events. + *#* + *#* Revision 1.5 2005/04/28 12:04:46 batt + *#* Add some comments. + *#* + *#* Revision 1.4 2005/04/28 10:35:45 batt + *#* Complete phase_setpower. + *#* + *#* Revision 1.3 2005/04/27 19:23:40 batt + *#* Reformat. + *#* + *#* Revision 1.1 2005/04/27 17:13:56 batt + *#* Add triac phase control driver. + *#* + *#*/ + + +#ifndef DRV_PHASE_H +#define DRV_PHASE_H + +#include +#include +#include + +#define TRIAC_MAX_DUTY 100 +#define TRIAC_MAX_POWER 100 +#define TRIAC_POWER_K TRIAC_MAX_DUTY * (1 / sqrt(2 * TRIAC_MAX_POWER)) + +/** + * \name Types for duty and power. + * \{ + */ +typedef uint16_t triac_duty_t; +typedef uint16_t triac_power_t; +/* \} */ + + +DB(extern bool phase_initialized;) + +/** + * \name Type for triac control. + * \{ + */ +typedef struct Triac +{ + Timer timer; /**< Timer for phase control. */ + triac_duty_t duty; /**< Duty cycle of the channel. */ + bool running; /**< True when the timer is active. */ +} Triac; +/* \} */ + +void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty); +void phase_setDuty(TriacDev dev, triac_duty_t duty); +void phase_setPower(TriacDev dev, triac_power_t power); + +void phase_init(void); + + +#endif /* DRV_PHASE_H */ diff --git a/bertos/drv/pwm.c b/bertos/drv/pwm.c new file mode 100644 index 00000000..39461882 --- /dev/null +++ b/bertos/drv/pwm.c @@ -0,0 +1,109 @@ +/** + * \file + * + * + * + * \brief PWM driver (implementation) + * + * \version $Id$ + * + * \author Francesco Sacchi + * \author Daniele Basile + */ + +#include +#include + +#include +#include + +#include +#include + + +/** + * Set duty of pwm channel \p dev. + */ +void pwm_setDuty(PwmDev dev, pwm_duty_t duty) +{ + pwm_period_t period = 0; + pwm_duty_t real_duty = 0; + + duty = MIN(duty, (pwm_duty_t)PWM_MAX_DUTY); + + period = pwm_hw_getPeriod(dev); + + real_duty = (uint64_t)(duty * period) >> (uint64_t)PWM_MAX_PERIOD_LOG2; + +// kprintf("real_duty[%d] duty[%d], period[%d]\n", real_duty, duty, period); + pwm_hw_setDutyUnlock(dev, real_duty); +} + +/** + * Set frequency of pwm channel \p dev at \p freq in Hz. + */ +void pwm_setFrequency(PwmDev dev, pwm_freq_t freq) +{ + pwm_hw_setFrequency(dev, freq); +} + +/** + * Set duty of pwm channel \p dev. + */ +void pwm_enable(PwmDev dev, bool state) +{ + if (state) + pwm_hw_enable(dev); + else + pwm_hw_disable(dev); +} + +/** + * Initialize PWM hw. + */ +void pwm_init(void) +{ + cpuflags_t flags; + PwmDev dev; + + IRQ_SAVE_DISABLE(flags); + + /* set all pwm to 0 */ + for (dev = 0; dev < PWM_CNT; dev++) + pwm_setDuty(dev, 0); + + pwm_hw_init(); + + IRQ_RESTORE(flags); +} + + + + diff --git a/bertos/drv/pwm.h b/bertos/drv/pwm.h new file mode 100644 index 00000000..03d98453 --- /dev/null +++ b/bertos/drv/pwm.h @@ -0,0 +1,53 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief PWM driver (interface) + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#ifndef DRV_PWM_H +#define DRV_PWM_H + +#include +#include + +typedef uint16_t pwm_duty_t; + +void pwm_setDuty(PwmDev dev, pwm_duty_t duty); +void pwm_init(void); + +#define PWM_MAX_DUTY 100 + +#endif /* DRV_PWM_H */ diff --git a/bertos/drv/pwm_test.c b/bertos/drv/pwm_test.c new file mode 100644 index 00000000..cb2dc84c --- /dev/null +++ b/bertos/drv/pwm_test.c @@ -0,0 +1,108 @@ +/** + * \file + * + * + * + * \brief Test for PWM driver (implementation) + * + * \version $Id$ + * + * \author Daniele Basile + */ + +#include +#include + +#include +#include + +#include +#include + +/* + * Esample of value for duty cycle" + * + * - 100% => 0xFFFFFFFF + * - 80% => 0xCCCCCCCC + * - 75% => 0xBFFFFFFF + * - 50% => 0x7FFFFFFF + * - 25% => 0x3FFFFFFF + * - 33% => 0x55555555 + * - 16% => 0x2AAAAAAA + */ + +#define PWM_TEST_CH0 0 +#define PWM_TEST_CH0_FREQ 100UL // 100Hz +#define PWM_TEST_CH0_DUTY 0xCCCC // 80% + +#define PWM_TEST_CH1 1 +#define PWM_TEST_CH1_FREQ 1000UL // 1000Hz +#define PWM_TEST_CH1_DUTY 0xBFFF // 75% + +#define PWM_TEST_CH2 2 +#define PWM_TEST_CH2_FREQ 12356 // 12356Hz +#define PWM_TEST_CH2_DUTY 0x7FFF // 50% + +#define PWM_TEST_CH3 3 +#define PWM_TEST_CH3_FREQ 100000UL // 100KHz +#define PWM_TEST_CH3_DUTY 0x5555 // 33% + +#define PWM_TEST_CH_SET(index) \ + do { \ + pwm_setFrequency(PWM_TEST_CH##index , PWM_TEST_CH##index##_FREQ); \ + pwm_setDuty(PWM_TEST_CH##index, PWM_TEST_CH##index##_DUTY); \ + pwm_enable(PWM_TEST_CH##index, true); \ + } while (0) + +/** + * Test suit for genation of pwm waveform. + * + */ +void pwm_test(void) +{ + + pwm_init(); + kputs("Init pwm..\n"); + + PWM_TEST_CH_SET(0); + kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH0, PWM_TEST_CH0_FREQ, PWM_TEST_CH0_DUTY); + PWM_TEST_CH_SET(1); + kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH1, PWM_TEST_CH1_FREQ, PWM_TEST_CH1_DUTY); + PWM_TEST_CH_SET(2); + kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH2, PWM_TEST_CH2_FREQ, PWM_TEST_CH2_DUTY); + PWM_TEST_CH_SET(3); + kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH3, PWM_TEST_CH3_FREQ, PWM_TEST_CH3_DUTY); +} + + + + + + diff --git a/bertos/drv/ser.c b/bertos/drv/ser.c new file mode 100644 index 00000000..0838bc15 --- /dev/null +++ b/bertos/drv/ser.c @@ -0,0 +1,529 @@ +/** + * \file + * + * + * \brief Buffered serial I/O driver + * + * The serial rx interrupt buffers incoming data in a software FIFO + * to decouple the higher level protocols from the line speed. + * Outgoing data is buffered as well for better performance. + * This driver is not optimized for best performance, but it + * has proved to be fast enough to handle transfer rates up to + * 38400bps on a 16MHz 80196. + * + * MODULE CONFIGURATION + * + * \li \c CONFIG_SER_HWHANDSHAKE - set to 1 to enable RTS/CTS handshake. + * Support is incomplete/untested. + * \li \c CONFIG_SER_TXTIMEOUT - Enable software serial transmission timeouts + * + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "ser.h" +#include "wdt.h" +#include "ser_p.h" +#include +#include +#include + +#include /* memset */ + +/* + * Sanity check for config parameters required by this module. + */ +#if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1) + #error CONFIG_KERNEL must be set to either 0 or 1 in config.h +#endif +#if !defined(CONFIG_SER_RXTIMEOUT) + #error CONFIG_SER_TXTIMEOUT missing in config.h +#endif +#if !defined(CONFIG_SER_RXTIMEOUT) + #error CONFIG_SER_RXTIMEOUT missing in config.h +#endif +#if !defined(CONFIG_SER_DEFBAUDRATE) + #error CONFIG_SER_DEFBAUDRATE missing in config.h +#endif + +#if CONFIG_KERNEL + #include +#endif + +#if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1 + #include +#endif + + +struct Serial ser_handles[SER_CNT]; + +/** + * Insert \a c in tx FIFO buffer. + * \note This function will switch out the calling process + * if the tx buffer is full. If the buffer is full + * and \a port->txtimeout is 0 return EOF immediatly. + * + * \return EOF on error or timeout, \a c otherwise. + */ +static int ser_putchar(int c, struct Serial *port) +{ + if (fifo_isfull_locked(&port->txfifo)) + { +#if CONFIG_SER_TXTIMEOUT != -1 + /* If timeout == 0 we don't want to wait */ + if (port->txtimeout == 0) + return EOF; + + ticks_t start_time = timer_clock(); +#endif + + /* Wait while buffer is full... */ + do + { + wdt_reset(); +#if CONFIG_KERNEL && CONFIG_KERN_SCHED + /* Give up timeslice to other processes. */ + proc_switch(); +#endif +#if CONFIG_SER_TXTIMEOUT != -1 + if (timer_clock() - start_time >= port->txtimeout) + { + ATOMIC(port->status |= SERRF_TXTIMEOUT); + return EOF; + } +#endif /* CONFIG_SER_TXTIMEOUT */ + } + while (fifo_isfull_locked(&port->txfifo)); + } + + fifo_push_locked(&port->txfifo, (unsigned char)c); + + /* (re)trigger tx interrupt */ + port->hw->table->txStart(port->hw); + + /* Avoid returning signed extended char */ + return (int)((unsigned char)c); +} + + +/** + * Fetch a character from the rx FIFO buffer. + * \note This function will switch out the calling process + * if the rx buffer is empty. If the buffer is empty + * and \a port->rxtimeout is 0 return EOF immediatly. + * + * \return EOF on error or timeout, \a c otherwise. + */ +static int ser_getchar(struct Serial *port) +{ + if (fifo_isempty_locked(&port->rxfifo)) + { +#if CONFIG_SER_RXTIMEOUT != -1 + /* If timeout == 0 we don't want to wait for chars */ + if (port->rxtimeout == 0) + return EOF; + + ticks_t start_time = timer_clock(); +#endif + /* Wait while buffer is empty */ + do + { + wdt_reset(); +#if CONFIG_KERNEL && CONFIG_KERN_SCHED + /* Give up timeslice to other processes. */ + proc_switch(); +#endif +#if CONFIG_SER_RXTIMEOUT != -1 + if (timer_clock() - start_time >= port->rxtimeout) + { + ATOMIC(port->status |= SERRF_RXTIMEOUT); + return EOF; + } +#endif /* CONFIG_SER_RXTIMEOUT */ + } + while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0); + } + + /* + * Get a byte from the FIFO (avoiding sign-extension), + * re-enable RTS, then return result. + */ + if (ser_getstatus(port) & SERRF_RX) + return EOF; + return (int)(unsigned char)fifo_pop_locked(&port->rxfifo); +} + +/** + * Fetch a character from the rx FIFO buffer. + * If the buffer is empty, ser_getchar_nowait() returns + * EOF immediatly. + * \note Deprecated, use ser_getchar with rx_timeout set to 0. + */ +int ser_getchar_nowait(struct KFileSerial *fd) +{ + if (fifo_isempty_locked(&fd->ser->rxfifo)) + return EOF; + + /* NOTE: the double cast prevents unwanted sign extension */ + return (int)(unsigned char)fifo_pop_locked(&fd->ser->rxfifo); +} + + + +/** + * Read at most \a size bytes from \a port and put them in \a buf + * + * \return number of bytes actually read. + */ +static size_t ser_read(struct KFile *fd, void *_buf, size_t size) +{ + KFileSerial *fds = KFILESERIAL(fd); + + size_t i = 0; + char *buf = (char *)_buf; + int c; + + while (i < size) + { + if ((c = ser_getchar(fds->ser)) == EOF) + break; + buf[i++] = c; + } + + return i; +} + +/** + * \brief Write a buffer to serial. + * + * \return 0 if OK, EOF in case of error. + * + * \todo Optimize with fifo_pushblock() + */ +static size_t ser_write(struct KFile *fd, const void *_buf, size_t size) +{ + KFileSerial *fds = KFILESERIAL(fd); + const char *buf = (const char *)_buf; + size_t i = 0; + + while (size--) + { + if (ser_putchar(*buf++, fds->ser) == EOF) + break; + i++; + } + return i; +} + + +#if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1 +void ser_settimeouts(struct KFileSerial *fd, mtime_t rxtimeout, mtime_t txtimeout) +{ + fd->ser->rxtimeout = ms_to_ticks(rxtimeout); + fd->ser->txtimeout = ms_to_ticks(txtimeout); +} +#endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */ + +#if CONFIG_SER_RXTIMEOUT != -1 +/** + * Discard input to resynchronize with remote end. + * + * Discard incoming data until the port stops receiving + * characters for at least \a delay milliseconds. + * + * \note Serial errors are reset before and after executing the purge. + */ +void ser_resync(struct KFileSerial *fd, mtime_t delay) +{ + mtime_t old_rxtimeout = ticks_to_ms(fd->ser->rxtimeout); + + ser_settimeouts(fd, delay, ticks_to_ms(fd->ser->txtimeout)); + do + { + ser_setstatus(fd->ser, 0); + ser_getchar(fd->ser); + } + while (!(ser_getstatus(fd->ser) & SERRF_RXTIMEOUT)); + + /* Restore port to an usable status */ + ser_setstatus(fd->ser, 0); + ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->ser->txtimeout)); +} +#endif /* CONFIG_SER_RXTIMEOUT */ + + +void ser_setbaudrate(struct KFileSerial *fd, unsigned long rate) +{ + fd->ser->hw->table->setBaudrate(fd->ser->hw, rate); +} + + +void ser_setparity(struct KFileSerial *fd, int parity) +{ + fd->ser->hw->table->setParity(fd->ser->hw, parity); +} + +static int ser_error(struct KFile *fd) +{ + KFileSerial *fds = KFILESERIAL(fd); + return ser_getstatus(fds->ser); +} + +static void ser_clearerr(struct KFile *fd) +{ + KFileSerial *fds = KFILESERIAL(fd); + ser_setstatus(fds->ser, 0); +} + + + +/** + * Flush both the RX and TX buffers. + */ +void ser_purge(struct KFileSerial *fd) +{ + ser_purgeRx(fd); + ser_purgeTx(fd); +} + +/** + * Flush RX buffer. + */ +void ser_purgeRx(struct KFileSerial *fd) +{ + fifo_flush_locked(&fd->ser->rxfifo); +} + +/** + * Flush TX buffer. + */ +void ser_purgeTx(struct KFileSerial *fd) +{ + fifo_flush_locked(&fd->ser->txfifo); +} + + +/** + * Wait until all pending output is completely + * transmitted to the other end. + * + * \note The current implementation only checks the + * software transmission queue. Any hardware + * FIFOs are ignored. + */ +static int ser_flush(struct KFile *fd) +{ + KFileSerial *fds = KFILESERIAL(fd); + + /* + * Wait until the FIFO becomes empty, and then until the byte currently in + * the hardware register gets shifted out. + */ + while (!fifo_isempty(&fds->ser->txfifo) + || fds->ser->hw->table->txSending(fds->ser->hw)) + { + #if CONFIG_KERNEL && CONFIG_KERN_SCHED + /* Give up timeslice to other processes. */ + proc_switch(); + #endif + wdt_reset(); + } + return 0; +} + + +/** + * Initialize a serial port. + * + * \param fd KFile Serial struct interface. + * \param unit Serial unit to open. Possible values are architecture dependant. + */ +static struct Serial *ser_open(struct KFileSerial *fd, unsigned int unit) +{ + struct Serial *port; + + ASSERT(unit < countof(ser_handles)); + port = &ser_handles[unit]; + + ASSERT(!port->is_open); + DB(port->is_open = true); + + port->unit = unit; + + port->hw = ser_hw_getdesc(unit); + + /* Initialize circular buffers */ + ASSERT(port->hw->txbuffer); + ASSERT(port->hw->rxbuffer); + fifo_init(&port->txfifo, port->hw->txbuffer, port->hw->txbuffer_size); + fifo_init(&port->rxfifo, port->hw->rxbuffer, port->hw->rxbuffer_size); + + port->hw->table->init(port->hw, port); + + fd->ser = port; + /* Set default values */ +#if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1 + ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT); +#endif +#if CONFIG_SER_DEFBAUDRATE + ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE); +#endif + + /* Clear error flags */ + ser_setstatus(port, 0); + + return port; +} + + +/** + * Clean up serial port, disabling the associated hardware. + */ +static int ser_close(struct KFile *fd) +{ + KFileSerial *fds = KFILESERIAL(fd); + Serial *port = fds->ser; + + ASSERT(port->is_open); + DB(port->is_open = false); + + // Wait until we finish sending everything + ser_flush(fd); + + port->hw->table->cleanup(port->hw); + DB(port->hw = NULL); + + /* + * We purge the FIFO buffer only after the low-level cleanup, so that + * we are sure that there are no more interrupts. + */ + ser_purge(fds); + return 0; +} + +/** + * Reopen serial port. + */ +static struct KFile *ser_reopen(struct KFile *fd) +{ + KFileSerial *fds = KFILESERIAL(fd); + + ser_close(fd); + ser_open(fds, fds->ser->unit); + return (KFile *)fds; +} + +/** + * Init serial driver for \a unit. + */ +void ser_init(struct KFileSerial *fds, unsigned int unit) +{ + memset(fds, 0, sizeof(*fds)); + + DB(fds->fd._type = KFT_SERIAL); + fds->fd.reopen = ser_reopen; + fds->fd.close = ser_close; + fds->fd.read = ser_read; + fds->fd.write = ser_write; + fds->fd.flush = ser_flush; + fds->fd.error = ser_error; + fds->fd.clearerr = ser_clearerr; + ser_open(fds, unit); +} + + +/** + * Read data from SPI bus. + * Since we are master, we have to trigger slave by sending + * fake chars on the bus. + */ +static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size) +{ + KFileSerial *fd_spi = KFILESERIAL(fd); + + ser_flush(&fd_spi->fd); + ser_purgeRx(fd_spi); + + size_t total_rd = 0; + uint8_t *buf = (uint8_t *)_buf; + int c; + + while (size--) + { + /* + * Send and receive chars 1 by 1, otherwise the rxfifo + * will overrun. + */ + ser_putchar(0, fd_spi->ser); + + if ((c = ser_getchar(fd_spi->ser)) == EOF) + break; + + *buf++ = c; + total_rd++; + } + return total_rd; +} + +/** + * Write data to SPI bus. + */ +static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size) +{ + KFileSerial *fd_spi = KFILESERIAL(fd); + + ser_purgeRx(fd_spi); + + return ser_write(&fd_spi->fd, buf, size); +} + + +/** + * Init SPI serial driver \a unit in master mode. + * + * This interface implements the SPI master protocol over a serial SPI + * driver. This is needed because normal serial driver send/receive data + * at the same time. SPI slaves like memories and other peripherals + * first receive and *then* send response back instead. + * To achieve this, when we are master and we are *sending*, + * we have to discard all incoming data. Then, when we want to + * receive, we must write fake data to SPI to trigger slave devices. + */ +void spimaster_init(KFileSerial *fds, unsigned int unit) +{ + ser_init(fds, unit); + fds->fd.read = spimaster_read; + fds->fd.write = spimaster_write; +} + + diff --git a/bertos/drv/ser.h b/bertos/drv/ser.h new file mode 100644 index 00000000..c0f7b8bb --- /dev/null +++ b/bertos/drv/ser.h @@ -0,0 +1,198 @@ +/** + * \file + * + * + * \brief High level serial I/O API + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#ifndef DRV_SER_H +#define DRV_SER_H + +#include +#include +#include + +#if OS_HOSTED + #include /* BV() */ + + typedef uint16_t serstatus_t; + + /* Software errors */ + #define SERRF_RXFIFOOVERRUN BV(0) /**< Rx FIFO buffer overrun */ + #define SERRF_RXTIMEOUT BV(1) /**< Receive timeout */ + #define SERRF_TXTIMEOUT BV(2) /**< Transmit timeout */ + + /* Hardware errors */ + #define SERRF_RXSROVERRUN 0 /**< Unsupported in emulated serial port. */ + #define SERRF_FRAMEERROR 0 /**< Unsupported in emulated serial port. */ + #define SERRF_PARITYERROR 0 /**< Unsupported in emulated serial port. */ + #define SERRF_NOISEERROR 0 /**< Unsupported in emulated serial port. */ + + enum + { + SER_UART0, + SER_UART1, + + SER_CNT /**< Number of serial ports */ + }; + +#else + #include CPU_HEADER(ser) +#endif + +#include + + + +/** + * \name Masks to group TX/RX errors. + * \{ + */ +#define SERRF_RX \ + ( SERRF_RXFIFOOVERRUN \ + | SERRF_RXTIMEOUT \ + | SERRF_RXSROVERRUN \ + | SERRF_PARITYERROR \ + | SERRF_FRAMEERROR \ + | SERRF_NOISEERROR) +#define SERRF_TX (SERRF_TXTIMEOUT) +/*\}*/ + +/** + * \name LSB or MSB first data order for SPI driver. + * \{ + */ +#define SER_MSB_FIRST 0 +#define SER_LSB_FIRST 1 +/*\}*/ + +/** + * \name Parity settings for ser_setparity(). + * + * \note Values are AVR-specific for performance reasons. + * Other processors should either decode them or + * redefine these macros. + * \{ + */ +#define SER_PARITY_NONE 0 +#define SER_PARITY_EVEN 2 +#define SER_PARITY_ODD 3 +/*\}*/ + + +struct SerialHardware; + +/** Human-readable serial error descriptions */ +extern const char * const serial_errors[8]; + +/** Serial handle structure */ +typedef struct Serial +{ + /** Physical port number */ + unsigned int unit; + +#ifdef _DEBUG + bool is_open; +#endif + + /** + * \name Transmit and receive FIFOs. + * + * Declared volatile because handled asinchronously by interrupts. + * + * \{ + */ + FIFOBuffer txfifo; + FIFOBuffer rxfifo; + /* \} */ + +#if CONFIG_SER_RXTIMEOUT != -1 + ticks_t rxtimeout; +#endif +#if CONFIG_SER_TXTIMEOUT != -1 + ticks_t txtimeout; +#endif + + /** Holds the flags defined above. Will be 0 when no errors have occurred. */ + volatile serstatus_t status; + + /** Low-level interface to hardware. */ + struct SerialHardware* hw; +} Serial; + +typedef struct KFileSerial +{ + KFile fd; + Serial *ser; +} KFileSerial; + +/** + * ID for serial. + */ +#define KFT_SERIAL MAKE_ID('S', 'E', 'R', 'L') + + +INLINE KFileSerial * KFILESERIAL(KFile *fd) +{ + ASSERT(fd->_type == KFT_SERIAL); + return (KFileSerial *)fd; +} + +/* Function prototypes */ +//extern int ser_getchar_nowait(struct Serial *port); + +void ser_setbaudrate(struct KFileSerial *fd, unsigned long rate); +void ser_setparity(struct KFileSerial *fd, int parity); +void ser_settimeouts(struct KFileSerial *fd, mtime_t rxtimeout, mtime_t txtimeout); +void ser_resync(struct KFileSerial *fd, mtime_t delay); +int ser_getchar_nowait(struct KFileSerial *fd); + +void ser_purgeRx(struct KFileSerial *fd); +void ser_purgeTx(struct KFileSerial *fd); +void ser_purge(struct KFileSerial *fd); +void ser_init(struct KFileSerial *fds, unsigned int unit); +void spimaster_init(KFileSerial *fds, unsigned int unit); + + +/** + * \name Additional functions implemented as macros + * + * \{ + */ +#define ser_getstatus(h) ((h)->status) +#define ser_setstatus(h, x) ((h)->status = (x)) +/* \} */ + +#endif /* DRV_SER_H */ diff --git a/bertos/drv/ser_p.h b/bertos/drv/ser_p.h new file mode 100644 index 00000000..d0071feb --- /dev/null +++ b/bertos/drv/ser_p.h @@ -0,0 +1,71 @@ +/** + * \file + * + * + * \brief Hardware dependent serial driver (interface) + * + * \version $Id$ + * + * \author Stefano Fedrigo + * \author Giovanni Bajo + */ + + +#ifndef DRV_SER_P_H +#define DRV_SER_P_H + +#include /* size_t */ + +struct SerialHardware; +struct Serial; + +struct SerialHardwareVT +{ + void (*init)(struct SerialHardware *ctx, struct Serial *ser); + void (*cleanup)(struct SerialHardware *ctx); + void (*setBaudrate)(struct SerialHardware *ctx, unsigned long rate); + void (*setParity)(struct SerialHardware *ctx, int parity); + void (*txStart)(struct SerialHardware *ctx); + bool (*txSending)(struct SerialHardware *ctx); +}; + +struct SerialHardware +{ + const struct SerialHardwareVT *table; + unsigned char *txbuffer; + unsigned char *rxbuffer; + size_t txbuffer_size; + size_t rxbuffer_size; +}; + +struct SerialHardware *ser_hw_getdesc(int unit); + +#endif /* DRV_SER_P_H */ diff --git a/bertos/drv/ser_posix.c b/bertos/drv/ser_posix.c new file mode 100644 index 00000000..5306e58d --- /dev/null +++ b/bertos/drv/ser_posix.c @@ -0,0 +1,199 @@ +/** + * \file + * + * + * \brief Serial port emulator for hosted environments. + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2006/02/17 22:28:00 bernie + *#* Rename ser_emul.c to ser_posix.c. + *#* + *#* Revision 1.4 2006/02/17 22:23:06 bernie + *#* Update POSIX serial emulator. + *#* + *#* Revision 1.3 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.2 2005/04/11 19:10:27 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.1 2004/12/31 17:40:00 bernie + *#* Add a simple serial emulation driver. + *#* + *#*/ + +#include "ser.h" +#include "ser_p.h" + +#include +#include +#include + +#include + +#include +#include +#include /* open() */ +#include /* read(), write() */ + + +/* From the high-level serial driver */ +extern struct Serial ser_handles[SER_CNT]; + +/* TX and RX buffers */ +static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; +static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; +static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; + + +/** + * Internal state structure + */ +struct EmulSerial +{ + struct SerialHardware hw; + struct Serial *ser; + int fd; +}; + + +/* + * Callbacks + */ +static void uart_init(struct SerialHardware *_hw, struct Serial *ser) +{ + struct EmulSerial *hw = (struct EmulSerial *)_hw; + + hw->ser = ser; + hw->fd = open("/dev/ttyS0", O_RDWR); +} + +static void uart_cleanup(UNUSED_ARG(struct SerialHardware *, _hw)) +{ + struct EmulSerial *hw = (struct EmulSerial *)_hw; + + close(hw->fd); + hw->fd = -1; +} + +static void uart_txStart(struct SerialHardware * _hw) +{ + struct EmulSerial *hw = (struct EmulSerial *)_hw; + + while(!fifo_isempty(&hw->ser->txfifo)) + { + char c = fifo_pop(&hw->ser->txfifo); + write(hw->fd, &c, 1); + } +} + +static bool uart_txSending(UNUSED_ARG(struct SerialHardware *, _hw)) +{ + return false; +} + + +static void uart_setBaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate) +{ + TRACEMSG("rate=%lu", rate); + // TODO + +} + +static void uart_setParity(UNUSED_ARG(struct SerialHardware *, _hw), int parity) +{ + TRACEMSG("parity=%d", parity); + // TODO +} + +// FIXME: move into compiler.h? Ditch? +#if COMPILER_C99 + #define C99INIT(name,val) .name = val +#elif defined(__GNUC__) + #define C99INIT(name,val) name: val +#else + #warning No designated initializers, double check your code + #define C99INIT(name,val) (val) +#endif + +/* + * High-level interface data structures. + */ +static const struct SerialHardwareVT uart_vtable = +{ + C99INIT(init, uart_init), + C99INIT(cleanup, uart_cleanup), + C99INIT(setBaudrate, uart_setBaudrate), + C99INIT(setParity, uart_setParity), + C99INIT(txStart, uart_txStart), + C99INIT(txSending, uart_txSending), +}; + +static struct EmulSerial UARTDescs[SER_CNT] = +{ + { + C99INIT(hw, /**/) { + C99INIT(table, &uart_vtable), + C99INIT(txbuffer, uart0_txbuffer), + C99INIT(rxbuffer, uart0_rxbuffer), + C99INIT(txbuffer_size, sizeof(uart0_txbuffer)), + C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)), + }, + C99INIT(ser, NULL), + C99INIT(fd, -1), + }, + { + C99INIT(hw, /**/) { + C99INIT(table, &uart_vtable), + C99INIT(txbuffer, uart1_txbuffer), + C99INIT(rxbuffer, uart1_rxbuffer), + C99INIT(txbuffer_size, sizeof(uart1_txbuffer)), + C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)), + }, + C99INIT(ser, NULL), + C99INIT(fd, -1), + }, +}; + +struct SerialHardware *ser_hw_getdesc(int unit) +{ + ASSERT(unit < SER_CNT); + return &UARTDescs[unit].hw; +} diff --git a/bertos/drv/spi_bitbang.c b/bertos/drv/spi_bitbang.c new file mode 100644 index 00000000..90e959d8 --- /dev/null +++ b/bertos/drv/spi_bitbang.c @@ -0,0 +1,118 @@ +/** + * \file + * + * + * \brief Emulated SPI Master for DSP firmware download (impl.) + * + * \version $Id: spi.c 15328 2007-03-21 15:07:04Z batt $ + * + * \author Francesco Sacchi + * \author Daniele Basile + */ + + +#include +#include +#include +#include "hw_spi.h" + +void spi_assertSS(void) +{ + ATOMIC(SS_ACTIVE()); +} + +void spi_deassertSS(void) +{ + ATOMIC(SS_INACTIVE()); +} + +/** + * Send byte \c c over MOSI line, CONFIG_SPI_DATAORDER first. + * SS pin state is left unchanged. + */ +uint8_t spi_sendRecv(uint8_t c) +{ + uint8_t data = 0; + uint8_t shift = SPI_DATAORDER_START; + + + ATOMIC( + for (int i = 0; i < 8; i++) + { + /* Shift the i-th bit to MOSI */ + if (c & shift) + MOSI_HIGH(); + else + MOSI_LOW(); + /* Assert clock */ + SCK_ACTIVE(); + data |= IS_MISO_HIGH() ? shift : 0; + /* De-assert clock */ + SCK_INACTIVE(); + SPI_DATAORDER_SHIFT(shift); + } + ); + return data; +} + +MOD_DEFINE(spi); +void spi_init(void) +{ + ATOMIC(SPI_HW_INIT()); + MOD_INIT(spi); +} + +/** + * Read \param len from spi, and put it in \param _buff . + */ +void spi_read(void *_buff, size_t len) +{ + uint8_t *buff = (uint8_t *)_buff; + + while (len--) + /* Read byte from spi and put it in buffer. */ + *buff++ = spi_sendRecv(0); + +} + +/** + * Write \param len to spi, and take it from \param _buff . + */ +void spi_write(const void *_buff, size_t len) +{ + const uint8_t *buff = (const uint8_t *)_buff; + + while (len--) + /* Write byte pointed at by *buff to spi */ + spi_sendRecv(*buff++); + +} diff --git a/bertos/drv/spi_bitbang.h b/bertos/drv/spi_bitbang.h new file mode 100644 index 00000000..ff716906 --- /dev/null +++ b/bertos/drv/spi_bitbang.h @@ -0,0 +1,72 @@ +/** + * \file + * + * + * \brief Emulated SPI Master for DSP firmware download (interface) + * + * \version $Id: spi.h 15321 2007-03-21 14:45:12Z asterix $ + * + * \author Francesco Sacchi + * \author Daniele Basile + */ + + +#ifndef DRV_SPI_EMU_H +#define DRV_SPI_EMU_H + +#include +#include + +/** + * Define send and receive order bit. + * \{ + */ +#define SPI_LSB_FIRST 1 +#define SPI_MSB_FIRST 2 +/* \} */ + +#if CONFIG_SPI_DATAORDER == SPI_LSB_FIRST + #define SPI_DATAORDER_START 1 + #define SPI_DATAORDER_SHIFT(i) ((i) <<= 1) +#elif CONFIG_SPI_DATAORDER == SPI_MSB_FIRST + #define SPI_DATAORDER_START 0x80 + #define SPI_DATAORDER_SHIFT(i) ((i) >>= 1) +#endif + +void spi_write(const void *buf, size_t len); +void spi_read(void *buf, size_t len); +uint8_t spi_sendRecv(uint8_t c); +void spi_init(void); +void spi_assertSS(void); +void spi_deassertSS(void); + +#endif /* DRV_SPI_EMU_H */ diff --git a/bertos/drv/tc520.c b/bertos/drv/tc520.c new file mode 100644 index 00000000..615a94e0 --- /dev/null +++ b/bertos/drv/tc520.c @@ -0,0 +1,162 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 ADC driver (implementation) + * + * \version $Id$ + * \author Francesco Sacchi + * \author Marco Benelli + */ + +#include +#include + +#include + +#include +#include + +#include + +static Serial *spi_ser; + +#define TC520_CONVERSION_TIMEOUT ms_to_ticks(1000) +#define INIT_LOAD_VALUE 0x00 + +/** + * Start an AD conversion and return result. + * + * To start a conversion first we must pull down CE pin. + * The ADC starts a convertion and keeps the DV pin high until the end. + * At this point, we can read the conversion value by SPI. + * The convertion result is yield in 3 bytes. + * + * \verbatim + * + * First byte: + * bit | Value + * ----|------- + * 7 | Overrange + * 6 | Polarity + * 5:0 | data bits 15:10 + * + * Second byte: data 9:2 + * + * Third byte: + * bit | Value + * ----|------- + * 7 | data bit 1 + * 6 | data bit 0 + * 5:0 | '0' + * + * \endverbatim + * + * So, to get the result we must shift and recompose the bits. + * \note Overrange bit is handled as the 17th data bit. + */ +tc520_data_t tc520_read(void) +{ + /* Start convertion and wait */ + CE_LOW(); + ticks_t start = timer_clock(); + do + { + /* timeout check */ + if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) + { + ASSERT(0); + CE_HIGH(); + return TC520_MAX_VALUE; + } + } + while(DV_LOW()); + + start = timer_clock(); + do + { + /* timeout check */ + if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) + { + ASSERT(0); + CE_HIGH(); + return TC520_MAX_VALUE; + } + } + while(DV_HIGH()); + + /* Ok, convertion finished, read result */ + CE_HIGH(); + READ_LOW(); + + /* RX buffer could be dirty...*/ + ser_purge(spi_ser); + + /* I/O buffer */ + uint8_t buf[3] = "\x0\x0\x0"; + + /* Dummy write to activate recv */ + ser_write(spi_ser, buf, sizeof(buf)); + ser_drain(spi_ser); + READ_HIGH(); + + /* recv */ + ASSERT(ser_read(spi_ser, buf, sizeof(buf)) == sizeof(buf)); + + tc520_data_t res; + + /* Recompose data */ + res = (((tc520_data_t)(buf[0] & 0x3F)) << 10) | (((tc520_data_t)buf[1]) << 2) | (((tc520_data_t)buf[2]) >> 6); + + #define OVERRANGE_BIT BV(7) + /* Handle overrange bit as 17th bit */ + if (buf[0] & OVERRANGE_BIT) + res |= BV32(16); + + return res; +} + + +/** + * Initialize tc520 A/D converter driver + */ +void tc520_init(Serial *spi_port) +{ + spi_ser = spi_port; + /* init io ports */ + TC520_HW_INIT; + /* Send initial load value */ + LOAD_LOW(); + ser_putchar(INIT_LOAD_VALUE, spi_ser); + ser_drain(spi_ser); + LOAD_HIGH(); +} diff --git a/bertos/drv/tc520.h b/bertos/drv/tc520.h new file mode 100644 index 00000000..c36238f7 --- /dev/null +++ b/bertos/drv/tc520.h @@ -0,0 +1,55 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 ADC driver (intercace) + * + * \version $Id$ + * \author Francesco Sacchi + * \author Marco Benelli + */ + +#ifndef DRV_TC520_H +#define DRV_TC520_H + +#include +#include + +typedef uint32_t tc520_data_t; + +/* 17 bit max value */ +#define TC520_MAX_VALUE 0x1FFFFUL + +tc520_data_t tc520_read(void); +void tc520_init(Serial *spi_port); + +#endif /* DRV_TC520_H */ diff --git a/bertos/drv/thermo.c b/bertos/drv/thermo.c new file mode 100644 index 00000000..fb8cbb79 --- /dev/null +++ b/bertos/drv/thermo.c @@ -0,0 +1,274 @@ +/** + * \file + * + * + * \brief Thermo-control driver + * + * \version $Id$ + * + * \author Giovanni Bajo + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.3 2006/09/20 20:12:41 marco + *#* Names convention, MOD_* macros. + *#* + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 17:59:47 bernie + *#* Import into DevLib. + *#* + *#*/ +#include +#include + +#include +#include +#include + +#include +#include + + +/** Interval at which thermo control is performed. */ +#define THERMO_INTERVAL_MS 100 + +/** Number of different samples we interpolate over to get the hifi temperature. */ +#define THERMO_HIFI_NUM_SAMPLES 10 + +/** Timer for thermo-regulation. */ +static Timer thermo_timer; + +typedef struct ThermoControlDev +{ + deg_t hifi_samples[THERMO_HIFI_NUM_SAMPLES]; + deg_t cur_hifi_sample; + deg_t target; + thermostatus_t status; + ticks_t expire; +} ThermoControlDev; + +/** Array of thermo-devices. */ +ThermoControlDev devs[THERMO_CNT]; + + +/** + * Return the status of the specific \a dev thermo-device. + */ +thermostatus_t thermo_status(ThermoDev dev) +{ + return devs[dev].status; +} + + +/** + * Do a single thermo control for device \a dev. + */ +static void thermo_do(ThermoDev index) +{ + ThermoControlDev* dev = &devs[index]; + deg_t cur_temp; + deg_t tolerance = thermo_hw_tolerance(index); + + cur_temp = thermo_hw_read(index); + + // Store the sample into the hifi FIFO buffer for later interpolation + dev->hifi_samples[dev->cur_hifi_sample] = cur_temp; + if (++dev->cur_hifi_sample == THERMO_HIFI_NUM_SAMPLES) + dev->cur_hifi_sample = 0; + + cur_temp = thermo_readTemperature(index); + + if (cur_temp == NTC_SHORT_CIRCUIT || cur_temp == NTC_OPEN_CIRCUIT) + { + if (cur_temp == NTC_SHORT_CIRCUIT) + { + #ifdef _DEBUG + if (!(dev->status & THERMOERRF_NTCSHORT)) + kprintf("dev[%d], thermo_do: NTC_SHORT\n",index); + #endif + dev->status |= THERMOERRF_NTCSHORT; + } + else + { + #ifdef _DEBUG + if (!(dev->status & THERMOERRF_NTCOPEN)) + kprintf("dev[%d], thermo_do: NTC_OPEN\n", index); + #endif + dev->status |= THERMOERRF_NTCOPEN; + } + + /* Reset timeout when there is an ntc error */ + dev->expire = thermo_hw_timeout(index) + timer_clock(); + thermo_hw_off(index); + return; + } + dev->status &= ~(THERMOERRF_NTCOPEN | THERMOERRF_NTCSHORT); + + if ((cur_temp < dev->target - tolerance) || (cur_temp > dev->target + tolerance)) + { + dev->status &= ~THERMO_TGT_REACH; + + /* Check for timeout */ + if (timer_clock() - dev->expire > 0) + { + dev->status |= THERMOERRF_TIMEOUT; + kprintf("dev[%d], thermo_do: TIMEOUT\n", index); + } + } + else /* In target */ + { + /* Clear errors */ + dev->status &= ~THERMO_ERRMASK; + dev->status |= THERMO_TGT_REACH; + + /* Reset timeout in case we go out of target in the future */ + dev->expire = thermo_hw_timeout(index) + timer_clock(); + } + + if (cur_temp < dev->target) + dev->status = (dev->status | THERMO_HEATING) & ~THERMO_FREEZING; + else + dev->status = (dev->status & ~THERMO_HEATING) | THERMO_FREEZING; + + thermo_hw_set(index, dev->target, cur_temp); + +} + + +/** + * Thermo soft interrupt. + */ +static void thermo_softint(void) +{ + int i; + for (i = 0; i < THERMO_CNT; ++i) + if (devs[i].status & THERMO_ACTIVE) + thermo_do((ThermoDev)i); + + timer_add(&thermo_timer); +} + + +/** + * Set the target temperature \a temperature for a specific \a dev thermo-device. + */ +void thermo_setTarget(ThermoDev dev, deg_t temperature) +{ + ASSERT(dev < THERMO_CNT); + devs[dev].target = temperature; + devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); + + kprintf("setTarget dev[%d], T[%d.%d]\n", dev, temperature / 10, temperature % 10); +} + +/** + * Starts a thermo-regulation for channel \a dev. + */ +void thermo_start(ThermoDev dev) +{ + int i; + deg_t temp; + + ASSERT(dev < THERMO_CNT); + + devs[dev].status |= THERMO_ACTIVE; + + /* Initialize the hifi FIFO with a constant value (the current temperature) */ + temp = thermo_hw_read(dev); + for (i = 0; i < THERMO_HIFI_NUM_SAMPLES; ++i) + devs[dev].hifi_samples[i] = temp; + devs[dev].cur_hifi_sample = 0; + + /* Reset timeout */ + devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); +} + +/** + * Stops a thermo-regulation for channel \a dev. + */ +void thermo_stop(ThermoDev dev) +{ + ASSERT(dev < THERMO_CNT); + + devs[dev].status &= ~THERMO_ACTIVE; + thermo_hw_off(dev); +} + + +/** + * Clear errors for channel \a dev. + */ +void thermo_clearErrors(ThermoDev dev) +{ + ASSERT(dev < THERMO_CNT); + devs[dev].status &= ~(THERMO_ERRMASK); +} + + +/** + * Read the temperature of the thermo-device \a dev using mobile mean. + */ +deg_t thermo_readTemperature(ThermoDev dev) +{ + int i; + long accum = 0; + + MOD_CHECK(thermo); + + for (i = 0; i < THERMO_HIFI_NUM_SAMPLES; i++) + accum += devs[dev].hifi_samples[i]; + + return (deg_t)(accum / THERMO_HIFI_NUM_SAMPLES); +} + +MOD_DEFINE(thermo) + +/** + * Init thermo-control and associated hw. + */ +void thermo_init(void) +{ + THERMO_HW_INIT; + + /* Set all status to off */ + for (int i = 0; i < THERMO_CNT; i++) + devs[i].status = THERMO_OFF; + + MOD_INIT(thermo); + + timer_setDelay(&thermo_timer, ms_to_ticks(THERMO_INTERVAL_MS)); + timer_set_event_softint(&thermo_timer, (Hook)thermo_softint, 0); + timer_add(&thermo_timer); +} diff --git a/bertos/drv/thermo.h b/bertos/drv/thermo.h new file mode 100644 index 00000000..693c086d --- /dev/null +++ b/bertos/drv/thermo.h @@ -0,0 +1,122 @@ +/** + * \file + * + * + * \brief Thermo-control driver + * + * \version $Id$ + * + * \author Giovanni Bajo + * \author Francesco Sacchi + * + * This module implements multiple thermo controls, which is the logic needed to try + * keeping the temperature of a device constant. For this module, a "device" is a black box + * whose temperature can be measured, and which has a mean to make it hotter or colder. + * For instance, a device could be the combination of a NTC (analog temperature reader) and + * a Peltier connected to the same physic block. + * + * This module relies on a low-level driver to communicate with the device (implementation + * of the black box). This low-level driver also controls the units in which the temperature + * is expressed: thermo control treats it just as a number. + * + */ + +/*#* + *#* $Log$ + *#* Revision 1.3 2006/09/20 20:12:41 marco + *#* Names convention, MOD_* macros. + *#* + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 17:59:47 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.2 2005/06/14 10:13:36 batt + *#* Better thermo errors handling. + *#* + *#* Revision 1.1 2005/05/24 09:17:58 batt + *#* Move drivers to top-level. + *#* + *#* Revision 1.4 2005/05/10 16:55:10 batt + *#* Add timeout to thermo-regulator; better thermo control handling; change thermo_getStatus() to thermo_status(). + *#* + *#* Revision 1.3 2005/05/10 09:26:54 batt + *#* Add thermo_getStatus for getting status/errors of thermo control. + *#* + *#* Revision 1.2 2005/05/09 19:18:40 batt + *#* Remove old logs. + *#* + *#* Revision 1.1 2005/05/09 16:40:44 batt + *#* Add thermo-control driver + *#*/ + + +#ifndef DRV_THERMO_H +#define DRV_THERMO_H + +#include +#include + +void thermo_init(void); + + +/** + * Set the target temperature at which a given device should be kept. + * + * \param dev Device + * \param temperature Target temperature + */ +void thermo_setTarget(ThermoDev dev, deg_t temperature); + +/** Start thermo control for a certain device \a dev */ +void thermo_start(ThermoDev dev); + +/** Stop thermo control for a certain device \a dev */ +void thermo_stop(ThermoDev dev); + +/** Clear errors for channel \a dev */ +void thermo_clearErrors(ThermoDev dev); + +/** Return the status of the specific \a dev thermo-device. */ +thermostatus_t thermo_status(ThermoDev dev); + +/** + * Return the current temperature of a device currently under thermo + * control. + * + * \param dev Device + * \return Current temperature (Celsius degrees * 10) + */ +deg_t thermo_readTemperature(ThermoDev dev); + + +#endif /* DRV_THERMO_H */ diff --git a/bertos/drv/timer.c b/bertos/drv/timer.c new file mode 100644 index 00000000..0e756dbb --- /dev/null +++ b/bertos/drv/timer.c @@ -0,0 +1,339 @@ +/** + * \file + * + * + * \brief Hardware independent timer driver (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "timer.h" + +#include +#include +#include + +#include +#include +#include +#include + +/* + * Include platform-specific binding code if we're hosted. + * Try the CPU specific one for bare-metal environments. + */ +#if OS_HOSTED + #include OS_CSOURCE(timer) +#else + #include CPU_CSOURCE(timer) +#endif + +/* + * Sanity check for config parameters required by this module. + */ +#if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1) + #error CONFIG_KERNEL must be set to either 0 or 1 in config.h +#endif +#if !defined(CONFIG_WATCHDOG) || ((CONFIG_WATCHDOG != 0) && CONFIG_WATCHDOG != 1) + #error CONFIG_WATCHDOG must be set to either 0 or 1 in config.h +#endif + +#if CONFIG_WATCHDOG + #include +#endif + +#if CONFIG_KERNEL + #include + #if CONFIG_KERN_PREEMPTIVE + #include + #endif + #if CONFIG_KERN_SIGNALS + #include /* sig_wait(), sig_check() */ + #include /* proc_current() */ + #include /* BV() */ + #endif +#endif + + +/** + * \def CONFIG_TIMER_STROBE + * + * This is a debug facility that can be used to + * monitor timer interrupt activity on an external pin. + * + * To use strobes, redefine the macros TIMER_STROBE_ON, + * TIMER_STROBE_OFF and TIMER_STROBE_INIT and set + * CONFIG_TIMER_STROBE to 1. + */ +#if !defined(CONFIG_TIMER_STROBE) || !CONFIG_TIMER_STROBE + #define TIMER_STROBE_ON do {/*nop*/} while(0) + #define TIMER_STROBE_OFF do {/*nop*/} while(0) + #define TIMER_STROBE_INIT do {/*nop*/} while(0) +#endif + + +/// Master system clock (1 tick accuracy) +volatile ticks_t _clock; + + +#ifndef CONFIG_TIMER_DISABLE_EVENTS + +/** + * List of active asynchronous timers. + */ +REGISTER static List timers_queue; + + +/** + * Add the specified timer to the software timer service queue. + * When the delay indicated by the timer expires, the timer + * device will execute the event associated with it. + * + * \note Interrupt safe + */ +void timer_add(Timer *timer) +{ + Timer *node; + cpuflags_t flags; + + + /* Inserting timers twice causes mayhem. */ + ASSERT(timer->magic != TIMER_MAGIC_ACTIVE); + DB(timer->magic = TIMER_MAGIC_ACTIVE;) + + IRQ_SAVE_DISABLE(flags); + + /* Calculate expiration time for this timer */ + timer->tick = _clock + timer->_delay; + + /* + * Search for the first node whose expiration time is + * greater than the timer we want to add. + */ + node = (Timer *)LIST_HEAD(&timers_queue); + while (node->link.succ) + { + /* + * Stop just after the insertion point. + * (this fancy compare takes care of wrap-arounds). + */ + if (node->tick - timer->tick > 0) + break; + + /* Go to next node */ + node = (Timer *)node->link.succ; + } + + /* Enqueue timer request into the list */ + INSERT_BEFORE(&timer->link, &node->link); + + IRQ_RESTORE(flags); +} + + +/** + * Remove a timer from the timer queue before it has expired. + */ +Timer *timer_abort(Timer *timer) +{ + ATOMIC(REMOVE(&timer->link)); + DB(timer->magic = TIMER_MAGIC_INACTIVE;) + + return timer; +} + +#endif /* CONFIG_TIMER_DISABLE_EVENTS */ + + +/** + * Wait for the specified amount of timer ticks. + */ +void timer_delayTicks(ticks_t delay) +{ +#if defined(IRQ_ENABLED) + /* We shouldn't sleep with interrupts disabled */ + ASSERT(IRQ_ENABLED()); +#endif + +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS + Timer t; + + ASSERT(!sig_check(SIG_SINGLE)); + timer_set_event_signal(&t, proc_current(), SIG_SINGLE); + timer_setDelay(&t, delay); + timer_add(&t); + sig_wait(SIG_SINGLE); + +#else /* !CONFIG_KERN_SIGNALS */ + + ticks_t start = timer_clock(); + + /* Busy wait */ + while (timer_clock() - start < delay) + { +#if CONFIG_WATCHDOG + wdt_reset(); +#endif + } + +#endif /* !CONFIG_KERN_SIGNALS */ +} + + +#ifndef CONFIG_TIMER_DISABLE_UDELAY + +/** + * Busy wait until the specified amount of high-precision ticks have elapsed. + * + * \note This function is interrupt safe, the only + * requirement is a running hardware timer. + */ +void timer_busyWait(hptime_t delay) +{ + hptime_t now, prev = timer_hw_hpread(); + hptime_t delta; + + for(;;) + { + now = timer_hw_hpread(); + /* + * We rely on hptime_t being unsigned here to + * reduce the modulo to an AND in the common + * case of TIMER_HW_CNT. + */ + delta = (now - prev) % TIMER_HW_CNT; + if (delta >= delay) + break; + delay -= delta; + prev = now; + } +} + +/** + * Wait for the specified amount of time (expressed in microseconds). + * + * \bug In AVR arch the maximum amount of time that can be used as + * delay could be very limited, depending on the hardware timer + * used. Check timer_avr.h, and what register is used as hptime_t. + */ +void timer_delayHp(hptime_t delay) +{ + if (UNLIKELY(delay > us_to_hptime(1000))) + { + timer_delayTicks(delay / (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC)); + delay %= (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC); + } + + timer_busyWait(delay); +} +#endif /* CONFIG_TIMER_DISABLE_UDELAY */ + + +/** + * Timer interrupt handler. Find soft timers expired and + * trigger corresponding events. + */ +DEFINE_TIMER_ISR +{ + /* + * With the Metrowerks compiler, the only way to force the compiler generate + * an interrupt service routine is to put a pragma directive within the function + * body. + */ + #ifdef __MWERKS__ + #pragma interrupt saveall + #endif + +#ifndef CONFIG_TIMER_DISABLE_EVENTS + Timer *timer; +#endif + /* + * On systems sharing IRQ line and vector, this check is needed + * to ensure that IRQ is generated by timer source. + */ + if (!timer_hw_triggered()) + return; + + TIMER_STROBE_ON; + + /* Perform hw IRQ handling */ + timer_hw_irq(); + + /* Update the master ms counter */ + ++_clock; + +#ifndef CONFIG_TIMER_DISABLE_EVENTS + /* + * Check the first timer request in the list and process + * it when it has expired. Repeat this check until the + * first node has not yet expired. Since the list is sorted + * by expiry time, all the following requests are guaranteed + * to expire later. + */ + while ((timer = (Timer *)LIST_HEAD(&timers_queue))->link.succ) + { + /* This request in list has not yet expired? */ + if (_clock - timer->tick < 0) + break; + + /* Retreat the expired timer */ + REMOVE(&timer->link); + DB(timer->magic = TIMER_MAGIC_INACTIVE;) + + /* Execute the associated event */ + event_do(&timer->expire); + } +#endif /* CONFIG_TIMER_DISABLE_EVENTS */ + + TIMER_STROBE_OFF; +} + +MOD_DEFINE(timer) + +/** + * Initialize timer + */ +void timer_init(void) +{ + TIMER_STROBE_INIT; + +#ifndef CONFIG_TIMER_DISABLE_EVENTS + LIST_INIT(&timers_queue); +#endif + + _clock = 0; + + timer_hw_init(); + + MOD_INIT(timer); +} diff --git a/bertos/drv/timer.h b/bertos/drv/timer.h new file mode 100644 index 00000000..cd7aa1b4 --- /dev/null +++ b/bertos/drv/timer.h @@ -0,0 +1,247 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Hardware independent timer driver (interface) + */ + +#ifndef DRV_TIMER_H +#define DRV_TIMER_H + +#include +#include +#include +#include + + +/* + * Include platform-specific binding header if we're hosted. + * Try the CPU specific one for bare-metal environments. + */ +#if OS_HOSTED + #include OS_HEADER(timer) +#else + #include CPU_HEADER(timer) +#endif + +#include +#include +#include +#include + + +extern volatile ticks_t _clock; + +/** + * \brief Return the system tick counter (expressed in ticks) + * + * The result is guaranteed to increment monotonically, + * but client code must be tolerant with respect to overflows. + * + * The following code is safe: + * + * \code + * ticks_t tea_start_time = timer_clock(); + * + * boil_water(); + * + * if (timer_clock() - tea_start_time > TEAPOT_DELAY) + * printf("Your tea, Sir.\n"); + * \endcode + * + * \note This function must disable interrupts on 8/16bit CPUs because the + * clock variable is larger than the processor word size and can't + * be copied atomically. + */ +INLINE ticks_t timer_clock(void) +{ + ticks_t result; + + ATOMIC(result = _clock); + + return result; +} + +/** + * Faster version of timer_clock(), to be called only when the timer + * interrupt is disabled (DISABLE_INTS) or overridden by a + * higher-priority or non-nesting interrupt. + * + * \sa timer_clock + */ +INLINE ticks_t timer_clock_unlocked(void) +{ + return _clock; +} + +/** Convert \a ms [ms] to ticks. */ +INLINE ticks_t ms_to_ticks(mtime_t ms) +{ +#if TIMER_TICKS_PER_SEC < 1000 + /* Slow timer: avoid rounding down too much. */ + return (ms * TIMER_TICKS_PER_SEC) / 1000; +#else + /* Fast timer: don't overflow ticks_t. */ + return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000); +#endif +} + +/** Convert \a us [us] to ticks. */ +INLINE ticks_t us_to_ticks(utime_t us) +{ +#if TIMER_TICKS_PER_SEC < 1000 + /* Slow timer: avoid rounding down too much. */ + return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000; +#else + /* Fast timer: don't overflow ticks_t. */ + return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000; +#endif +} + +/** Convert \a ticks [ticks] to ms. */ +INLINE mtime_t ticks_to_ms(ticks_t ticks) +{ +#if TIMER_TICKS_PER_SEC < 1000 + /* Slow timer: avoid rounding down too much. */ + return (ticks * 1000) / TIMER_TICKS_PER_SEC; +#else + /* Fast timer: avoid overflowing ticks_t. */ + return ticks / (TIMER_TICKS_PER_SEC / 1000); +#endif +} + +/** Convert \a ticks [ticks] to us. */ +INLINE utime_t ticks_to_us(ticks_t ticks) +{ +#if TIMER_TICKS_PER_SEC < 1000 + /* Slow timer: avoid rounding down too much. */ + return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000; +#else + /* Fast timer: avoid overflowing ticks_t. */ + return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000; +#endif +} + +/** Convert \a us [us] to hpticks */ +INLINE hptime_t us_to_hptime(utime_t us) +{ +#if TIMER_HW_HPTICKS_PER_SEC > 10000000UL + return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL); +#else + return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL; +#endif +} + +/** Convert \a hpticks [hptime] to usec */ +INLINE utime_t hptime_to_us(hptime_t hpticks) +{ +#if TIMER_HW_HPTICKS_PER_SEC < 100000UL + return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC); +#else + return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL); +#endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */ +} + + +void timer_init(void); +void timer_delayTicks(ticks_t delay); +INLINE void timer_delay(mtime_t delay) +{ + timer_delayTicks(ms_to_ticks(delay)); +} + +#if !defined(CONFIG_TIMER_DISABLE_UDELAY) +void timer_busyWait(hptime_t delay); +void timer_delayHp(hptime_t delay); +INLINE void timer_udelay(utime_t delay) +{ + timer_delayHp(us_to_hptime(delay)); +} +#endif + +#ifndef CONFIG_TIMER_DISABLE_EVENTS + +#include + +/** + * The timer driver supports multiple synchronous timers + * that can trigger an event when they expire. + * + * \sa timer_add() + * \sa timer_abort() + */ +typedef struct Timer +{ + Node link; /**< Link into timers queue */ + ticks_t _delay; /**< Timer delay in ms */ + ticks_t tick; /**< Timer will expire at this tick */ + Event expire; /**< Event to execute when the timer expires */ + DB(uint16_t magic;) +} Timer; + +/** Timer is active when Timer.magic contains this value (for debugging purposes). */ +#define TIMER_MAGIC_ACTIVE 0xABBA +#define TIMER_MAGIC_INACTIVE 0xBAAB + +extern void timer_add(Timer *timer); +extern Timer *timer_abort(Timer *timer); + +/** Set the timer so that it calls an user hook when it expires */ +INLINE void timer_set_event_softint(Timer *timer, Hook func, iptr_t user_data) +{ + event_initSoftInt(&timer->expire, func, user_data); +} + +/** Set the timer delay (the time before the event will be triggered) */ +INLINE void timer_setDelay(Timer *timer, ticks_t delay) +{ + timer->_delay = delay; +} + +#endif /* CONFIG_TIMER_DISABLE_EVENTS */ + +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS + +/** Set the timer so that it sends a signal when it expires */ +INLINE void timer_set_event_signal(Timer *timer, struct Process *proc, sigmask_t sigs) +{ + event_initSignal(&timer->expire, proc, sigs); +} + +#endif /* CONFIG_KERN_SIGNALS */ + + +#endif /* DRV_TIMER_H */ diff --git a/bertos/drv/timer_posix.c b/bertos/drv/timer_posix.c new file mode 100644 index 00000000..e6149cea --- /dev/null +++ b/bertos/drv/timer_posix.c @@ -0,0 +1,75 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Low-level timer module for Qt emulator (implementation). + */ +#include // hptime.t +#include + +#include // sigaction() +#include // setitimer() +#include // memset() + + +// Forward declaration for the user interrupt server routine. +void timer_isr(int); + +/// HW dependent timer initialization. +static void timer_hw_init(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + + // Setup interrupt callback + sa.sa_handler = timer_isr; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGALRM); + sa.sa_flags = SA_RESTART; + sigaction(SIGALRM, &sa, NULL); + + // Setup POSIX realtime timer to interrupt every 1/TIMER_TICKS_PER_SEC. + static struct itimerval itv = + { + { 0, 1000000 / TIMER_TICKS_PER_SEC }, /* it_interval */ + { 0, 1000000 / TIMER_TICKS_PER_SEC } /* it_value */ + }; + setitimer(ITIMER_REAL, &itv, NULL); +} + +INLINE hptime_t timer_hw_hpread(void) +{ + return hptime_get(); +} diff --git a/bertos/drv/timer_posix.h b/bertos/drv/timer_posix.h new file mode 100644 index 00000000..fd2e9c60 --- /dev/null +++ b/bertos/drv/timer_posix.h @@ -0,0 +1,59 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Low-level timer module for POSIX systems (interface). + */ +#ifndef DRV_TIMER_POSIX_H +#define DRV_TIMER_POSIX_H + +// HW dependent timer initialization + +#define DEFINE_TIMER_ISR void timer_isr(UNUSED_ARG(int, arg)) + +/** Most Linux kernels can't do better than this (CONFIG_HZ=250). */ +#define TIMER_TICKS_PER_SEC 250 + +#define TIMER_HW_CNT (1<<31) /* We assume 32bit integers here */ + +#include + +/// Frequency of the hardware high-precision timer. +#define TIMER_HW_HPTICKS_PER_SEC HPTIME_TICKS_PER_SECOND + +/// Not needed. +#define timer_hw_irq() do {} while (0) + +#endif /* DRV_TIMER_POSIX_H */ diff --git a/bertos/drv/timer_qt.c b/bertos/drv/timer_qt.c new file mode 100644 index 00000000..6f96da64 --- /dev/null +++ b/bertos/drv/timer_qt.c @@ -0,0 +1,129 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Low-level timer module for Qt emulator (implementation). + */ +#include /* hptime.t */ + +// Qt headers +#include +#include + + +// The user interrupt server routine +void timer_isr(void); + + +/** + * Singleton class for Qt-based hardware timer emulation. + */ +class EmulTimer : public QObject +{ +private: + Q_OBJECT; + + /// System timer (counts ms since application startup) + QTime system_time; + + /// The 1ms "hardware" tick counter. + QTimer timer; + + /** + * We deliberately don't use RAII because the real hardware + * we're simulating needs to be initialized manually. + */ + bool initialized; + + /// Private ctor (singleton) + EmulTimer() : initialized(false) { } + +public: + /// Return singleton instance + static EmulTimer &instance() + { + static EmulTimer et; + return et; + } + + /// Start timer emulator. + void init() + { + // Timer initialized twice? + ASSERT(!initialized); + + // Record initial time + system_time.start(); + + // Activate timer interrupt + timer.connect(&timer, SIGNAL(timeout()), this, SLOT(timerInterrupt())); + timer.start(1000 / TIMER_TICKS_PER_SEC); + + initialized = true; + } + + /// Return current time in high-precision format. + hptime_t hpread() + { + ASSERT(initialized); + return system_time.elapsed(); + } + +public slots: + void timerInterrupt(void) + { + // Just call user interrupt server, timer restarts automatically. + timer_isr(); + } + +}; + +#include "timer_qt_moc.cpp" + + +/// HW dependent timer initialization. +static void timer_hw_init(void) +{ + // Kick EmulTimer initialization + EmulTimer::instance().init(); +} + +INLINE hptime_t timer_hw_hpread(void) +{ + return EmulTimer::instance().hpread(); +} + +/** Not needed, timer IRQ handler called only for timer source */ +#define timer_hw_triggered() (true) diff --git a/bertos/drv/timer_qt.h b/bertos/drv/timer_qt.h new file mode 100644 index 00000000..76268fd4 --- /dev/null +++ b/bertos/drv/timer_qt.h @@ -0,0 +1,57 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Low-level timer module for Qt emulator (interface). + */ +#ifndef DRV_TIMER_QT_H +#define DRV_TIMER_QT_H + +// HW dependent timer initialization + +#define DEFINE_TIMER_ISR void timer_isr(void) +#define TIMER_TICKS_PER_SEC 250 +#define TIMER_HW_CNT (1<<31) /* We assume 32bit integers here */ + +/// Type of time expressed in ticks of the hardware high-precision timer. +typedef unsigned int hptime_t; + +/// Frequency of the hardware high-precision timer. +#define TIMER_HW_HPTICKS_PER_SEC 1000 + +/// Not needed. +#define timer_hw_irq() do {} while (0) + +#endif /* DRV_TIMER_QT_H */ diff --git a/bertos/drv/timer_test.c b/bertos/drv/timer_test.c new file mode 100644 index 00000000..170105de --- /dev/null +++ b/bertos/drv/timer_test.c @@ -0,0 +1,134 @@ +/** + * \file + * + * + * \brief Hardware independent timer driver (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "timer.c" +#include "mware/event.c" +#include "os/hptime.c" + +static void timer_test_constants(void) +{ + kprintf("TIMER_HW_HPTICKS_PER_SEC=%lu\n", TIMER_HW_HPTICKS_PER_SEC); + #ifdef TIMER_PRESCALER + kprintf("TIMER_PRESCALER=%d\n", TIMER_PRESCALER); + #endif + #ifdef TIMER1_OVF_COUNT + kprintf("TIMER1_OVF_COUNT=%d\n", (int)TIMER1_OVF_COUNT); + #endif + kprintf("TIMER_TICKS_PER_SEC=%d\n", (int)TIMER_TICKS_PER_SEC); + kprintf("\n"); + kprintf("ms_to_ticks(100)=%lu\n", ms_to_ticks(100)); + kprintf("ms_to_ticks(10000)=%lu\n", ms_to_ticks(10000)); + kprintf("us_to_ticks(100)=%lu\n", us_to_ticks(100)); + kprintf("us_to_ticks(10000)=%lu\n", us_to_ticks(10000)); + kprintf("\n"); + kprintf("ticks_to_ms(100)=%lu\n", ticks_to_ms(100)); + kprintf("ticks_to_ms(10000)=%lu\n", ticks_to_ms(10000)); + kprintf("ticks_to_us(100)=%lu\n", ticks_to_us(100)); + kprintf("ticks_to_us(10000)=%lu\n", ticks_to_us(10000)); + kprintf("\n"); + kprintf("hptime_to_us(100)=%lu\n", hptime_to_us(100)); + kprintf("hptime_to_us(10000)=%lu\n", hptime_to_us(10000)); + kprintf("us_to_hptime(100)=%lu\n", us_to_hptime(100)); + kprintf("us_to_hptime(10000)=%lu\n", us_to_hptime(10000)); +} + +static void timer_test_delay(void) +{ + int i; + + kputs("Delay test\n"); + for (i = 0; i < 1000; i += 100) + { + kprintf("delay %d...", i); + timer_delay(i); + kputs("done\n"); + } +} + +static void timer_test_hook(iptr_t _timer) +{ + Timer *timer = (Timer *)(void *)_timer; + + kprintf("Timer %ld expired\n", ticks_to_ms(timer->_delay)); + timer_add(timer); +} + +static void timer_test_async(void) +{ + static Timer test_timers[5]; + static const mtime_t test_delays[5] = { 170, 50, 310, 1500, 310 }; + size_t i; + + for (i = 0; i < countof(test_timers); ++i) + { + Timer *timer = &test_timers[i]; + timer_setDelay(timer, ms_to_ticks(test_delays[i])); + timer_set_event_softint(timer, timer_test_hook, (iptr_t)timer); + timer_add(timer); + } +} + +static void timer_test_poll(void) +{ + int secs = 0; + mtime_t start_time = ticks_to_ms(timer_clock()); + mtime_t now; + + while (secs <= 10) + { + now = ticks_to_ms(timer_clock()); + if (now - start_time >= 1000) + { + ++secs; + start_time += 1000; + kprintf("seconds = %d, ticks=%ld\n", secs, now); + } + wdt_reset(); + } +} + +int main(void) +{ + wdt_init(7); + timer_init(); + timer_test_constants(); + timer_test_delay(); + timer_test_async(); + timer_test_poll(); + return 0; +} diff --git a/bertos/drv/wdt.h b/bertos/drv/wdt.h new file mode 100644 index 00000000..1db10538 --- /dev/null +++ b/bertos/drv/wdt.h @@ -0,0 +1,166 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Watchdog interface + */ + +#ifndef DRV_WDT_H +#define DRV_WDT_H + +#include +#include // INLINE +#include + +/* Configury sanity check */ +#if !defined(CONFIG_WATCHDOG) || (CONFIG_WATCHDOG != 0 && CONFIG_WATCHDOG != 1) + #error CONFIG_WATCHDOG must be defined to either 0 or 1 +#endif + +#if CONFIG_WATCHDOG + #include + #include + + #if OS_QT + #if _QT < 4 + #include + #else + #include + #endif + #elif OS_POSIX + #include + #elif CPU_AVR + #include + #include // BV() + #if CPU_AVR_ATMEGA1281 // Name is different in atmega1281 + #define WDTCR WDTCSR + #endif + #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) + #include /* taskYIELD() */ + #else + #error unknown CPU + #endif +#endif /* CONFIG_WATCHDOG */ + +/** + * Reset the watchdog timer. + */ +INLINE void wdt_reset(void) +{ +#if CONFIG_WATCHDOG + #if OS_QT + // Let Qt handle events + ASSERT(qApp); + qApp->processEvents(); + #elif OS_POSIX + static struct timeval tv = { 0, 0 }; + select(0, NULL, NULL, NULL, &tv); + #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) + vTaskDelay(1); + #elif CPU_AVR + __asm__ __volatile__ ("wdr"); + #else + #error unknown CPU + #endif +#endif /* CONFIG_WATCHDOG */ +} + +/** + * Set watchdog timer timeout. + * + * \param timeout 0: 16.3ms, 7: 2.1s + */ +INLINE void wdt_init(uint8_t timeout) +{ +#if CONFIG_WATCHDOG + #if OS_QT + // Create a dummy QApplication object + if (!qApp) + { + int argc; + new QApplication(argc, (char **)NULL); + } + (void)timeout; + #elif OS_POSIX + (void)timeout; // NOP + #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) + /* nop */ + #elif CPU_AVR + WDTCR |= BV(WDCE) | BV(WDE); + WDTCR = timeout; + #else + #error unknown CPU + #endif +#else + (void)timeout; +#endif /* CONFIG_WATCHDOG */ +} + +INLINE void wdt_start(void) +{ +#if CONFIG_WATCHDOG + #if OS_QT + // NOP + #elif OS_POSIX + // NOP + #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) + /* nop */ + #elif CPU_AVR + WDTCR |= BV(WDE); + #else + #error unknown CPU + #endif +#endif /* CONFIG_WATCHDOG */ +} + +INLINE void wdt_stop(void) +{ +#if CONFIG_WATCHDOG + #if OS_QT + // NOP + #elif OS_POSIX + // NOP + #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) + /* nop */ + #elif CPU_AVR + WDTCR |= BV(WDCE) | BV(WDE); + WDTCR &= ~BV(WDE); + #else + #error unknown CPU + #endif +#endif /* CONFIG_WATCHDOG */ +} + +#endif /* DRV_WDT_H */ diff --git a/bertos/dt/dnotifier.c b/bertos/dt/dnotifier.c new file mode 100644 index 00000000..502ce284 --- /dev/null +++ b/bertos/dt/dnotifier.c @@ -0,0 +1,188 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Notifier obj (implementation). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.5 2005/06/09 13:49:22 batt + *#* Reformat; correct some comments. + *#* + *#* Revision 1.4 2005/06/09 13:23:58 batt + *#* Add some comments. + *#* + *#* Revision 1.3 2005/06/08 17:32:33 batt + *#* Switch to new messaging system. + *#* + *#* Revision 1.2 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#include + +#include
+#include
+#include + +/** + * Default update used to notify target: notify all trasparently all + * targets in the list. + */ +static void notifier_update(DNotifier *n, dtag_t tag, dval_t val) +{ + dnotify_targets(n, tag, val); +} + +/** + * Init. + */ +void notifier_init(DNotifier *n) +{ + // Init instance + n->update = notifier_update; + LIST_INIT(&n->targets); +} + +/** + * Search in the map a tag and a val corresponding to the ones supplied. + * If a match is found change them to the corresponding ones in the map. + * If map is NULL the filter is trasparent and all messages sent to filter + * will be forwarded to its target. + */ +void filter_update(DFilter *f, dtag_t tag, dval_t val) +{ + + const DFilterMap *map = f->map; + + if (map) + { + while (map->src.tag != TAG_END) + { + if ((map->src.tag == tag) && (map->src.val == val)) + { + tag = map->dst.tag; + val = map->dst.val; + break; + } + /* TAG_ANY matches anything */ + if (map->src.tag == TAG_ANY) + break; + map++; + } + + if (map->src.tag != TAG_END) + dnotify(f->target, tag, val); + } + else + dnotify(f->target, tag, val); +} + + +/** + * Search in the table a tag corresponding to the one supplied and a val + * that has at least the mask map supplied bits to one. + * If a match is found change them to the corresponding ones in the map. + * If map is NULL the filter is trasparent and all messages sent to filter + * will be forwarded to its target. + */ +void filter_mask_update(DFilter *f, dtag_t tag, dval_t val) +{ + + const DFilterMap *map = f->map; + dfilter_mask_t mask; + + if (map) + { + while (map->src.tag != TAG_END) + { + mask = (dfilter_mask_t) map->src.val; + if ((map->src.tag == tag) && ((mask & (dfilter_mask_t)val) == mask)) + { + tag = map->dst.tag; + val = map->dst.val; + break; + } + /* TAG_ANY matches anything */ + if (map->src.tag == TAG_ANY) + break; + map++; + } + + + if (map->src.tag != TAG_END) + dnotify(f->target, tag, val); + } + else + dnotify(f->target, tag, val); +} + + +#define FILTER_MAGIC_ACTIVE 0xAA +/** + * Init filter. + * If \a masked is true, all the fields value in \a map must be interpreted as a mask of bits. + */ +void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target) +{ + // Init instance + if (masked) + f->update = (update_filter_ptr)filter_mask_update; + else + f->update = (update_filter_ptr)filter_update; + + /* set filter map and target */ + f->map = map; + f->target = target; + + /* these ensure that the filter is not inserted in more than one list */ + ASSERT(f->magic != FILTER_MAGIC_ACTIVE); + DB(f->magic = FILTER_MAGIC_ACTIVE;) + + /* Add the filter to source filter list */ + ADDTAIL(&source->targets, &f->link); +} diff --git a/bertos/dt/dnotifier.h b/bertos/dt/dnotifier.h new file mode 100644 index 00000000..118a2f4c --- /dev/null +++ b/bertos/dt/dnotifier.h @@ -0,0 +1,173 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Notifier obj (interface). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.4 2005/06/09 13:23:58 batt + *#* Add some comments. + *#* + *#* Revision 1.3 2005/06/08 17:32:33 batt + *#* Switch to new messaging system. + *#* + *#* Revision 1.2 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ +#ifndef DT_DNOTIFIER_H +#define DT_DNOTIFIER_H + +#include +#include
+#include + +//Fwd declaretion. +struct DNotifier; +struct DFilter; + +typedef void (* update_func_ptr)(struct DNotifier *, dtag_t, dval_t); +typedef void (* update_filter_ptr)(struct DFilter *, dtag_t, dval_t); + +/** + * Base object for receive and forward messages. + * It contains an update function used to update itslef and a list to + * notify other DNotifer eventually connected. + */ +typedef struct DNotifier +{ + /// Receive new attributes from other notifiers. + update_func_ptr update; + + /// List of target notifiers to set new attributes to. + List targets; +} DNotifier; + +/** + * Map for messages. + * Used to translate src message to dst message. + */ +typedef struct DFilterMap +{ + DTagItem src; + DTagItem dst; +} DFilterMap; + + +/** + * A filter is an interface between two notifier. + * It can translate messages between them through a map (if it is not null). + */ +typedef struct DFilter +{ + /// Allow creating a list of dfilter objects. + Node link; + + /// Target of the filter + DNotifier *target; + + /// Update function called by the source dnotifier + update_filter_ptr update; + + ///Map for translating messages for target + const DFilterMap *map; + + ///Used in debug to prevent inserting this filter in more than one list + DB(uint8_t magic;) +} DFilter; + +/// Type for filter-mask checking +typedef uint16_t dfilter_mask_t; + +/// Filter init +void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target); + +/// Filter update function without masking capabilities. +void filter_update(DFilter *f, dtag_t tag, dval_t val); + +/// Filter update function with masking capabilities. +void filter_mask_update(DFilter *f, dtag_t tag, dval_t val); + +/// Notifier init +void notifier_init(DNotifier *n); + + +/** + * Macro to notify the target object. + */ +INLINE void dnotify(DNotifier *target, dtag_t tag, dval_t val) +{ + if (target) + target->update(target, tag, val); +} + +/** + * Macro to notify all the targets of \a target object. + */ +INLINE void dnotify_targets(DNotifier *target, dtag_t tag, dval_t val) +{ + DFilter *f; + if (!ISLISTEMPTY(&target->targets)) + FOREACHNODE(f, &target->targets) + f->update(f, tag, val); +} + + +/** + * Macro that connect \a src notifier to \a tgt using \a map and passing \a opt for filtering option. + * It declares a static filter to achieve connection and messages translation. + * \note Due its static filter declaration, DCONNECT MUST NOT be used inside loops or in functions called multiple times. + * Failing to do so will lead to unpredictable connections between notifiers. + */ +#define DCONNECT(src, tgt, map, opt) \ + do { \ + static DFilter _filter_; /* Declare a filter */ \ + filter_init(&(_filter_), map, opt, src, tgt); /* Init it. */ \ + } while (0) + + +#endif /* DT_DNOTIFIER_H */ diff --git a/bertos/dt/dtag.h b/bertos/dt/dtag.h new file mode 100644 index 00000000..5ecbfa75 --- /dev/null +++ b/bertos/dt/dtag.h @@ -0,0 +1,113 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Tags interface. + * This module contains the base message definitions and the list of all available tags. + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.8 2005/06/07 15:22:29 batt + *#* Add const_dval_t. + *#* + *#* Revision 1.7 2005/06/06 17:42:23 batt + *#* Add error tag TAG_ERROR. + *#* + *#* Revision 1.6 2005/06/06 12:45:33 batt + *#* Add TAG_NONE tag. + *#* + *#* Revision 1.5 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.4 2005/05/31 11:09:52 batt + *#* Add some tags. + *#* + *#* Revision 1.3 2005/05/26 14:55:12 batt + *#* Add form_processTime; change form_kbdProcess to form_processKey. + *#* + *#* Revision 1.2 2005/05/26 14:43:33 batt + *#* Add new message filter interface. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#ifndef DT_DTAG_H +#define DT_DTAG_H + +#include + +/** Type for values associated with tags. */ +typedef iptr_t dval_t; + +/** Type for constant values associated with tags. */ +typedef const_iptr_t const_dval_t; + +/** Type for tag */ +typedef enum dtag_t +{ + TAG_END = 0, + TAG_NONE, + TAG_ANY, + TAG_SETVALUE, + TAG_UP, + TAG_DOWN, + TAG_START, + TAG_STOP, + TAG_TOGGLE, + TAG_KEY, + TAG_TIME, + TAG_ERROR, +} dtag_t; + +/** This is the basic message structure used by all dnotifiers. */ +typedef struct DTagItem +{ + dtag_t tag; + dval_t val; +} DTagItem; + +/** Marker to indicate the end of a map for message filtering/translating */ +#define TAG_END_MARKER {{TAG_END, 0}, {TAG_END, 0}} +#endif diff --git a/bertos/dt/dwidget.c b/bertos/dt/dwidget.c new file mode 100644 index 00000000..096f84d2 --- /dev/null +++ b/bertos/dt/dwidget.c @@ -0,0 +1,77 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Widget (implementation). + * A widget is typically a graphic object on a device. + * Its proproperties are the position, the size and a context on which the widget is drawn. + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.3 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.2 2005/05/26 14:44:10 batt + *#* Abstract widget from layer: use context. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#include
+#include
+ +/** + * Init the widget of \a pos and \a size on the drawing \a context. + */ +void widget_init(DWidget *w, dpos_t pos, dpos_t size, dcontext_t *context) +{ + // Init superclass + notifier_init(&w->notifier); + + // Init instance + w->pos = pos; + w->size = size; + w->context = context; +} diff --git a/bertos/dt/dwidget.h b/bertos/dt/dwidget.h new file mode 100644 index 00000000..8c240dd4 --- /dev/null +++ b/bertos/dt/dwidget.h @@ -0,0 +1,85 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Widget (interface). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.3 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.2 2005/05/26 14:44:10 batt + *#* Abstract widget from layer: use context. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#ifndef DT_DWIDGET_H +#define DT_DWIDGET_H + +#include
+#include + +/** Widget position. */ +typedef uint8_t dpos_t; + +/** Widget drawing context. */ +typedef iptr_t dcontext_t; + +/** Widget definition. */ +typedef struct DWidget +{ + DNotifier notifier; + + dpos_t pos; + dpos_t size; + dcontext_t *context; +} DWidget; + + +void widget_init(DWidget *w, dpos_t pos, dpos_t size, dcontext_t *context); + +#endif diff --git a/bertos/dt/editbool.c b/bertos/dt/editbool.c new file mode 100644 index 00000000..55e94480 --- /dev/null +++ b/bertos/dt/editbool.c @@ -0,0 +1,120 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Edit bool widget (implementation). + * This widget handles boolean editing. + * The boolean value will be displayed using two strings: + * one when the bool is false and one when it's true. + * + * \version $Id$ + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.3 2005/06/08 17:32:33 batt + *#* Switch to new messaging system. + *#* + *#* Revision 1.2 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.1 2005/05/31 11:11:37 batt + *#* Edit bool: first release. + *#* + *#*/ + +#include +#include
+ +#include + +/** + * Init widget. + */ +void editbool_init(DEditBool *e, dpos_t pos, dpos_t size, dcontext_t *context, bool *value, const char *true_string, const char *false_string) +{ + // Initialize superclass + widget_init(&e->widget, pos, size, context); + + // Override superclass methods + e->widget.notifier.update = (update_func_ptr)editbool_update; + + // Init instance + e->value = value; + e->true_string = true_string; + e->false_string = false_string; + e->draw = editbool_draw; +} + +/** + * Handle the messages (edit the bool). + */ +void editbool_update(DEditBool *e, dtag_t tag, dval_t _val) +{ + bool changed = false; + + switch (tag) + { + case TAG_SETVALUE: + *e->value = (bool)_val; + changed = true; + break; + + case TAG_TOGGLE: + *e->value = !*e->value; + changed = true; + break; + default: + break; + } + + if (changed) + { + e->draw(e); + dnotify_targets(&e->widget.notifier, TAG_SETVALUE, (dval_t)*e->value); + } +} + +/** + * Draw the string on the context. + */ +void editbool_draw(DEditBool *e) +{ + lcd_printf((Layer *)e->widget.context, (lcdpos_t)e->widget.pos, LCD_NORMAL, "%*s", (int)e->widget.size , *e->value? e->true_string: e->false_string); +} diff --git a/bertos/dt/editbool.h b/bertos/dt/editbool.h new file mode 100644 index 00000000..360484a5 --- /dev/null +++ b/bertos/dt/editbool.h @@ -0,0 +1,76 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Edit bool widget (interface). + * + * \version $Id$ + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.2 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.1 2005/05/31 11:11:37 batt + *#* Edit bool: first release. + *#* + *#*/ + +#ifndef DT_EDITBOOL_H +#define DT_EDITBOOL_H + +#include
+#include
+ +typedef struct DEditBool +{ + DWidget widget; + bool *value; + const char *true_string; + const char *false_string; + void (*draw)(struct DEditBool *); +} DEditBool; + +void editbool_init(DEditBool *e, dpos_t pos, dpos_t size, dcontext_t *context, bool *val, const char *true_str, const char *false_str); +void editbool_update(DEditBool *e, dtag_t tag, dval_t val); +void editbool_draw(DEditBool *e); + + +#endif diff --git a/bertos/dt/editint.c b/bertos/dt/editint.c new file mode 100644 index 00000000..8ddcb7ed --- /dev/null +++ b/bertos/dt/editint.c @@ -0,0 +1,159 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Integer edit widget (implementation). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.7 2005/06/10 15:46:09 batt + *#* Add EDIS_WRAP style that wrap around min and max. + *#* + *#* Revision 1.6 2005/06/08 17:32:33 batt + *#* Switch to new messaging system. + *#* + *#* Revision 1.5 2005/06/06 11:04:12 batt + *#* Add some comments. + *#* + *#* Revision 1.4 2005/05/31 11:09:34 batt + *#* Fix sending pointer instead of value bug. + *#* + *#* Revision 1.3 2005/05/26 14:46:20 batt + *#* Use correct tag; remove warning. + *#* + *#* Revision 1.2 2005/05/26 14:44:10 batt + *#* Abstract widget from layer: use context. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#include +#include
+#include
+#include
+ +#include + +#include + +/** + * Init. + */ +void editint_init(DEditInt *e, dpos_t pos, dpos_t size, dcontext_t *context, int *value, int min, int max) +{ + // Initialize superclass + widget_init(&e->widget, pos, size, context); + + // Override superclass methods + e->widget.notifier.update = (update_func_ptr)editint_update; + + // Init instance + e->value = value; + e->min = min; + e->max = max; + e->style = EDIS_DEFAULT; + e->draw = editint_draw; +} + +/** + * Handle the messages (edit the int). + */ +void editint_update(DEditInt *e, dtag_t tag, dval_t _val) +{ + bool changed = false; + int val = (int)_val; + + switch (tag) + { + case TAG_SETVALUE: + *e->value = MINMAX(e->min, val, e->max); + changed = true; + break; + + /* Increments the integer by val */ + case TAG_UP: + if (e->style & EDIS_WRAP) + { + if (*e->value + val > e->max) + *e->value = (*e->value + val - e->min) % (e->max - e->min + 1) + e->min; + else + *e->value += val; + } + else + *e->value = MIN(*e->value + val, e->max); + changed = true; + break; + /* Decrements the integer by val */ + case TAG_DOWN: + if (e->style & EDIS_WRAP) + { + if (*e->value - val < e->min) + *e->value = e->max - (e->max - (*e->value - val)) % (e->max - e->min + 1); + else + *e->value -= val; + } + else + *e->value = MAX(*e->value - val, e->min); + changed = true; + break; + + default: + break; + } + + if (changed) + { + e->draw(e); + dnotify_targets(&e->widget.notifier, TAG_SETVALUE, (dval_t)*e->value); + } +} + +/** + * Draw the integer on the context. + */ +void editint_draw(DEditInt *e) +{ + lcd_printf((Layer *)e->widget.context, (lcdpos_t)e->widget.pos, LCD_NORMAL,"%*d", (int)e->widget.size, *e->value); +} diff --git a/bertos/dt/editint.h b/bertos/dt/editint.h new file mode 100644 index 00000000..1b707696 --- /dev/null +++ b/bertos/dt/editint.h @@ -0,0 +1,94 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Integer edit (interface). + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/11/04 18:26:38 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.3 2005/06/10 15:46:09 batt + *#* Add EDIS_WRAP style that wrap around min and max. + *#* + *#* Revision 1.2 2005/05/26 14:44:10 batt + *#* Abstract widget from layer: use context. + *#* + *#* Revision 1.1 2005/05/26 08:32:53 batt + *#* Add new Develer widget system :) + *#* + *#*/ + +#ifndef DT_EDITINT_H +#define DT_EDITINT_H + +#include
+#include
+#include + +#include +#include + + +#define EDIS_DEFAULT 0 +#define EDIS_CURSORLEFT BV(0) +#define EDIS_WRAP BV(1) + +/** Type for edit style */ +typedef uint16_t dstyle_t; + +typedef struct DEditInt +{ + DWidget widget; + + int *value; + int min; + int max; + dstyle_t style; + void (*draw)(struct DEditInt *); + +} DEditInt; + +void editint_init(DEditInt *e, dpos_t pos, dpos_t size, dcontext_t *context, int *value, int min, int max); +void editint_update(DEditInt *e, dtag_t tag, dval_t val); +void editint_draw(DEditInt *e); + +#endif diff --git a/bertos/emul/emul.cpp b/bertos/emul/emul.cpp new file mode 100644 index 00000000..ad081db1 --- /dev/null +++ b/bertos/emul/emul.cpp @@ -0,0 +1,149 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Qt-based emulator framework for embedded applications (implementation) + */ + +/*#* + *#* $Log$ + *#* Revision 1.6 2006/05/28 12:17:57 bernie + *#* Drop almost all the Qt3 cruft. + *#* + *#* Revision 1.5 2006/05/27 22:30:56 bernie + *#* Add some delay to slow things down. + *#* + *#* Revision 1.4 2006/02/24 01:35:40 bernie + *#* Update for new emulator. + *#* + *#* Revision 1.3 2006/02/20 02:00:40 bernie + *#* Port to Qt 4.1. + *#* + *#* Revision 1.2 2006/01/16 03:51:51 bernie + *#* Fix boilerplate. + *#* + *#* Revision 1.1 2006/01/16 03:37:12 bernie + *#* Add emulator skeleton. + *#* + *#*/ + +#include "emul.h" +#include "emulwin.h" +#include + +#include +#if CONFIG_KERNEL + #include +#endif + + +#include // std::exit() + +#include + + +/// The global emulator instance. +Emulator *emul; + +#if CONFIG_KERNEL + #include + + /// List of process stacks + List StackFreeList; + + // HACK: Reserve 64KB of stack space for kernel processes + const int NPROC = 8; + int stacks[NPROC][(64 * 1024) / sizeof(int)]; +#endif + +Emulator::Emulator(int &argc, char **argv) : + emulApp(new QApplication(argc, argv)), + emulWin(new EmulWin(this)) +{ + emulWin->show(); +} + + +Emulator::~Emulator() +{ + // we don't delete emulWin because it automatically + // deletes itself when closed + delete emulApp; +} + + +NORETURN void Emulator::quit() +{ + // WHAT A KLUDGE! + this->~Emulator(); + emul = NULL; + + // do we have a better way to shut down the emulation? + exit(0); +} + +MOD_DEFINE(emul) + +/// Main emulator entry point. +extern "C" void emul_init(int *argc, char *argv[]) +{ + // setup global emulator pointer + emul = new Emulator(*argc, argv); + +#if CONFIG_KERNEL + LIST_INIT(&StackFreeList); + for (int i = 0; i < NPROC; i++) + ADDTAIL(&StackFreeList, (Node *)stacks[i]); +#endif + + MOD_INIT(emul); +} + +extern "C" void emul_cleanup() +{ + MOD_CLEANUP(emul); + + delete emul; + emul = NULL; +} + +extern "C" void emul_idle() +{ + // We process GUI events when the application is idle. + emul->emulApp->processEvents(); + usleep(1000); +} + diff --git a/bertos/emul/emul.h b/bertos/emul/emul.h new file mode 100644 index 00000000..80d3ecc2 --- /dev/null +++ b/bertos/emul/emul.h @@ -0,0 +1,101 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Qt-based emulator framework for embedded applications (interface) + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/02/15 09:11:17 bernie + *#* Add keyboard emulator. + *#* + *#* Revision 1.3 2006/01/23 23:12:08 bernie + *#* Let Doxygen see through C++ protected section. + *#* + *#* Revision 1.2 2006/01/16 03:51:51 bernie + *#* Fix boilerplate. + *#* + *#* Revision 1.1 2006/01/16 03:37:12 bernie + *#* Add emulator skeleton. + *#* + *#*/ + +#ifndef EMUL_EMUL_H +#define EMUL_EMUL_H + +#include + +#if defined(__cplusplus) || defined(__doxygen__) + +// fwd decls +class QApplication; +class EmulWin; +class EmulPRT; +class EmulLCD; +class EmulKbd; +class QCheckBox; +class QSlider; +class QLabel; + +class Emulator +{ +// data members +public: + QApplication *emulApp; ///< QT Application. + EmulWin *emulWin; ///< Main window. + + EmulLCD *emulLCD; ///< Display emulator. + EmulKbd *emulKbd; ///< Keyboard emulator. + +// construction + Emulator(int &argc, char **argv); + ~Emulator(); + +// public methods + void quit(); +}; + +extern Emulator *emul; + +#endif /* __cplusplus */ + +EXTERN_C void emul_init(int *argc, char *argv[]); +EXTERN_C void emul_cleanup(); +EXTERN_C void emul_idle(); + +#endif /* EMUL_EMUL_H */ + diff --git a/bertos/emul/emul.mk b/bertos/emul/emul.mk new file mode 100644 index 00000000..b7ddf358 --- /dev/null +++ b/bertos/emul/emul.mk @@ -0,0 +1,13 @@ +# +# Copyright 2007 Bernardo Innocenti (http://www.codewiz.org/) +# All rights reserved. +# +# Author: Bernardo Innocenti +# +# Qt configuration for devlib emulator demo. Include it from +# your app Makefile fragment + +EMUL_CFLAGS = $(shell pkg-config QtCore QtGui --cflags) -DQT_CLEAN_NAMESPACE -DQT3_SUPPORT +EMUL_LDFLAGS = $(shell pkg-config QtCore QtGui --libs) +QT_MOC = $(shell pkg-config QtCore --variable=moc_location) +#QT_UIC = $(shell pkg-config QtCore --variable=uic_location) diff --git a/bertos/emul/emulkbd.cpp b/bertos/emul/emulkbd.cpp new file mode 100644 index 00000000..19c6d880 --- /dev/null +++ b/bertos/emul/emulkbd.cpp @@ -0,0 +1,232 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief QT-based widget for keyboard emulation (implementation) + */ + +#include "emulkbd.h" +#include "emul.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +EmulKey::EmulKey(EmulKbd *kbd, const char *label, int _keycode, int _row, int _col) : + QPushButton(label, kbd), + row(_row), col(_col), + keycode(_keycode) +{ + // don't let the widget get focus + setFocusPolicy(Qt::NoFocus); + + // unused + connect(this, SIGNAL(pressed()), this, SLOT(keyPressed())); + connect(this, SIGNAL(released()), this, SLOT(keyReleased())); +} + + +EmulKey::~EmulKey() +{ + // nop +} + + +/** + * Override standad QButton behaviour: we must also emit the signals. + */ +// unused +void EmulKey::setDown(bool enable) +{ + // let our superclass do everything else + QPushButton::setDown(enable); + + if (enable) + emit pressed(); + else + emit released(); +} + + +// unused +void EmulKey::keyPressed(void) +{ + static_cast(parent())->setKey(row, col, true); +} + + +// unused +void EmulKey::keyReleased(void) +{ + static_cast(parent())->setKey(row, col, false); +} + + +EmulKbd::EmulKbd(QWidget *parent, Qt::WFlags f) : + QFrame(parent, f), + layout(new QGridLayout(this)), + active_row(0) +{ + setFrameStyle(QFrame::Box | QFrame::Sunken); + setLineWidth(1); + setFocusPolicy(Qt::StrongFocus); + frame_width = frameWidth(); +} + + +EmulKbd::~EmulKbd() +{ + delete layout; +} + + +QSizePolicy EmulKbd::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + + +void EmulKbd::resizeEvent(QResizeEvent *event) +{ + // Let our superclass process the event first + QFrame::resizeEvent(event); +} + + +// handle key presses for all keys in keyboard +bool EmulKbd::event(QEvent *_e) +{ + switch (_e->type()) + { + case QEvent::KeyPress: + case QEvent::KeyRelease: + { + QKeyEvent *e = static_cast(_e); + int keycode = e->key(); + EmulKey *key; + + // ignore repeated keys + if (!e->isAutoRepeat()) + { + // scan all children + for (QObjectList::const_iterator it(children().begin()); it != children().end(); ++it) + { + // only keys, not other children! + if ((*it)->metaObject() == &EmulKey::staticMetaObject) + // if ((key = dynamic_cast(*it))) + { + key = static_cast(*it); + + // same key? + if (key->keycode == keycode) + { + // yes, tell key to go down (or up) + key->setDown(_e->type() == QEvent::KeyPress); + break; + } + } + } + } + return true; + } + + default: + // let superclass process this event + return QFrame::event(_e); + + } // end switch(_e->type()) +} + + +void EmulKbd::addKey(const char *label, int keycode, int row, int col, int matrix_row, int matrix_col) +{ + if (matrix_row == -1) + matrix_row = row; + if (matrix_col == -1) + matrix_col = col; + + layout->addWidget(new EmulKey(this, label, keycode, matrix_row, matrix_col), row, col); +} + + +// unused +void EmulKbd::setKey(int /*row*/, int /*col*/, bool /*on*/) +{ +} + + +void EmulKbd::setRow(int r) +{ + active_row = r; +} + +int EmulKbd::readCols(void) +{ + QLayoutItem *item; + EmulKey *key; + int cols = 0; + + // FIXME: QLayoutIterator is obsolete in Qt4 + for(QLayoutIterator it(layout->iterator()); (item = it.current()); ++it) + { + key = static_cast(item->widget()); + if (key->row == active_row) + { + if (key->isDown()) + cols |= (1<col); + } + } + return cols; +} + +extern "C" void emul_kbdSetRows(int r) +{ + emul->emulKbd->setRow(r); +} + + +extern "C" int emul_kbdReadCols(void) +{ + return emul->emulKbd->readCols(); +} + +#include "emulkbd_moc.cpp" diff --git a/bertos/emul/emulkbd.h b/bertos/emul/emulkbd.h new file mode 100644 index 00000000..82048367 --- /dev/null +++ b/bertos/emul/emulkbd.h @@ -0,0 +1,119 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief QT-based widget for leyboard emulation (interface) + */ + +#if !defined(EMULKBD_H) +#define EMULKBD_H + +#if defined (_MSC_VER) && (_MSC_VER > 1000) +#pragma once +#endif // _MSC_VER > 1000 + +#include + +// fwd decl +class QGridLayout; +class EmulKey; + +class EmulKbd : public QFrame +{ + Q_OBJECT + +// Data members +protected: + QGridLayout *layout; + int frame_width; + int active_row; + +// Construction +public: + EmulKbd(QWidget *parent = 0, Qt::WFlags f = 0); + virtual ~EmulKbd(); + +// Public methods + void addKey(const char *label, int keycode, int row, int col, int matrix_row = -1, int matrix_col = -1); + void setRow(int row); + int readCols(void); + +// Protected methods +protected: + void setKey(int row, int col, bool on); + +// Base class overrides +protected: + virtual QSizePolicy sizePolicy() const; + virtual void resizeEvent(QResizeEvent *e); + virtual bool event(QEvent *e); + +// Friends + friend class EmulKey; +}; + + +// Private helper class for EmulKbd +// NOTE: with protected inheritance, dynamic_cast<> does not work (gcc 2.96) +#include +class EmulKey : public QPushButton +{ + Q_OBJECT + +// Data members +protected: + int row, col; + int keycode; + +// Construction +public: + EmulKey(EmulKbd *parent, const char *label, int keycode, int _row, int _col); + virtual ~EmulKey(); + +// superclass overrides + void setDown(bool enable); + +protected slots: + void keyPressed(void); + void keyReleased(void); + +// Friends +public: + friend class EmulKbd; +}; + +#endif // !defined(EMULKBD_H) + diff --git a/bertos/emul/emulwin.cpp b/bertos/emul/emulwin.cpp new file mode 100644 index 00000000..b5f57cd4 --- /dev/null +++ b/bertos/emul/emulwin.cpp @@ -0,0 +1,130 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Main Qt window for embedded applications emulator (implementation) + */ + +#include "emulwin.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace Qt; + +EmulWin::EmulWin(Emulator *e) +{ + setWindowTitle(tr("BeRTOS Emul Demo")); + setAttribute(Qt::WA_DeleteOnClose); + + // Create the menu bar + QMenu *file_menu = menuBar()->addMenu(tr("&File")); + file_menu->addAction(tr("&Quit"), + e->emulApp, SLOT(closeAllWindows()), CTRL+Key_Q); + + menuBar()->addSeparator(); + + QMenu *help_menu = menuBar()->addMenu(tr("&Help")); + help_menu->addAction(tr("&About"), + this, SLOT(about()), Key_F1); + + // Make a central widget to contain the other widgets + QWidget *central = new QWidget(this); + setCentralWidget(central); + + // Create a layout to position the widgets + QHBoxLayout *box_main = new QHBoxLayout(central); + + // Main layout + QVBoxLayout *box_right = new QVBoxLayout(); + box_main->addLayout(box_right); + + // LCD + QHBoxLayout *lay_lcd = new QHBoxLayout(); + box_right->addLayout(lay_lcd); + lay_lcd->addStretch(); + lay_lcd->addWidget(e->emulLCD = new EmulLCD(central)); + lay_lcd->addStretch(); + + // Keyboard + box_right->addWidget(e->emulKbd = new EmulKbd(central)); + + // Setup keyboard: Label Keycode Row Col MRow MCol + e->emulKbd->addKey("^", Key_Up, 0, 0, 0, 0); + e->emulKbd->addKey("v", Key_Down, 1, 0, 0, 1); + e->emulKbd->addKey("OK", Key_Return, 0, 1, 0, 2); + e->emulKbd->addKey("ESC", Key_Escape, 1, 1, 0, 3); +} + + +EmulWin::~EmulWin() +{ + emul->quit(); +} + + +void EmulWin::closeEvent(QCloseEvent *ce) +{ + emul->quit(); + ce->accept(); +} + + +void EmulWin::about() +{ + QMessageBox::about(this, + "BeRTOS Embedded Application Emulator", + "Version 0.1\n" + "Copyright 2006, 2008 Develer S.r.l. (http://www.develer.com/)\n" + "Copyright 2001, 2002, 2003, 2005 Bernardo Innocenti \n" + "All rights reserved." + ); +} + +#include "emulwin_moc.cpp" diff --git a/bertos/emul/emulwin.h b/bertos/emul/emulwin.h new file mode 100644 index 00000000..8ce6c8bf --- /dev/null +++ b/bertos/emul/emulwin.h @@ -0,0 +1,82 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Main Qt window for embedded applications emulator (interface) + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/05/28 12:17:56 bernie + *#* Drop almost all the Qt3 cruft. + *#* + *#* Revision 1.3 2006/02/20 02:00:39 bernie + *#* Port to Qt 4.1. + *#* + *#* Revision 1.2 2006/01/16 03:51:51 bernie + *#* Fix boilerplate. + *#* + *#* Revision 1.1 2006/01/16 03:37:12 bernie + *#* Add emulator skeleton. + *#* + *#*/ + +#ifndef EMUL_EMULWIN_H +#define EMUL_EMULWIN_H + +#include + +// fwd decls +class Emulator; + +class EmulWin : public QMainWindow +{ + Q_OBJECT + +// construction +public: + EmulWin(Emulator *emul); + ~EmulWin(); + +protected: + void closeEvent(QCloseEvent *); + +private slots: + void about(); +}; + +#endif // EMUL_EMULWIN_H + diff --git a/bertos/fonts/convbdf b/bertos/fonts/convbdf new file mode 100755 index 00000000..61307cd8 --- /dev/null +++ b/bertos/fonts/convbdf @@ -0,0 +1,209 @@ +#! /usr/bin/perl -w +# +# Convert BDF files to nano-X font files +# modified by G Haerr from bdftobogl for 16 bit MWIMAGEBITS +# modified on 2/10/00 by K Harris to accept any size input character +# modified on 3/26/00 by G Haerr added ascent field, fixed $IMAGE_BITS +# modified on 2/15/06 by for DevLib. +# originally from BOGL - Ben's Own Graphics Library . +# + +use POSIX; + +if ($#ARGV < 0) { + print "Usage: convbdf font.bdf > font.c\n"; + exit -1; +} + +$LAST_CHAR = 0xff; +$IMAGE_BITS = 8; +$IMAGE_NIBBLES = $IMAGE_BITS/4; +$IMAGE_MASK = 0xff; +$IMAGE_VERTICAL = 1; + +$file = $ARGV[0]; + +$font = $file; +$font =~ s#.*/##; # remove path name +$font =~ s/\.bdf//; +$font =~ tr/a-zA-Z0-9_/_/cs; + +print "/* Generated by convbdf on ", substr(`date`, 0, -1), ". */\n"; +print "#include \n\n"; + +open BDF, "<$file" || die; +while () { + chop; + $pixel_size = $1 if /^PIXEL_SIZE (\d+)$/; + $font_ascent = $1 if /^FONT_ASCENT (\d+)$/; + $font_descent = $1 if /^FONT_DESCENT (\d+)$/; + $font_name = $1 if /^FONT (.*)$/; + $default_char = $1 if /^DEFAULT_CHAR (\d+)$/; + + last if /^CHARS /; +} + +print "/* Font information:\n\n"; +print " name: $font_name\n"; +print " pixel size: $pixel_size\n"; +print " ascent: $font_ascent\n"; +print " descent: $font_descent\n"; +print "*/\n\n"; + +print "/* Font character bitmap data. */\n"; +print "static const PROGMEM uint8_t font_${font}_glyphs[] = {\n"; + +$ch_height = $font_ascent + $font_descent; +$ofs = 0; +$maxwidth = 0; +$proportional = 0; +$firstchar = -1; +while () { + chop; + undef $encoding, undef $width, undef $bbx, undef $bby, undef $bbw, undef $bbh if /^STARTCHAR /; + $encoding = $1 if /^ENCODING (\d+)/; + last if defined $encoding && $encoding > $LAST_CHAR; + $width = $1 if /^DWIDTH (-?\d+)/; + ($bbw, $bbh, $bbx, $bby) = ($1, $2, $3, $4) if /^BBX (-?\d+) (-?\d+) (-?\d+) (-?\d+)/; + + if (/^BITMAP$/) { + next if !defined $encoding; + $firstchar = $encoding if $firstchar < 0; + $encoding_tab[$encoding] = $ofs; + $width -= $bbx, $bbx = 0 if $bbx < 0; + $width[$encoding] = $width; + $maxwidth != 0 and $width != $maxwidth and $proportional = 1; + $maxwidth = $width if $width > $maxwidth; + $ch_words = int (($width+$IMAGE_BITS-1)/$IMAGE_BITS); + $ch_bits = $ch_words*$IMAGE_BITS; + for (my $i = 0; $i < $ch_height; $i++) { + for (my $k = 0; $k < $ch_words; $k++) { + $bm[$i][$k] = 0; + } + } + for (my $i = 0; ; $i++) { + $_ = ; + chop; + last if /^ENDCHAR$/; + + @hexnibbles = split //,$_; + for (my $k=0; $k<$ch_words; $k++) { + $ndx = $k*$IMAGE_NIBBLES; + $padnibbles = @hexnibbles - $ndx; + # if bbx pushes bits into next word + # and no more bits from bdf file + last if $padnibbles <= 0; + $padnibbles = 0 if $padnibbles >= $IMAGE_NIBBLES; + $value = hex join '',@hexnibbles[$ndx..($ndx+$IMAGE_NIBBLES-1-$padnibbles)]; + $value = $value << ($padnibbles*$IMAGE_NIBBLES); + $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k] |= + $value >> ($bbx); + if ($bbx) { # handle overflow into next image_word + $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k+1] = + ($value << ($IMAGE_BITS - $bbx)) & $IMAGE_MASK; + } + } + } + + # GLYPH PREVIEW +### printf "\n/* Character %c (0x%02x): ", $encoding, $encoding; + printf "\n/* Character (0x%02x): ", $encoding; + print "bbw=$bbw, bbh=$bbh, bbx=$bbx, bby=$bby, width=$width */\n"; + + # GLYPH DATA + if ($IMAGE_VERTICAL) { + my $bitstring = ""; + for (my $k = 0; $k < int(($ch_height + $IMAGE_BITS - 1) / $IMAGE_BITS); $k++) { + for (my $x = 0; $x < $width; $x++) { + my $v = 0; + for (my $y = 0; $y < $IMAGE_BITS && ($y + $k * $IMAGE_BITS < $ch_height); ++$y) { + my $bit = ($bm[$k * $IMAGE_BITS + $y][int($x / $IMAGE_BITS)] & (1 << ($IMAGE_BITS - ($x % $IMAGE_BITS) - 1))) ? 1 : 0; + $bitstring .= $bit ? '*' : ' '; + $v |= $bit << $y; + } + $ofs++; + printf "0x%02x, ", $v; + } + # Preview + printf "/* $bitstring */\n"; + } + + } + else { # IMAGE_HORIZONTAL + + # Preview + print " +", ("-" x $ch_bits), "+\n"; + for (my $i = 0; $i < $ch_height; $i++) { + print " |"; + for (my $k = 0; $k < $ch_words; $k++) { + for (my $j = $IMAGE_BITS - 1; $j >= 0; $j--) { + print $bm[$i][$k] & (1 << $j) ? "*" : " "; + } + } + print "|\n"; + } + print " +", ("-" x $ch_bits), "+ */\n"; + + for (my $i = 0; $i < $ch_height; $i++) { + for (my $k=0; $k<$ch_words; $k++) { + $ofs++; + printf "0x%02x, ", $bm[$i][$k]; + } + printf "\n"; + } + } + } +} + +print "};\n\n"; + +#print STDERR "Maximum character width=$maxwidth\n"; + +if ($proportional) { + print "/* Character->glyph data. */\n"; + print "static const PROGMEM uint16_t ${font}_offset[] = {\n"; + for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) { + my $char = $i; + my $ofs = $encoding_tab[$i]; + $ofs = $encoding_tab[$default_char], $char = $default_char if !defined $ofs; + ### printf " $ofs,\t/* %c (0x%02x) */\n", $char, $i; + printf " $ofs,\t/* (0x%02x) */\n", $i; + } + print "};\n\n"; + + print "/* Character width data. */\n"; + print "static const PROGMEM uint8_t ${font}_width[] = {\n"; + for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) { + my $char = $i; + my $width = $width[$i]; + $width = $width[$default_char], $char = $default_char if !defined $encoding_tab[$i]; + ### printf " $width,\t/* %c (0x%02x) */\n", $char, $i; + printf " $width,\t/* (0x%02x) */\n", $i; + } + print "};\n\n"; + + $font_offset = "${font}_offset"; + $font_width = "${font}_width"; +} else { + $font_offset = "NULL"; + $font_width = "NULL"; +} + +$lastchar = $LAST_CHAR; +#$size = $lastchar - $firstchar + 1; + +print < + * + * --> + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Font 8x6 IBM-PC 8bit + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2006/05/27 22:30:22 bernie + *#* Move 6x8 font to fonts/. + *#* + *#* Revision 1.3 2006/02/10 12:29:05 bernie + *#* Add multiple font support in bitmaps. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.6 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.5 2005/01/08 09:20:38 bernie + *#* Add missing type in declaration. + *#* + *#* Revision 1.4 2004/12/31 16:42:55 bernie + *#* Sanitize for non-Harvard processors. + *#* + *#* Revision 1.3 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 15:43:16 bernie + *#* Import mware modules. + *#*/ + +#include "font.h" + +static const PROGMEM uint8_t default_font_glyphs[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, /*  */ +/* 0x80 */ + 0x38, 0xC4, 0xC4, 0x44, 0x28, 0x00, /* € */ + 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x00, /*  */ + 0x38, 0x54, 0x54, 0x55, 0x19, 0x00, /* ‚ */ + 0x22, 0x55, 0x55, 0x55, 0x78, 0x00, /* ƒ */ + 0x20, 0x55, 0x54, 0x54, 0x79, 0x00, /* „ */ + 0x21, 0x75, 0x55, 0x54, 0x78, 0x00, /* … */ + 0x20, 0x74, 0x57, 0x54, 0x78, 0x00, /* † */ + 0x08, 0x54, 0x54, 0x74, 0x14, 0x00, /* ‡ */ +/* 0x88 */ + 0x3A, 0x55, 0x55, 0x55, 0x1A, 0x00, /* ˆ */ + 0x39, 0x54, 0x54, 0x55, 0x18, 0x00, /* ‰ */ + 0x39, 0x55, 0x55, 0x54, 0x18, 0x00, /* Š */ + 0x00, 0x45, 0x7C, 0x41, 0x00, 0x00, /* ‹ */ + 0x02, 0x45, 0x7D, 0x42, 0x00, 0x00, /* Œ */ + 0x01, 0x45, 0x7D, 0x40, 0x00, 0x00, /*  */ + 0x79, 0x14, 0x12, 0x14, 0x79, 0x00, /* Ž */ + 0x70, 0x2B, 0x2B, 0x2B, 0x70, 0x00, /*  */ +/* 0x90 */ + 0x7C, 0x54, 0x55, 0x55, 0x45, 0x00, /*  */ + 0x20, 0x54, 0x38, 0x54, 0x48, 0x00, /* ‘ */ + 0x7E, 0x09, 0x7F, 0x49, 0x49, 0x00, /* ’ */ + 0x32, 0x49, 0x49, 0x49, 0x32, 0x00, /* “ */ + 0x32, 0x48, 0x48, 0x48, 0x32, 0x00, /* ” */ + 0x32, 0x4A, 0x4A, 0x48, 0x30, 0x00, /* • */ + 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x00, /* – */ + 0x3A, 0x42, 0x42, 0x20, 0x78, 0x00, /* — */ +/* 0x98 */ + 0x0D, 0x50, 0x50, 0x50, 0x3D, 0x00, /* ˜ */ + 0x19, 0x24, 0x42, 0x24, 0x19, 0x00, /* ™ */ + 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x00, /* š */ + 0x18, 0x24, 0x7E, 0x24, 0x24, 0x00, /* › */ + 0x28, 0x5E, 0x29, 0x42, 0x20, 0x00, /* œ */ + 0x09, 0x2A, 0x7C, 0x2A, 0x09, 0x00, /*  */ + 0x7F, 0x05, 0x15, 0x3D, 0x52, 0x00, /* ž */ + 0x20, 0x48, 0x3E, 0x09, 0x02, 0x00, /* Ÿ */ +/* 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 /* ÿ */ +}; + +struct Font default_font = +{ + /* .glyph = */ default_font_glyphs, + /* .width = */ 6, + /* .height = */ 8 +}; + diff --git a/bertos/fonts/fonts.mk b/bertos/fonts/fonts.mk new file mode 100644 index 00000000..e3831ee1 --- /dev/null +++ b/bertos/fonts/fonts.mk @@ -0,0 +1,12 @@ +# +# $Id$ +# Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/) +# All rights reserved. +# +# Makefile fragment for DevLib demo application. +# +# Author: Bernardo Innocenti +# + +%.c: %.bdf + bertos/fonts/convbdf $< > $@ diff --git a/bertos/fonts/helvB10.bdf b/bertos/fonts/helvB10.bdf new file mode 100644 index 00000000..fe548f54 --- /dev/null +++ b/bertos/fonts/helvB10.bdf @@ -0,0 +1,3305 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-R-Normal--10-100-75-75-P-60-ISO8859-1 +SIZE 10 75 75 +FONTBOUNDINGBOX 11 13 -1 -2 +COMMENT $XConsortium: helvB10.bdf,v 1.13 95/01/26 18:01:30 gildea Exp $ +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 28 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 10 +POINT_SIZE 100 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 8 +X_HEIGHT 6 +FONT_ASCENT 10 +FONT_DESCENT 2 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" +DEFAULT_CHAR 32 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 229 +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 0 +BITMAP +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 5 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +50 +50 +FC +50 +F8 +A0 +A0 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -1 +BITMAP +20 +70 +A8 +E0 +70 +38 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +62 +B4 +68 +10 +10 +2C +56 +8C +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +70 +D8 +D8 +70 +DE +CC +DC +76 +ENDCHAR +STARTCHAR quoteright +ENCODING 39 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +20 +60 +40 +C0 +C0 +C0 +C0 +40 +60 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +80 +C0 +40 +60 +60 +60 +60 +40 +C0 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +40 +40 +40 +80 +ENDCHAR +STARTCHAR minus +ENCODING 45 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 2 1 0 +BITMAP +80 +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 4 8 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +18 +38 +58 +58 +98 +FC +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +18 +98 +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +C0 +F0 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +70 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +D8 +D8 +78 +18 +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +80 +00 +00 +80 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +40 +00 +00 +40 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 5 3 0 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 4 5 0 1 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +D8 +18 +30 +60 +60 +00 +60 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A480 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +F8 +CC +CC +CC +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +CC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +F8 +C0 +C0 +F0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3C +66 +C2 +C0 +CE +C6 +66 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +FC +CC +CC +CC +CC +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +18 +18 +18 +18 +D8 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +CC +D8 +F0 +E0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 9 0 -1 +BITMAP +38 +6C +C6 +C6 +C6 +D6 +6C +3C +02 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +CC +CC +CC +F8 +CC +CC +CC +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +78 +CC +E0 +78 +1C +8C +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 10 8 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +6D80 +6D80 +7F80 +3300 +2100 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +C6 +C6 +6C +38 +38 +6C +C6 +C6 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +0C +18 +30 +70 +60 +C0 +FC +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 0 -2 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 5 0 +BBX 5 4 0 4 +BITMAP +20 +70 +D8 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 -2 +BITMAP +FC +ENDCHAR +STARTCHAR quoteleft +ENCODING 96 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 5 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 6 0 0 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +18 +18 +78 +D8 +98 +98 +D8 +78 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 8 0 0 +BITMAP +70 +C0 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +C0 +C0 +F0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 -2 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 8 0 0 +BITMAP +C0 +C0 +D8 +F0 +E0 +F0 +D8 +CC +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +B6 +DB +DB +DB +DB +DB +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +B0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +68 +D8 +98 +98 +D8 +78 +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 4 0 +BBX 4 6 0 0 +BITMAP +B0 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 8 0 0 +BITMAP +C0 +C0 +E0 +C0 +C0 +C0 +C0 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +D8 +D8 +D8 +50 +70 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 6 0 0 +BITMAP +D6 +D6 +D6 +6C +6C +6C +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 0 +BITMAP +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 6 0 0 +BITMAP +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +30 +60 +60 +60 +C0 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 10 0 -2 +BITMAP +C0 +60 +60 +60 +30 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 2 0 2 +BITMAP +6C +D8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 8 1 -2 +BITMAP +C0 +00 +40 +40 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 -1 +BITMAP +10 +70 +D8 +A0 +A0 +D8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +38 +68 +60 +F0 +60 +60 +68 +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 6 0 1 +BITMAP +D8 +70 +D8 +D8 +70 +D8 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +84 +CC +48 +78 +FC +30 +FC +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 3 0 +BBX 1 10 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +70 +C8 +E0 +70 +98 +C8 +70 +38 +98 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +99 +A5 +A1 +9D +42 +3C +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +6C +D8 +6C +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +42 +BD +A5 +B9 +A5 +42 +3C +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 7 +BITMAP +E0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 4 0 +BBX 3 3 1 4 +BITMAP +60 +A0 +C0 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +60 +A0 +40 +E0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 3 +BITMAP +E0 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 7 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +D8 +D8 +D8 +D8 +D8 +E8 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 10 0 -2 +BITMAP +7C +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 1 0 3 +BITMAP +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +40 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 4 0 3 +BITMAP +40 +C0 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 3 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 3 0 1 +BITMAP +D8 +6C +D8 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +42 +C4 +48 +48 +12 +26 +2F +42 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 7 8 0 0 +BITMAP +42 +C4 +48 +48 +16 +2A +24 +4E +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 9 0 +BBX 8 8 0 0 +BITMAP +E2 +44 +28 +C8 +12 +26 +2F +42 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 -2 +BITMAP +30 +00 +30 +30 +60 +C0 +D8 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +10 +38 +38 +6C +6C +6C +FE +C6 +C6 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +3C00 +6C00 +6F80 +6C00 +FC00 +CC00 +CF80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 10 0 -2 +BITMAP +3C +66 +C2 +C0 +C0 +C2 +66 +3C +10 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +40 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +10 +20 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 11 0 0 +BITMAP +20 +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +50 +00 +F8 +C0 +C0 +F8 +C0 +C0 +C0 +F8 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 0 +BITMAP +40 +80 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +40 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F0 +D8 +CC +EC +CC +CC +D8 +F0 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +C6 +C6 +E6 +D6 +D6 +CE +CE +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +04 +08 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +28 +00 +38 +6C +C6 +C6 +C6 +C6 +6C +38 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +3A +6C +CE +D6 +D6 +E6 +6C +B8 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +20 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +08 +10 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +10 +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +28 +00 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 11 0 0 +BITMAP +04 +08 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +C0 +F8 +CC +CC +CC +F8 +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 8 0 0 +BITMAP +70 +C8 +C8 +D0 +C8 +C8 +C8 +D0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +40 +20 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +08 +10 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +30 +68 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +28 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +50 +50 +00 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +20 +50 +20 +70 +98 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 9 0 +BBX 8 6 0 0 +BITMAP +7E +9B +7F +D8 +DB +6E +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 5 0 +BBX 4 8 0 -2 +BITMAP +70 +D0 +C0 +C0 +D0 +70 +20 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +F8 +C0 +D8 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +80 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +20 +40 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 -1 0 +BITMAP +40 +A0 +00 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +A0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +60 +A0 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +28 +50 +00 +B0 +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +A0 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +70 +D8 +D8 +D8 +D8 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 6 0 0 +BITMAP +74 +D8 +F8 +D8 +D8 +70 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +40 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +20 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +D8 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +10 +20 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 5 10 0 -2 +BITMAP +C0 +C0 +F0 +D8 +C8 +C8 +D8 +F0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 11 0 -2 +BITMAP +50 +50 +00 +D8 +D8 +D8 +D8 +78 +30 +30 +60 +ENDCHAR +STARTCHAR Lslash +ENCODING -1 +SWIDTH 611 0 +DWIDTH 6 0 +BBX 6 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +7C +ENDCHAR +STARTCHAR OE +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 9 8 0 0 +BITMAP +3F80 +6C00 +CC00 +CF80 +CC00 +CC00 +6C00 +3F80 +ENDCHAR +STARTCHAR Scaron +ENCODING -1 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +78 +CC +70 +3C +CC +78 +ENDCHAR +STARTCHAR Ydieresis +ENCODING -1 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 8 0 0 +BITMAP +14 +00 +C3 +66 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Zcaron +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +28 +10 +00 +FC +18 +30 +60 +C0 +FC +ENDCHAR +STARTCHAR breve +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +90 +60 +ENDCHAR +STARTCHAR bullet +ENCODING -1 +SWIDTH 350 0 +DWIDTH 4 0 +BBX 2 2 1 2 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR caron +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +A0 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 6 +BITMAP +40 +A0 +ENDCHAR +STARTCHAR dagger +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING -1 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -2 +BITMAP +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR dotaccent +ENCODING -1 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 1 1 0 7 +BITMAP +80 +ENDCHAR +STARTCHAR dotlessi +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 6 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ellipsis +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 8 1 1 0 +BITMAP +DB +ENDCHAR +STARTCHAR emdash +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 10 1 0 3 +BITMAP +FFC0 +ENDCHAR +STARTCHAR endash +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 6 1 0 3 +BITMAP +FC +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +60 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 8 -1 0 +BITMAP +36 +66 +F6 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR florin +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +38 +60 +F8 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING -1 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 7 -1 0 +BITMAP +08 +10 +10 +20 +40 +40 +80 +ENDCHAR +STARTCHAR grave +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 6 +BITMAP +80 +40 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +60 +C0 +60 +ENDCHAR +STARTCHAR guilsinglright +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 3 1 1 +BITMAP +C0 +60 +C0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING -1 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR lslash +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 8 -1 0 +BITMAP +60 +60 +60 +70 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR oe +ENCODING -1 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 9 6 0 0 +BITMAP +7700 +CD80 +CF80 +CC00 +CD80 +7700 +ENDCHAR +STARTCHAR ogonek +ENCODING -1 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 2 0 -2 +BITMAP +80 +C0 +ENDCHAR +STARTCHAR perthousand +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +6200 +B400 +6800 +1000 +2D80 +56C0 +8D80 +ENDCHAR +STARTCHAR quotedblbase +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblleft +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING -1 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 3 0 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesingle +ENCODING -1 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR ring +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 3 0 5 +BITMAP +40 +A0 +40 +ENDCHAR +STARTCHAR scaron +ENCODING -1 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +70 +D8 +70 +18 +D8 +70 +ENDCHAR +STARTCHAR tilde +ENCODING -1 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 6 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR trademark +ENCODING -1 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 4 1 3 +BITMAP +E880 +4D80 +4A80 +4A80 +ENDCHAR +STARTCHAR zcaron +ENCODING -1 +SWIDTH 500 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +50 +20 +00 +F8 +18 +30 +60 +C0 +F8 +ENDCHAR +ENDFONT diff --git a/bertos/fonts/luBS14.bdf b/bertos/fonts/luBS14.bdf new file mode 100644 index 00000000..90c37be9 --- /dev/null +++ b/bertos/fonts/luBS14.bdf @@ -0,0 +1,13542 @@ +STARTFONT 2.1 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn , 2001-03-20 +COMMENT (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered +COMMENT trademark of Bigelow & Holmes. See LEGAL NOTICE file for terms +COMMENT of the license. +COMMENT GRID 0014 0014 0200 0200 +FONT -B&H-Lucida-Bold-R-Normal-Sans-14-140-75-75-P-92-ISO10646-1 +SIZE 14 72 72 +FONTBOUNDINGBOX 18 21 -1 -5 +STARTPROPERTIES 22 +COMMENT Begin LogicalFontDescription +FONTNAME_REGISTRY "" +FOUNDRY "B&H" +FAMILY_NAME "Lucida" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "Sans" +PIXEL_SIZE 14 +POINT_SIZE 140 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 92 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +COMMENT END LogicalFontDescription +FONT_ASCENT 13 +FONT_DESCENT 2 +DEFAULT_CHAR 0 +COPYRIGHT "Copyright Bigelow & Holmes 1986, 1985." +FACE_NAME "Lucida Sans Bold" +X_HEIGHT 8 +CAP_HEIGHT 10 +ENDPROPERTIES +CHARS 756 +STARTCHAR char0 +ENCODING 0 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 7 9 2 0 +BITMAP +AA +00 +82 +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 7 +BITMAP +D8 +D8 +90 +90 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 9 10 0 0 +BITMAP +1B00 +1B00 +1B00 +7F80 +3600 +3600 +FF80 +6C00 +6C00 +6C00 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 12 1 -1 +BITMAP +10 +7C +D6 +D0 +F0 +70 +1C +1E +16 +D6 +7C +10 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 898 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +7000 +D980 +DB00 +7200 +0400 +0800 +1380 +36C0 +66C0 +0380 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 792 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +3C00 +6600 +6600 +6400 +3980 +5980 +CD00 +C600 +E700 +7980 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +C0 +60 +60 +30 +30 +30 +30 +30 +30 +60 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 464 0 +DWIDTH 7 0 +BBX 5 5 1 5 +BITMAP +20 +A8 +70 +A8 +20 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 7 1 1 +BITMAP +10 +10 +10 +FE +10 +10 +10 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 289 0 +DWIDTH 5 0 +BBX 3 1 1 4 +BITMAP +E0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 2 1 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 596 0 +DWIDTH 8 0 +BBX 8 12 0 -1 +BITMAP +03 +06 +06 +0C +0C +18 +18 +30 +30 +60 +60 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 5 10 2 0 +BITMAP +18 +F8 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +7E +C7 +03 +03 +06 +0C +18 +60 +FF +FF +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +7E +C7 +03 +06 +3C +06 +03 +03 +C7 +7E +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +0C +1C +2C +4C +8C +FF +FF +0C +0C +0C +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 10 2 0 +BITMAP +FC +FC +80 +80 +FC +0E +06 +06 +CC +78 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3E +63 +C0 +DC +E6 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +FF +FF +06 +0C +18 +30 +30 +60 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +7E +C7 +C3 +72 +3C +4E +C7 +C3 +E3 +7E +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +67 +1B +03 +C6 +7C +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 6 7 2 1 +BITMAP +0C +38 +60 +C0 +60 +38 +0C +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 3 1 3 +BITMAP +FE +00 +FE +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 6 7 2 1 +BITMAP +C0 +70 +18 +0C +18 +70 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 572 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +78 +CC +0C +0C +18 +30 +30 +00 +30 +30 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +1E00 +6100 +4180 +8F80 +9980 +9980 +9980 +4EC0 +6000 +1F00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 669 0 +DWIDTH 10 0 +BBX 7 10 2 0 +BITMAP +FC +C6 +C6 +CC +F0 +CC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 10 2 0 +BITMAP +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 602 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 10 2 0 +BITMAP +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 2 10 2 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 501 0 +DWIDTH 6 0 +BBX 4 12 0 -2 +BITMAP +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 940 0 +DWIDTH 15 0 +BBX 11 10 2 0 +BITMAP +E0E0 +E0E0 +B160 +B160 +B160 +9A60 +9A60 +8C60 +8C60 +8060 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 10 2 0 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 657 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +F8 +CC +CC +CC +CC +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 12 1 -2 +BITMAP +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0300 +0180 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 10 2 0 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 735 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +C180 +C180 +C180 +6100 +6300 +6300 +3200 +3600 +1C00 +1C00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 10 1 0 +BITMAP +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 699 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +C6 +6C +6C +38 +38 +6C +6C +C6 +C6 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +F0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 596 0 +DWIDTH 8 0 +BBX 8 12 0 -1 +BITMAP +C0 +60 +60 +30 +30 +18 +18 +0C +0C +06 +06 +03 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +F0 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +F0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 6 7 2 3 +BITMAP +30 +30 +78 +48 +CC +84 +84 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 500 0 +DWIDTH 11 0 +BBX 9 1 1 -1 +BITMAP +FF80 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 2 9 +BITMAP +E0 +38 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 8 1 0 +BITMAP +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +C0 +C0 +C0 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 461 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +1E +30 +30 +FE +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 11 1 0 +BITMAP +C0 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 361 0 +DWIDTH 5 0 +BBX 4 13 0 -2 +BITMAP +30 +30 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 11 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 1006 0 +DWIDTH 14 0 +BBX 12 8 1 0 +BITMAP +DDE0 +EF70 +C630 +C630 +C630 +C630 +C630 +C630 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +3F +63 +C3 +C3 +C3 +C3 +67 +3B +03 +03 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 8 2 0 +BITMAP +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 8 1 0 +BITMAP +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 663 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +C6 +C6 +C6 +C6 +64 +68 +38 +38 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 8 1 0 +BITMAP +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 568 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +C6 +C6 +64 +38 +38 +4C +C6 +C6 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 10 1 -2 +BITMAP +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +FE +06 +0C +18 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +70 +C0 +C0 +60 +20 +C0 +20 +60 +C0 +C0 +C0 +70 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 12 1 -1 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 386 0 +DWIDTH 6 0 +BBX 4 12 1 -1 +BITMAP +E0 +30 +30 +60 +40 +30 +40 +60 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 687 0 +DWIDTH 9 0 +BBX 7 3 1 3 +BITMAP +72 +BA +9C +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 10 1 -2 +BITMAP +C0 +C0 +00 +40 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 12 1 -1 +BITMAP +08 +08 +3E +6A +C8 +C8 +C8 +C8 +68 +3E +08 +08 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 10 1 0 +BITMAP +1C +32 +30 +30 +FC +30 +30 +30 +60 +FE +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 9 10 0 0 +BITMAP +8080 +4100 +3E00 +6300 +6300 +6300 +6300 +3E00 +4100 +8080 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +C3 +C3 +62 +66 +34 +7E +18 +7E +18 +18 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 12 1 -1 +BITMAP +C0 +C0 +C0 +C0 +C0 +00 +00 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 6 11 2 -1 +BITMAP +78 +CC +C0 +70 +D8 +CC +6C +38 +0C +CC +78 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 2 3 9 +BITMAP +90 +90 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 825 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +1E00 +6180 +4080 +8E40 +9840 +9840 +8E40 +4080 +6180 +1E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 536 0 +DWIDTH 8 0 +BBX 6 6 1 4 +BITMAP +70 +18 +78 +D8 +D8 +6C +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 8 5 0 2 +BITMAP +33 +66 +CC +66 +33 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 4 1 1 +BITMAP +FE +02 +02 +02 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 289 0 +DWIDTH 5 0 +BBX 3 1 1 4 +BITMAP +E0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 7 1 3 +BITMAP +38 +44 +BA +B2 +AA +44 +38 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 1 3 9 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 241 0 +DWIDTH 4 0 +BBX 4 3 0 7 +BITMAP +60 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 7 1 1 +BITMAP +10 +10 +FE +10 +10 +00 +FE +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 5 6 1 4 +BITMAP +F0 +18 +18 +60 +C0 +F8 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 5 6 1 4 +BITMAP +F0 +18 +70 +18 +18 +F0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 9 +BITMAP +38 +E0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 699 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +FB +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 6 11 2 -1 +BITMAP +7C +F4 +F4 +F4 +F4 +74 +14 +14 +14 +14 +14 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 343 0 +DWIDTH 10 0 +BBX 2 2 4 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 3 2 3 -2 +BITMAP +20 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 4 6 1 4 +BITMAP +30 +F0 +30 +30 +30 +30 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 536 0 +DWIDTH 8 0 +BBX 6 6 1 4 +BITMAP +78 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 8 5 1 2 +BITMAP +CC +66 +33 +66 +CC +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 1066 0 +DWIDTH 14 0 +BBX 12 10 1 0 +BITMAP +6100 +E100 +6200 +6200 +64E0 +6560 +0A60 +0BF0 +1060 +1060 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 1066 0 +DWIDTH 14 0 +BBX 12 10 1 0 +BITMAP +6100 +E100 +6200 +6200 +64E0 +6530 +0870 +08E0 +1180 +11F0 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 1120 0 +DWIDTH 15 0 +BBX 13 10 1 0 +BITMAP +7080 +9880 +3100 +1A00 +9A70 +74B0 +0530 +09F8 +1030 +1030 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 572 0 +DWIDTH 8 0 +BBX 6 10 1 -2 +BITMAP +30 +30 +00 +30 +30 +60 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +7000 +1C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +0700 +1C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1C00 +2600 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1A00 +2C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 773 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +24 +24 +00 +18 +18 +2C +2C +66 +46 +FE +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1C00 +2600 +1C00 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 997 0 +DWIDTH 13 0 +BBX 11 10 1 0 +BITMAP +1FE0 +1600 +2600 +2600 +67C0 +4600 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 12 2 -2 +BITMAP +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +08 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +70 +1C +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +1C +70 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +30 +58 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +48 +48 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 13 1 0 +BITMAP +E0 +30 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 13 1 0 +BITMAP +70 +C0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 13 1 0 +BITMAP +60 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 13 1 0 +BITMAP +90 +90 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 11 10 0 0 +BITMAP +3F80 +30C0 +3060 +3060 +FC60 +3060 +3060 +3060 +30C0 +3F80 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +1A +2C +00 +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +3800 +0E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +0700 +1C00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +0C00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +0D00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +2100 +2100 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 5 5 2 2 +BITMAP +C8 +70 +20 +70 +98 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 12 1 -1 +BITMAP +0040 +3F40 +6180 +C2C0 +C2C0 +C4C0 +C8C0 +D0C0 +D0C0 +6180 +BF00 +8000 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +70 +1C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +18 +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +64 +3C +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +0E +38 +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 657 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +C0 +C0 +F8 +CC +CC +CC +CC +F8 +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 724 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +7C +C6 +C6 +C4 +CC +C6 +C3 +C3 +C3 +C3 +CE +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +70 +1C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +0E +38 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +18 +2C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +34 +58 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +24 +24 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +18 +2C +18 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 913 0 +DWIDTH 14 0 +BBX 12 8 1 0 +BITMAP +7DE0 +0730 +0630 +7FF0 +C600 +C600 +C710 +79E0 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 10 1 -2 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +62 +3C +10 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +70 +1C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +0E +38 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +2C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +44 +44 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +E0 +30 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +70 +C0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +60 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +90 +90 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +10 +3E +0C +3E +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +1A +2C +00 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +70 +1C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +0E +38 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +2C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +34 +58 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +24 +24 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 7 1 1 +BITMAP +10 +10 +00 +FE +00 +10 +10 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 10 1 -1 +BITMAP +01 +3D +66 +CB +CB +D3 +D3 +66 +BC +80 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +70 +1C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +1C +70 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +1C +70 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +C0 +C0 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +44 +44 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +2100 +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +42 +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 12 1 -2 +BITMAP +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +0800 +0600 +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 10 1 -2 +BITMAP +7C +06 +06 +7E +C6 +C6 +CE +77 +10 +0C +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +0E +38 +00 +3C +66 +C0 +C0 +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +18 +2C +00 +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +58 +00 +3C +66 +C0 +C0 +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +18 +18 +00 +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +30 +00 +3C +66 +C0 +C0 +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +58 +30 +00 +3C +66 +C0 +C0 +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 13 2 0 +BITMAP +2C00 +1800 +0000 +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 926 0 +DWIDTH 14 0 +BBX 12 11 1 0 +BITMAP +0330 +0330 +0310 +3F20 +6300 +C300 +C300 +C300 +C300 +6700 +3B00 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 11 10 0 0 +BITMAP +3F80 +30C0 +3060 +3060 +FC60 +3060 +3060 +3060 +30C0 +3F80 +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +03 +1F +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 12 2 0 +BITMAP +F0 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +3C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +84 +78 +00 +7E +60 +60 +60 +7C +60 +60 +60 +60 +7E +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +42 +3C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +60 +60 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +18 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 12 2 -2 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +20 +18 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 10 1 -2 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +20 +18 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +B0 +60 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +2C +18 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +18 +2C +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +18 +2C +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +42 +3C +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +42 +3C +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +18 +18 +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +18 +18 +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 15 2 -5 +BITMAP +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 15 1 -2 +BITMAP +08 +10 +18 +18 +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +18 +2C +00 +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +60 +B0 +00 +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 10 2 0 +BITMAP +C3 +FF +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +C0 +F8 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 5 13 1 0 +BITMAP +68 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 11 0 0 +BITMAP +68 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 12 1 0 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 6 13 0 0 +BITMAP +84 +78 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 6 11 -1 0 +BITMAP +84 +78 +00 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 3 12 2 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +60 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 3 13 1 -2 +BITMAP +C0 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +80 +60 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 2 13 2 0 +BITMAP +C0 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 8 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 844 0 +DWIDTH 12 0 +BBX 8 12 2 -2 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +03 +0E +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 704 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +C6 +C6 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +06 +1C +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 501 0 +DWIDTH 6 0 +BBX 5 15 0 -2 +BITMAP +30 +58 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 361 0 +DWIDTH 5 0 +BBX 5 13 0 -2 +BITMAP +30 +58 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 15 2 -5 +BITMAP +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 16 1 -5 +BITMAP +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 8 1 0 +BITMAP +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +38 +E0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 14 0 0 +BITMAP +38 +E0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 15 2 -5 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 16 1 -5 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 854 0 +DWIDTH 13 0 +BBX 10 11 2 0 +BITMAP +00C0 +C0C0 +C040 +C080 +C000 +C000 +C000 +C000 +C000 +C000 +FC00 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 608 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +CC +CC +C4 +C8 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 932 0 +DWIDTH 19 0 +BBX 13 10 2 0 +BITMAP +C000 +C000 +C000 +C000 +C000 +C018 +C018 +C000 +C000 +FC00 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 686 0 +DWIDTH 14 0 +BBX 9 11 1 0 +BITMAP +C000 +C000 +C000 +C000 +C000 +C000 +C180 +C180 +C000 +C000 +C000 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 8 10 0 0 +BITMAP +30 +30 +30 +30 +3C +F0 +30 +30 +30 +3F +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 6 11 0 0 +BITMAP +30 +30 +30 +30 +3C +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +0E +38 +00 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 15 2 -5 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +00 +0C +0C +04 +08 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 13 1 -5 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +58 +30 +00 +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +2C +18 +00 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 945 0 +DWIDTH 14 0 +BBX 12 11 1 0 +BITMAP +C000 +C000 +4000 +8DE0 +0E70 +0C30 +0C30 +0C30 +0C30 +0C30 +0C30 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 12 2 -2 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8F +8F +87 +87 +03 +0E +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +03 +0E +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 12 1 0 +BITMAP +1E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +2100 +1E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +42 +3C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +1B00 +1200 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +36 +24 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1102 0 +DWIDTH 15 0 +BBX 13 10 1 0 +BITMAP +3DF8 +6380 +C180 +C180 +C1F0 +C180 +C180 +C180 +6380 +3DF8 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 990 0 +DWIDTH 15 0 +BBX 13 8 1 0 +BITMAP +3CF0 +6398 +C318 +C3F8 +C300 +C300 +6388 +3CF0 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 11 2 0 +BITMAP +38 +E0 +00 +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 15 2 -5 +BITMAP +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 13 2 -5 +BITMAP +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 11 2 0 +BITMAP +B0 +60 +00 +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +1C +70 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +1C +70 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +30 +58 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +60 +B0 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 12 1 -2 +BITMAP +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +08 +30 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 10 1 -2 +BITMAP +7C +C0 +C0 +F0 +3C +0C +0C +F8 +10 +60 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +2C +18 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +58 +30 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +08 +30 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +20 +C0 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +2C +18 +00 +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 679 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +0180 +6180 +6080 +F900 +6000 +6000 +6000 +6000 +6000 +6000 +3800 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +FF +18 +18 +18 +3E +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +60 +60 +F8 +60 +60 +F8 +60 +60 +60 +38 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +1A +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +1A +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 12 2 0 +BITMAP +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +42 +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +42 +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 14 2 0 +BITMAP +18 +2C +18 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +18 +2C +18 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +36 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +36 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 12 2 -2 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +10 +0C +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +10 +0C +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +0C00 +1600 +0000 +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +0C00 +1600 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +18 +2C +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +30 +58 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +24 +24 +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +0E +38 +00 +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +0E +38 +00 +FE +06 +0C +18 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +18 +18 +00 +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +18 +00 +FE +06 +0C +18 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +2C +18 +00 +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +2C +18 +00 +FE +06 +0C +18 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +7C +C6 +03 +03 +03 +03 +03 +03 +C6 +7C +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 11 10 0 0 +BITMAP +3F80 +30C0 +3060 +3060 +FC60 +3060 +3060 +3060 +30C0 +3F80 +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +FC +0C +0C +0C +0C +7C +0C +0C +0C +FC +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 11 2 -1 +BITMAP +1C +32 +30 +30 +FC +60 +60 +60 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 5 10 1 0 +BITMAP +60 +60 +60 +60 +F8 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 11 0 0 +BITMAP +60 +60 +60 +60 +60 +F8 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 12 0 -2 +BITMAP +3840 +3840 +2C40 +2C40 +2640 +2640 +3340 +3140 +31C0 +31C0 +3000 +E000 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +3F00 +6180 +C0C0 +C0C0 +FFC0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 11 10 1 0 +BITMAP +3F60 +61E0 +C0E0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 10 8 1 0 +BITMAP +3CC0 +66C0 +C340 +C380 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni01A7 +ENCODING 423 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +7C +C6 +06 +0E +3C +78 +E0 +C0 +C6 +7C +ENDCHAR +STARTCHAR uni01A8 +ENCODING 424 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 8 1 0 +BITMAP +F8 +0C +0C +3C +F0 +C0 +C0 +7C +ENDCHAR +STARTCHAR uni01AE +ENCODING 430 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +0E +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 10 2 0 +BITMAP +C3C0 +C3C0 +C340 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 10 8 1 0 +BITMAP +C3C0 +C3C0 +C340 +C380 +C300 +C300 +E700 +7B00 +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FE +06 +0C +1C +7C +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +FE +06 +0C +7C +30 +60 +C0 +FE +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +7E +C7 +03 +03 +FF +0C +18 +60 +FF +FF +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 10 2 0 +BITMAP +FC +FC +80 +80 +FC +0E +06 +06 +CC +78 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 12 1 -1 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 12 1 -1 +BITMAP +18 +18 +18 +18 +18 +FE +18 +FE +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1600 +0C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +2C +18 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 4 13 1 0 +BITMAP +B0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +B0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +1600 +0C00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +2C +18 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +2C +18 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 15 2 0 +BITMAP +3C +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +64 +3C +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 16 2 0 +BITMAP +0E +38 +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +64 +3C +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 16 2 0 +BITMAP +2C +18 +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +64 +3C +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +2C +18 +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 16 2 0 +BITMAP +70 +1C +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +64 +3C +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +70 +1C +00 +24 +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +78 +8C +06 +06 +FE +C6 +CC +78 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 773 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +3C +00 +24 +24 +00 +18 +18 +2C +2C +66 +46 +FE +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 13 1 0 +BITMAP +3C +00 +24 +24 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 15 1 0 +BITMAP +1E00 +0000 +0C00 +0C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 13 1 0 +BITMAP +3C +00 +18 +18 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 997 0 +DWIDTH 13 0 +BBX 11 12 1 0 +BITMAP +0F00 +0000 +1FE0 +1600 +2600 +2600 +67C0 +4600 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 913 0 +DWIDTH 14 0 +BBX 12 10 1 0 +BITMAP +0780 +0000 +7DE0 +0730 +0630 +7FF0 +C600 +C600 +C710 +79E0 +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 9 10 2 0 +BITMAP +3E00 +6300 +C000 +C000 +C000 +C300 +CF80 +C300 +6300 +3F00 +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +3F +63 +C3 +C3 +C3 +67 +3B +FF +C6 +7C +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +2C +18 +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +B0 +60 +00 +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 12 1 -2 +BITMAP +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0800 +0600 +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +66 +3C +10 +0C +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 14 1 -2 +BITMAP +1E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0800 +0600 +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +3C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +10 +0C +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 361 0 +DWIDTH 5 0 +BBX 5 13 0 -2 +BITMAP +58 +30 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +07 +1C +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR uni01F8 +ENCODING 504 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +E0 +38 +00 +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR uni01F9 +ENCODING 505 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +70 +1C +00 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +0700 +1C00 +0000 +1C00 +2600 +1C00 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +18 +2C +18 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 997 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +0380 +0E00 +0000 +1FE0 +1600 +2600 +2600 +67C0 +4600 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 913 0 +DWIDTH 14 0 +BBX 12 11 1 0 +BITMAP +01C0 +0700 +0000 +7DE0 +0730 +0630 +7FF0 +C600 +C600 +C710 +79E0 +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 -1 +BITMAP +0380 +0E00 +0000 +0040 +3F40 +6180 +C2C0 +C2C0 +C4C0 +C8C0 +D0C0 +D0C0 +6180 +BF00 +8000 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 -1 +BITMAP +07 +1C +00 +01 +3D +66 +CB +CB +D3 +D3 +66 +BC +80 +ENDCHAR +STARTCHAR uni0200 +ENCODING 512 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +3600 +1200 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni0201 +ENCODING 513 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +36 +12 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni0202 +ENCODING 514 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1E00 +2100 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni0203 +ENCODING 515 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +3C +42 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni0204 +ENCODING 516 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +D8 +48 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni0205 +ENCODING 517 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +6C +24 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni0206 +ENCODING 518 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +78 +84 +00 +7E +60 +60 +60 +7C +60 +60 +60 +60 +7E +ENDCHAR +STARTCHAR uni0207 +ENCODING 519 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +3C +42 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni0208 +ENCODING 520 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 5 13 0 0 +BITMAP +D8 +48 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni0209 +ENCODING 521 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 11 -1 0 +BITMAP +D8 +48 +00 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni020A +ENCODING 522 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 6 13 0 0 +BITMAP +78 +84 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni020B +ENCODING 523 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 6 11 -1 0 +BITMAP +78 +84 +00 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni020C +ENCODING 524 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +3600 +1200 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni020D +ENCODING 525 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +6C +24 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni020E +ENCODING 526 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +1E00 +2100 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni020F +ENCODING 527 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +3C +42 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0210 +ENCODING 528 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +6C +24 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni0211 +ENCODING 529 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +D8 +48 +00 +6C +6C +70 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni0212 +ENCODING 530 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +3C +42 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni0213 +ENCODING 531 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +78 +84 +00 +6C +6C +70 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni0214 +ENCODING 532 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +6C +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0215 +ENCODING 533 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +6C +24 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni0216 +ENCODING 534 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +3C +42 +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0217 +ENCODING 535 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +3C +42 +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 15 1 -5 +BITMAP +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 13 1 -5 +BITMAP +7C +C0 +C0 +F0 +3C +0C +0C +F8 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 15 1 -5 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 15 1 -5 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR uni021E +ENCODING 542 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +2C +18 +00 +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni021F +ENCODING 543 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +B0 +60 +00 +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni0226 +ENCODING 550 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +0C00 +0C00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni0227 +ENCODING 551 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 0 +BITMAP +18 +18 +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni0228 +ENCODING 552 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 12 2 -2 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +20 +C0 +ENDCHAR +STARTCHAR uni0229 +ENCODING 553 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 10 1 -2 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +10 +60 +ENDCHAR +STARTCHAR uni022A +ENCODING 554 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 0 +BITMAP +1E00 +0000 +2100 +2100 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni022B +ENCODING 555 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +24 +24 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni022C +ENCODING 556 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 0 +BITMAP +1E00 +0000 +0D00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni022D +ENCODING 557 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +34 +58 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni022E +ENCODING 558 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 0 +BITMAP +0C00 +0C00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni022F +ENCODING 559 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +18 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0230 +ENCODING 560 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 0 +BITMAP +1E00 +0000 +0C00 +0C00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni0231 +ENCODING 561 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +18 +18 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0232 +ENCODING 562 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +3C +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni0233 +ENCODING 563 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 12 1 -2 +BITMAP +3C +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR uni0250 +ENCODING 592 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 8 1 0 +BITMAP +EE +73 +63 +63 +7E +60 +60 +3E +ENDCHAR +STARTCHAR uni0254 +ENCODING 596 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +78 +CC +06 +06 +06 +06 +8C +78 +ENDCHAR +STARTCHAR uni0258 +ENCODING 600 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +78 +CC +C6 +FE +06 +06 +8C +78 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +78 +8C +06 +06 +FE +C6 +CC +78 +ENDCHAR +STARTCHAR uni025F +ENCODING 607 +SWIDTH 461 0 +DWIDTH 7 0 +BBX 7 11 0 -3 +BITMAP +18 +18 +18 +18 +18 +18 +18 +FE +18 +18 +F0 +ENDCHAR +STARTCHAR uni0265 +ENCODING 613 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +03 +03 +03 +ENDCHAR +STARTCHAR uni0275 +ENCODING 629 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +3C +66 +C3 +FF +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0279 +ENCODING 633 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 8 2 0 +BITMAP +18 +18 +18 +18 +18 +38 +D8 +D8 +ENDCHAR +STARTCHAR uni0287 +ENCODING 647 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +E0 +30 +30 +30 +30 +30 +30 +F8 +30 +30 +ENDCHAR +STARTCHAR uni0288 +ENCODING 648 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +60 +60 +38 +ENDCHAR +STARTCHAR uni0289 +ENCODING 649 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 8 1 0 +BITMAP +C3 +C3 +C3 +FF +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni028C +ENCODING 652 +SWIDTH 663 0 +DWIDTH 9 0 +BBX 7 8 1 0 +BITMAP +38 +38 +2C +4C +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni028D +ENCODING 653 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 8 1 0 +BITMAP +3180 +3180 +3BC0 +6AC0 +6EC0 +C460 +C460 +C060 +ENDCHAR +STARTCHAR uni028E +ENCODING 654 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +0E +0C +18 +38 +2C +6C +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni029E +ENCODING 670 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 11 1 -3 +BITMAP +E3 +63 +33 +1B +0F +1B +33 +63 +03 +03 +03 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +40 +80 +C0 +C0 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +80 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 2 3 9 +BITMAP +60 +B0 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 2 3 9 +BITMAP +B0 +60 +ENDCHAR +STARTCHAR uni02C8 +ENCODING 712 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +80 +80 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 1 3 9 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CA +ENCODING 714 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 9 +BITMAP +38 +E0 +ENDCHAR +STARTCHAR uni02CB +ENCODING 715 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 2 9 +BITMAP +E0 +38 +ENDCHAR +STARTCHAR uni02CD +ENCODING 717 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 1 3 -2 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CE +ENCODING 718 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 2 -3 +BITMAP +E0 +38 +ENDCHAR +STARTCHAR uni02CF +ENCODING 719 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 -3 +BITMAP +38 +E0 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 6 2 2 9 +BITMAP +84 +78 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 2 2 4 9 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 4 3 3 8 +BITMAP +60 +B0 +60 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 3 2 5 -2 +BITMAP +80 +60 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 9 +BITMAP +68 +B0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 9 +BITMAP +D8 +90 +ENDCHAR +STARTCHAR uni02EE +ENCODING 750 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 7 +BITMAP +D8 +D8 +48 +90 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 2 3 9 +BITMAP +38 +E0 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 5 5 3 9 +BITMAP +38 +E0 +00 +90 +90 +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 343 0 +DWIDTH 10 0 +BBX 2 2 4 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 699 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +FB +C0 +C0 +ENDCHAR +STARTCHAR uni1E00 +ENCODING 7680 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 14 1 -4 +BITMAP +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +0000 +0C00 +1600 +0C00 +ENDCHAR +STARTCHAR uni1E01 +ENCODING 7681 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 12 1 -4 +BITMAP +7C +06 +06 +7E +C6 +C6 +CE +77 +00 +18 +2C +18 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 669 0 +DWIDTH 10 0 +BBX 7 13 2 0 +BITMAP +30 +30 +00 +FC +C6 +C6 +CC +F0 +CC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +60 +60 +00 +C0 +C0 +C0 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +ENDCHAR +STARTCHAR uni1E04 +ENCODING 7684 +SWIDTH 669 0 +DWIDTH 10 0 +BBX 7 13 2 -3 +BITMAP +FC +C6 +C6 +CC +F0 +CC +C6 +C6 +C6 +FC +00 +30 +30 +ENDCHAR +STARTCHAR uni1E05 +ENCODING 7685 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +C0 +C0 +C0 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +00 +18 +18 +ENDCHAR +STARTCHAR uni1E06 +ENCODING 7686 +SWIDTH 669 0 +DWIDTH 10 0 +BBX 7 12 2 -2 +BITMAP +FC +C6 +C6 +CC +F0 +CC +C6 +C6 +C6 +FC +00 +78 +ENDCHAR +STARTCHAR uni1E07 +ENCODING 7687 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +C0 +C0 +C0 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +00 +3C +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 8 15 2 -2 +BITMAP +0E +38 +00 +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +08 +30 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 545 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +0E +38 +00 +3C +66 +C0 +C0 +C0 +C0 +62 +3C +10 +60 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 13 2 0 +BITMAP +1800 +1800 +0000 +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +06 +06 +00 +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +ENDCHAR +STARTCHAR uni1E0C +ENCODING 7692 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 13 2 -3 +BITMAP +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1E0D +ENCODING 7693 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +00 +18 +18 +ENDCHAR +STARTCHAR uni1E0E +ENCODING 7694 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 12 2 -2 +BITMAP +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E0F +ENCODING 7695 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +00 +3C +ENDCHAR +STARTCHAR uni1E10 +ENCODING 7696 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 12 2 -2 +BITMAP +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +0800 +3000 +ENDCHAR +STARTCHAR uni1E11 +ENCODING 7697 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +08 +30 +ENDCHAR +STARTCHAR uni1E12 +ENCODING 7698 +SWIDTH 819 0 +DWIDTH 12 0 +BBX 9 13 2 -3 +BITMAP +FE00 +C300 +C180 +C180 +C180 +C180 +C180 +C180 +C300 +FE00 +0000 +1800 +2C00 +ENDCHAR +STARTCHAR uni1E13 +ENCODING 7699 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +03 +03 +03 +3F +63 +C3 +C3 +C3 +C3 +67 +3B +00 +18 +2C +ENDCHAR +STARTCHAR uni1E14 +ENCODING 7700 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +E0 +38 +00 +78 +00 +7E +60 +60 +60 +7C +60 +60 +60 +60 +7E +ENDCHAR +STARTCHAR uni1E15 +ENCODING 7701 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +70 +1C +00 +3C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1E16 +ENCODING 7702 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 15 2 0 +BITMAP +1C +70 +00 +F0 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1E17 +ENCODING 7703 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +0E +38 +00 +3C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1E18 +ENCODING 7704 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 -3 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +00 +60 +B0 +ENDCHAR +STARTCHAR uni1E19 +ENCODING 7705 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 -3 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +00 +30 +58 +ENDCHAR +STARTCHAR uni1E1A +ENCODING 7706 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 -3 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E1B +ENCODING 7707 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 -3 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +00 +34 +58 +ENDCHAR +STARTCHAR uni1E1C +ENCODING 7708 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 15 1 -2 +BITMAP +84 +78 +00 +7E +60 +60 +60 +7C +60 +60 +60 +60 +7E +10 +60 +ENDCHAR +STARTCHAR uni1E1D +ENCODING 7709 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +42 +3C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +10 +60 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 602 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +60 +60 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 461 0 +DWIDTH 7 0 +BBX 7 14 0 0 +BITMAP +18 +18 +00 +1E +30 +30 +FE +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni1E20 +ENCODING 7712 +SWIDTH 759 0 +DWIDTH 11 0 +BBX 8 12 2 0 +BITMAP +3C +00 +3E +63 +C0 +C0 +C0 +C3 +C3 +C3 +63 +3F +ENDCHAR +STARTCHAR uni1E21 +ENCODING 7713 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +3C +00 +3F +63 +C3 +C3 +C3 +67 +3B +03 +C6 +7C +ENDCHAR +STARTCHAR uni1E22 +ENCODING 7714 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +18 +18 +00 +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1E23 +ENCODING 7715 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +60 +60 +00 +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1E24 +ENCODING 7716 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E25 +ENCODING 7717 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E26 +ENCODING 7718 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +24 +24 +00 +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1E27 +ENCODING 7719 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +90 +90 +00 +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1E28 +ENCODING 7720 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 12 2 -2 +BITMAP +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +08 +30 +ENDCHAR +STARTCHAR uni1E29 +ENCODING 7721 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +08 +30 +ENDCHAR +STARTCHAR uni1E2A +ENCODING 7722 +SWIDTH 813 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +FF +C3 +C3 +C3 +C3 +C3 +00 +42 +3C +ENDCHAR +STARTCHAR uni1E2B +ENCODING 7723 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +42 +3C +ENDCHAR +STARTCHAR uni1E2C +ENCODING 7724 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 5 13 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2D +ENCODING 7725 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 14 -1 -3 +BITMAP +30 +30 +00 +30 +30 +30 +30 +30 +30 +30 +30 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2E +ENCODING 7726 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 5 16 1 0 +BITMAP +38 +E0 +00 +90 +90 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni1E2F +ENCODING 7727 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 5 14 0 0 +BITMAP +38 +E0 +00 +90 +90 +00 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni1E30 +ENCODING 7728 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +0E +38 +00 +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni1E31 +ENCODING 7729 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +38 +E0 +00 +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +ENDCHAR +STARTCHAR uni1E32 +ENCODING 7730 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 13 2 -3 +BITMAP +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E33 +ENCODING 7731 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 14 1 -3 +BITMAP +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E34 +ENCODING 7732 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 12 2 -2 +BITMAP +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +00 +3C +ENDCHAR +STARTCHAR uni1E35 +ENCODING 7733 +SWIDTH 681 0 +DWIDTH 9 0 +BBX 8 13 1 -2 +BITMAP +C0 +C0 +C0 +C6 +CC +D8 +F0 +D8 +CC +C6 +C7 +00 +3C +ENDCHAR +STARTCHAR uni1E36 +ENCODING 7734 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 13 2 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +ENDCHAR +STARTCHAR uni1E37 +ENCODING 7735 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 14 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni1E38 +ENCODING 7736 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 15 2 -3 +BITMAP +F0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +ENDCHAR +STARTCHAR uni1E39 +ENCODING 7737 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 16 0 -3 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +60 +60 +ENDCHAR +STARTCHAR uni1E3A +ENCODING 7738 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 12 2 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +F0 +ENDCHAR +STARTCHAR uni1E3B +ENCODING 7739 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 13 0 -2 +BITMAP +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +F0 +ENDCHAR +STARTCHAR uni1E3C +ENCODING 7740 +SWIDTH 620 0 +DWIDTH 9 0 +BBX 6 13 2 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +B0 +ENDCHAR +STARTCHAR uni1E3D +ENCODING 7741 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 4 14 0 -3 +BITMAP +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +60 +B0 +ENDCHAR +STARTCHAR uni1E3E +ENCODING 7742 +SWIDTH 940 0 +DWIDTH 15 0 +BBX 11 13 2 0 +BITMAP +0380 +0E00 +0000 +E0E0 +E0E0 +B160 +B160 +B160 +9A60 +9A60 +8C60 +8C60 +8060 +ENDCHAR +STARTCHAR uni1E3F +ENCODING 7743 +SWIDTH 1006 0 +DWIDTH 14 0 +BBX 12 11 1 0 +BITMAP +0380 +0E00 +0000 +DDE0 +EF70 +C630 +C630 +C630 +C630 +C630 +C630 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 940 0 +DWIDTH 15 0 +BBX 11 13 2 0 +BITMAP +0600 +0600 +0000 +E0E0 +E0E0 +B160 +B160 +B160 +9A60 +9A60 +8C60 +8C60 +8060 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 1006 0 +DWIDTH 14 0 +BBX 12 11 1 0 +BITMAP +0600 +0600 +0000 +DDE0 +EF70 +C630 +C630 +C630 +C630 +C630 +C630 +ENDCHAR +STARTCHAR uni1E42 +ENCODING 7746 +SWIDTH 940 0 +DWIDTH 15 0 +BBX 11 13 2 -3 +BITMAP +E0E0 +E0E0 +B160 +B160 +B160 +9A60 +9A60 +8C60 +8C60 +8060 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E43 +ENCODING 7747 +SWIDTH 1006 0 +DWIDTH 14 0 +BBX 12 11 1 -3 +BITMAP +DDE0 +EF70 +C630 +C630 +C630 +C630 +C630 +C630 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E44 +ENCODING 7748 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 0 +BITMAP +30 +30 +00 +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +ENDCHAR +STARTCHAR uni1E45 +ENCODING 7749 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +18 +00 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1E46 +ENCODING 7750 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +00 +0C +0C +ENDCHAR +STARTCHAR uni1E47 +ENCODING 7751 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E48 +ENCODING 7752 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 12 2 -2 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +00 +1E +ENDCHAR +STARTCHAR uni1E49 +ENCODING 7753 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 10 1 -2 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +3C +ENDCHAR +STARTCHAR uni1E4A +ENCODING 7754 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +E1 +E1 +B1 +B1 +99 +99 +8D +8D +87 +87 +00 +0C +16 +ENDCHAR +STARTCHAR uni1E4B +ENCODING 7755 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +18 +2C +ENDCHAR +STARTCHAR uni1E4C +ENCODING 7756 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +0700 +1C00 +0000 +0D00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1E4D +ENCODING 7757 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +34 +58 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E4E +ENCODING 7758 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +1200 +1200 +0000 +0D00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1E4F +ENCODING 7759 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +24 +24 +00 +34 +58 +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E50 +ENCODING 7760 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 0 +BITMAP +3800 +0E00 +0000 +1E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1E51 +ENCODING 7761 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +70 +1C +00 +3C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E52 +ENCODING 7762 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 15 1 0 +BITMAP +0700 +1C00 +0000 +1E00 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1E53 +ENCODING 7763 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +0E +38 +00 +3C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E54 +ENCODING 7764 +SWIDTH 657 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +1C +70 +00 +F8 +CC +CC +CC +CC +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E55 +ENCODING 7765 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +0E +38 +00 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 657 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +30 +30 +00 +F8 +CC +CC +CC +CC +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 696 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +18 +18 +00 +DC +E6 +C3 +C3 +C3 +C3 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR uni1E58 +ENCODING 7768 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 0 +BITMAP +18 +18 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni1E59 +ENCODING 7769 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 11 2 0 +BITMAP +60 +60 +00 +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E5A +ENCODING 7770 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 13 2 -3 +BITMAP +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E5B +ENCODING 7771 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 11 2 -3 +BITMAP +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +00 +60 +60 +ENDCHAR +STARTCHAR uni1E5C +ENCODING 7772 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 15 2 -3 +BITMAP +78 +00 +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E5D +ENCODING 7773 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 13 2 -3 +BITMAP +F0 +00 +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +00 +60 +60 +ENDCHAR +STARTCHAR uni1E5E +ENCODING 7774 +SWIDTH 734 0 +DWIDTH 11 0 +BBX 8 12 2 -2 +BITMAP +FC +C6 +C6 +C4 +CC +F8 +CC +C6 +C3 +C3 +00 +3C +ENDCHAR +STARTCHAR uni1E5F +ENCODING 7775 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 5 10 2 -2 +BITMAP +D8 +D8 +E0 +C0 +C0 +C0 +C0 +C0 +00 +F0 +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +30 +30 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +30 +30 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR uni1E62 +ENCODING 7778 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 13 1 -3 +BITMAP +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +00 +18 +18 +ENDCHAR +STARTCHAR uni1E63 +ENCODING 7779 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 11 1 -3 +BITMAP +7C +C0 +C0 +F0 +3C +0C +0C +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E64 +ENCODING 7780 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 16 1 0 +BITMAP +18 +18 +00 +1C +70 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR uni1E65 +ENCODING 7781 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +30 +30 +00 +1C +70 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR uni1E66 +ENCODING 7782 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 16 1 0 +BITMAP +18 +18 +00 +2C +18 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR uni1E67 +ENCODING 7783 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +30 +30 +00 +58 +30 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +ENDCHAR +STARTCHAR uni1E68 +ENCODING 7784 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 7 16 1 -3 +BITMAP +30 +30 +00 +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +00 +18 +18 +ENDCHAR +STARTCHAR uni1E69 +ENCODING 7785 +SWIDTH 622 0 +DWIDTH 8 0 +BBX 6 14 1 -3 +BITMAP +30 +30 +00 +7C +C0 +C0 +F0 +3C +0C +0C +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +18 +18 +00 +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +60 +60 +00 +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +ENDCHAR +STARTCHAR uni1E6C +ENCODING 7788 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 13 1 -3 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +00 +18 +18 +ENDCHAR +STARTCHAR uni1E6D +ENCODING 7789 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E6E +ENCODING 7790 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +00 +3C +ENDCHAR +STARTCHAR uni1E6F +ENCODING 7791 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +00 +78 +ENDCHAR +STARTCHAR uni1E70 +ENCODING 7792 +SWIDTH 735 0 +DWIDTH 10 0 +BBX 8 13 1 -3 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +00 +18 +2C +ENDCHAR +STARTCHAR uni1E71 +ENCODING 7793 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +00 +30 +58 +ENDCHAR +STARTCHAR uni1E72 +ENCODING 7794 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +24 +24 +ENDCHAR +STARTCHAR uni1E73 +ENCODING 7795 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +00 +24 +24 +ENDCHAR +STARTCHAR uni1E74 +ENCODING 7796 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +34 +58 +ENDCHAR +STARTCHAR uni1E75 +ENCODING 7797 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +00 +34 +58 +ENDCHAR +STARTCHAR uni1E76 +ENCODING 7798 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +2C +ENDCHAR +STARTCHAR uni1E77 +ENCODING 7799 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +00 +18 +2C +ENDCHAR +STARTCHAR uni1E78 +ENCODING 7800 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 16 2 0 +BITMAP +0E +38 +00 +1A +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E79 +ENCODING 7801 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +07 +1C +00 +1A +2C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni1E7A +ENCODING 7802 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 15 2 0 +BITMAP +24 +24 +00 +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E7B +ENCODING 7803 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +24 +24 +00 +3C +00 +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +ENDCHAR +STARTCHAR uni1E7C +ENCODING 7804 +SWIDTH 735 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1A00 +2C00 +0000 +C180 +C180 +C180 +6100 +6300 +6300 +3200 +3600 +1C00 +1C00 +ENDCHAR +STARTCHAR uni1E7D +ENCODING 7805 +SWIDTH 663 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +34 +58 +00 +C6 +C6 +C6 +C6 +64 +68 +38 +38 +ENDCHAR +STARTCHAR uni1E7E +ENCODING 7806 +SWIDTH 735 0 +DWIDTH 11 0 +BBX 9 13 1 -3 +BITMAP +C180 +C180 +C180 +6100 +6300 +6300 +3200 +3600 +1C00 +1C00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E7F +ENCODING 7807 +SWIDTH 663 0 +DWIDTH 9 0 +BBX 7 11 1 -3 +BITMAP +C6 +C6 +C6 +C6 +64 +68 +38 +38 +00 +30 +30 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +3800 +0E00 +0000 +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +3800 +0E00 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +0380 +0E00 +0000 +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +0380 +0E00 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +0900 +0900 +0000 +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +0900 +0900 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 0 +BITMAP +0600 +0600 +0000 +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +0600 +0600 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR uni1E88 +ENCODING 7816 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 13 1 -3 +BITMAP +C060 +C060 +C660 +C660 +6640 +6B40 +6B40 +7BC0 +3180 +3180 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E89 +ENCODING 7817 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 11 1 -3 +BITMAP +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E8A +ENCODING 7818 +SWIDTH 699 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +18 +18 +00 +C6 +C6 +6C +6C +38 +38 +6C +6C +C6 +C6 +ENDCHAR +STARTCHAR uni1E8B +ENCODING 7819 +SWIDTH 568 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +30 +00 +C6 +C6 +64 +38 +38 +4C +C6 +C6 +ENDCHAR +STARTCHAR uni1E8C +ENCODING 7820 +SWIDTH 699 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +24 +24 +00 +C6 +C6 +6C +6C +38 +38 +6C +6C +C6 +C6 +ENDCHAR +STARTCHAR uni1E8D +ENCODING 7821 +SWIDTH 568 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +48 +48 +00 +C6 +C6 +64 +38 +38 +4C +C6 +C6 +ENDCHAR +STARTCHAR uni1E8E +ENCODING 7822 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +18 +18 +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1E8F +ENCODING 7823 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +18 +18 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR uni1E90 +ENCODING 7824 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +18 +2C +00 +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +ENDCHAR +STARTCHAR uni1E91 +ENCODING 7825 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +2C +00 +FE +06 +0C +18 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR uni1E92 +ENCODING 7826 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 13 1 -3 +BITMAP +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +00 +30 +30 +ENDCHAR +STARTCHAR uni1E93 +ENCODING 7827 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 11 1 -3 +BITMAP +FE +06 +0C +18 +30 +60 +C0 +FE +00 +30 +30 +ENDCHAR +STARTCHAR uni1E94 +ENCODING 7828 +SWIDTH 675 0 +DWIDTH 9 0 +BBX 7 12 1 -2 +BITMAP +FE +06 +0C +1C +18 +30 +70 +60 +C0 +FE +00 +78 +ENDCHAR +STARTCHAR uni1E95 +ENCODING 7829 +SWIDTH 608 0 +DWIDTH 9 0 +BBX 7 10 1 -2 +BITMAP +FE +06 +0C +18 +30 +60 +C0 +FE +00 +78 +ENDCHAR +STARTCHAR uni1E96 +ENCODING 7830 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 13 1 -2 +BITMAP +C0 +C0 +C0 +DE +E7 +C3 +C3 +C3 +C3 +C3 +C3 +00 +3C +ENDCHAR +STARTCHAR uni1E97 +ENCODING 7831 +SWIDTH 436 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +90 +90 +00 +60 +60 +F8 +60 +60 +60 +60 +60 +60 +38 +ENDCHAR +STARTCHAR uni1E98 +ENCODING 7832 +SWIDTH 885 0 +DWIDTH 13 0 +BBX 11 12 1 0 +BITMAP +0600 +0B00 +0600 +0000 +C060 +C460 +C460 +6EC0 +6AC0 +7B80 +3180 +3180 +ENDCHAR +STARTCHAR uni1E99 +ENCODING 7833 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 14 1 -2 +BITMAP +18 +2C +18 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR uni1EA0 +ENCODING 7840 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 -3 +BITMAP +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EA1 +ENCODING 7841 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 11 1 -3 +BITMAP +7C +06 +06 +7E +C6 +C6 +CE +77 +00 +18 +18 +ENDCHAR +STARTCHAR uni1EA4 +ENCODING 7844 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +0700 +1C00 +0000 +1C00 +2600 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EA5 +ENCODING 7845 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +18 +2C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EA6 +ENCODING 7846 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +7000 +1C00 +0000 +1C00 +2600 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EA7 +ENCODING 7847 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +70 +1C +00 +18 +2C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EAA +ENCODING 7850 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +1A00 +2C00 +0000 +1C00 +2600 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EAB +ENCODING 7851 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +1A +2C +00 +18 +2C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EAC +ENCODING 7852 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 -3 +BITMAP +0C00 +1600 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EAD +ENCODING 7853 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 -3 +BITMAP +18 +2C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +00 +18 +18 +ENDCHAR +STARTCHAR uni1EAE +ENCODING 7854 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +0700 +1C00 +0000 +2100 +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EAF +ENCODING 7855 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +42 +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EB0 +ENCODING 7856 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +3800 +0E00 +0000 +2100 +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EB1 +ENCODING 7857 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +70 +1C +00 +42 +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EB4 +ENCODING 7860 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 0 +BITMAP +1A00 +2C00 +0000 +2100 +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni1EB5 +ENCODING 7861 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 0 +BITMAP +1A +2C +00 +42 +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +ENDCHAR +STARTCHAR uni1EB6 +ENCODING 7862 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 16 1 -3 +BITMAP +2100 +1E00 +0000 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EB7 +ENCODING 7863 +SWIDTH 623 0 +DWIDTH 9 0 +BBX 8 14 1 -3 +BITMAP +42 +3C +00 +7C +06 +06 +7E +C6 +C6 +CE +77 +00 +18 +18 +ENDCHAR +STARTCHAR uni1EB8 +ENCODING 7864 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 -3 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +ENDCHAR +STARTCHAR uni1EB9 +ENCODING 7865 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 -3 +BITMAP +3C +66 +C6 +FE +C0 +C0 +62 +3C +00 +30 +30 +ENDCHAR +STARTCHAR uni1EBC +ENCODING 7868 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 13 2 0 +BITMAP +68 +B0 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EBD +ENCODING 7869 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +34 +58 +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1EBE +ENCODING 7870 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 16 2 0 +BITMAP +1C +70 +00 +30 +58 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EBF +ENCODING 7871 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +0E +38 +00 +18 +2C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1EC0 +ENCODING 7872 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 16 2 0 +BITMAP +E0 +38 +00 +30 +58 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EC1 +ENCODING 7873 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +70 +1C +00 +18 +2C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1EC4 +ENCODING 7876 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 16 2 0 +BITMAP +34 +58 +00 +30 +58 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EC5 +ENCODING 7877 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +1A +2C +00 +18 +2C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +ENDCHAR +STARTCHAR uni1EC6 +ENCODING 7878 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 16 2 -3 +BITMAP +60 +B0 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +ENDCHAR +STARTCHAR uni1EC7 +ENCODING 7879 +SWIDTH 614 0 +DWIDTH 9 0 +BBX 7 14 1 -3 +BITMAP +18 +2C +00 +3C +66 +C6 +FE +C0 +C0 +62 +3C +00 +30 +30 +ENDCHAR +STARTCHAR uni1ECA +ENCODING 7882 +SWIDTH 361 0 +DWIDTH 6 0 +BBX 2 13 2 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni1ECB +ENCODING 7883 +SWIDTH 361 0 +DWIDTH 4 0 +BBX 2 14 1 -3 +BITMAP +C0 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni1ECC +ENCODING 7884 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 13 1 -3 +BITMAP +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1ECD +ENCODING 7885 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +18 +ENDCHAR +STARTCHAR uni1ED0 +ENCODING 7888 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +0700 +1C00 +0000 +0C00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1ED1 +ENCODING 7889 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +0E +38 +00 +18 +2C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED2 +ENCODING 7890 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +3800 +0E00 +0000 +0C00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1ED3 +ENCODING 7891 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +70 +1C +00 +18 +2C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED6 +ENCODING 7894 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 0 +BITMAP +0D00 +1600 +0000 +0C00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1ED7 +ENCODING 7895 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +1A +2C +00 +18 +2C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED8 +ENCODING 7896 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 10 16 1 -3 +BITMAP +0C00 +1600 +0000 +3F00 +6180 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1ED9 +ENCODING 7897 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +18 +2C +00 +3C +66 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +18 +ENDCHAR +STARTCHAR uni1EDA +ENCODING 7898 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +0380 +0E00 +0000 +3F60 +61E0 +C0E0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1EDB +ENCODING 7899 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0380 +0E00 +0000 +3CC0 +66C0 +C340 +C380 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EDC +ENCODING 7900 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +1C00 +0700 +0000 +3F60 +61E0 +C0E0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1EDD +ENCODING 7901 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +3800 +0E00 +0000 +3CC0 +66C0 +C340 +C380 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EE0 +ENCODING 7904 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 11 13 1 0 +BITMAP +0680 +0B00 +0000 +3F60 +61E0 +C0E0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +ENDCHAR +STARTCHAR uni1EE1 +ENCODING 7905 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0D00 +1600 +0000 +3CC0 +66C0 +C340 +C380 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EE2 +ENCODING 7906 +SWIDTH 855 0 +DWIDTH 12 0 +BBX 11 13 1 -3 +BITMAP +3F60 +61E0 +C0E0 +C0C0 +C0C0 +C0C0 +C0C0 +C0C0 +6180 +3F00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EE3 +ENCODING 7907 +SWIDTH 675 0 +DWIDTH 10 0 +BBX 10 11 1 -3 +BITMAP +3CC0 +66C0 +C340 +C380 +C300 +C300 +6600 +3C00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1EE4 +ENCODING 7908 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 13 2 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +18 +ENDCHAR +STARTCHAR uni1EE5 +ENCODING 7909 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 8 11 1 -3 +BITMAP +C3 +C3 +C3 +C3 +C3 +C3 +E7 +7B +00 +18 +18 +ENDCHAR +STARTCHAR uni1EE8 +ENCODING 7912 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 13 2 0 +BITMAP +0380 +0E00 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EE9 +ENCODING 7913 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0380 +0E00 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +E700 +7B00 +ENDCHAR +STARTCHAR uni1EEA +ENCODING 7914 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 13 2 0 +BITMAP +3800 +0E00 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EEB +ENCODING 7915 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +3800 +0E00 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +E700 +7B00 +ENDCHAR +STARTCHAR uni1EEE +ENCODING 7918 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 13 2 0 +BITMAP +0D00 +1600 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EEF +ENCODING 7919 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0D00 +1600 +0000 +C3C0 +C3C0 +C340 +C380 +C300 +C300 +E700 +7B00 +ENDCHAR +STARTCHAR uni1EF0 +ENCODING 7920 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 10 13 2 -3 +BITMAP +C3C0 +C3C0 +C340 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1EF1 +ENCODING 7921 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 10 11 1 -3 +BITMAP +C3C0 +C3C0 +C340 +C380 +C300 +C300 +E700 +7B00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +70 +1C +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +E0 +38 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR uni1EF4 +ENCODING 7924 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 -3 +BITMAP +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +00 +18 +18 +ENDCHAR +STARTCHAR uni1EF5 +ENCODING 7925 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -5 +BITMAP +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +00 +30 +30 +ENDCHAR +STARTCHAR uni1EF8 +ENCODING 7928 +SWIDTH 738 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +1A +2C +00 +C3 +C3 +62 +66 +34 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1EF9 +ENCODING 7929 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +34 +58 +00 +C6 +C6 +C6 +C6 +6C +68 +38 +30 +60 +E0 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 1000 0 +DWIDTH 15 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 1000 0 +DWIDTH 15 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 250 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 167 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 200 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 100 0 +DWIDTH 1 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200B +ENCODING 8203 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 289 0 +DWIDTH 5 0 +BBX 3 1 1 4 +BITMAP +E0 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 289 0 +DWIDTH 5 0 +BBX 3 1 1 4 +BITMAP +E0 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 1 1 4 +BITMAP +F8 +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 1 1 4 +BITMAP +F8 +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 15 0 +BBX 13 1 1 4 +BITMAP +FFF8 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 15 0 +BBX 13 1 1 4 +BITMAP +FFF8 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +40 +80 +C0 +C0 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 265 0 +DWIDTH 4 0 +BBX 2 4 1 7 +BITMAP +C0 +C0 +80 +40 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 7 +BITMAP +48 +90 +D8 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 7 +BITMAP +D8 +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 -2 +BITMAP +D8 +D8 +48 +90 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 530 0 +DWIDTH 7 0 +BBX 5 4 1 7 +BITMAP +D8 +D8 +90 +48 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 6 11 2 -1 +BITMAP +30 +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 693 0 +DWIDTH 10 0 +BBX 6 11 2 -1 +BITMAP +30 +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 4 4 3 2 +BITMAP +F0 +F0 +F0 +F0 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 10 0 +BBX 6 2 2 0 +BITMAP +CC +CC +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1313 0 +DWIDTH 18 0 +BBX 16 10 1 0 +BITMAP +7000 +D980 +DB00 +7200 +0400 +0800 +138E +36DB +66DB +038E +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 361 0 +DWIDTH 5 0 +BBX 4 5 0 2 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 361 0 +DWIDTH 5 0 +BBX 4 5 1 2 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 93 0 +DWIDTH 4 0 +BBX 6 10 -1 0 +BITMAP +0C +0C +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 4 6 1 -2 +BITMAP +30 +F0 +30 +30 +30 +30 +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 5 6 1 -2 +BITMAP +F0 +18 +18 +60 +C0 +F8 +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 536 0 +DWIDTH 7 0 +BBX 5 6 1 -2 +BITMAP +F0 +18 +70 +18 +18 +F0 +ENDCHAR +STARTCHAR uni20A5 +ENCODING 8357 +SWIDTH 1006 0 +DWIDTH 14 0 +BBX 12 12 1 -2 +BITMAP +00C0 +0180 +DDE0 +EF70 +C730 +C630 +C630 +CE30 +CE30 +DE30 +1800 +3000 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 783 0 +DWIDTH 12 0 +BBX 8 10 2 0 +BITMAP +E1 +E1 +B1 +FF +99 +FF +8D +8D +87 +87 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 940 0 +DWIDTH 13 0 +BBX 11 10 1 0 +BITMAP +C060 +C060 +C660 +FFE0 +6640 +7FC0 +6B40 +7BC0 +3180 +3180 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 726 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +1F00 +3180 +6000 +FE00 +6000 +FE00 +6000 +6000 +3180 +1F00 +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +C3 +C6 +CC +D8 +FF +D8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 955 0 +DWIDTH 15 0 +BBX 14 10 0 0 +BITMAP +60F8 +918C +6300 +0300 +0300 +0300 +0300 +0300 +018C +00F8 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 831 0 +DWIDTH 13 0 +BBX 12 10 0 0 +BITMAP +63F0 +9300 +6300 +0300 +03E0 +0300 +0300 +0300 +0300 +0300 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 901 0 +DWIDTH 13 0 +BBX 10 5 1 5 +BITMAP +FEC0 +2540 +2540 +2540 +2440 +ENDCHAR +STARTCHAR uni212A +ENCODING 8490 +SWIDTH 753 0 +DWIDTH 11 0 +BBX 8 10 2 0 +BITMAP +C3 +C6 +CC +D8 +F0 +D8 +CC +C6 +C3 +C3 +ENDCHAR +STARTCHAR uni212B +ENCODING 8491 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 13 1 0 +BITMAP +1C00 +2600 +1C00 +1C00 +1C00 +2600 +2600 +6300 +4300 +FF00 +C180 +C180 +C180 +ENDCHAR +STARTCHAR uni2132 +ENCODING 8498 +SWIDTH 602 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +0C +0C +0C +0C +0C +7C +0C +0C +0C +FC +ENDCHAR +STARTCHAR universal +ENCODING 8704 +SWIDTH 773 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +C180 +C180 +C180 +FF00 +4300 +6300 +2600 +2600 +1C00 +1C00 +ENDCHAR +STARTCHAR existential +ENCODING 8707 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 6 10 2 0 +BITMAP +FC +0C +0C +0C +7C +0C +0C +0C +0C +FC +ENDCHAR +STARTCHAR uni2204 +ENCODING 8708 +SWIDTH 645 0 +DWIDTH 9 0 +BBX 8 12 1 -1 +BITMAP +03 +7E +06 +0E +0E +3E +1E +36 +36 +66 +7E +C0 +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 1 1 4 +BITMAP +FE +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 93 0 +DWIDTH 4 0 +BBX 6 10 -1 0 +BITMAP +0C +0C +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 343 0 +DWIDTH 10 0 +BBX 2 2 4 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR uni2236 +ENCODING 8758 +SWIDTH 343 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 6 1 3 +BITMAP +18 +2C +00 +FE +00 +FE +ENDCHAR +STARTCHAR uni225A +ENCODING 8794 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 6 1 3 +BITMAP +2C +18 +00 +FE +00 +FE +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 1 -1 +BITMAP +03 +06 +06 +0C +0C +FE +18 +FE +30 +60 +60 +C0 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 7 5 0 2 +BITMAP +FE +00 +FE +00 +FE +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 0 -1 +BITMAP +03 +06 +06 +0C +FE +18 +FE +30 +FE +60 +60 +C0 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 6 9 2 -1 +BITMAP +0C +38 +60 +C0 +60 +38 +0C +00 +FC +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 6 9 2 -1 +BITMAP +C0 +70 +18 +0C +18 +70 +C0 +00 +FC +ENDCHAR +STARTCHAR uni226E +ENCODING 8814 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 1 -1 +BITMAP +03 +06 +06 +0E +1C +38 +78 +30 +3C +66 +60 +C0 +ENDCHAR +STARTCHAR uni226F +ENCODING 8815 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 1 -1 +BITMAP +03 +06 +06 +6C +3C +1C +1E +3C +38 +60 +60 +C0 +ENDCHAR +STARTCHAR uni2270 +ENCODING 8816 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +03 +06 +06 +1C +3C +78 +38 +3C +36 +60 +7E +C0 +ENDCHAR +STARTCHAR uni2271 +ENCODING 8817 +SWIDTH 687 0 +DWIDTH 10 0 +BBX 8 12 1 -2 +BITMAP +03 +06 +66 +3C +0C +1E +1C +38 +70 +60 +7E +C0 +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 711 0 +DWIDTH 11 0 +BBX 9 11 0 0 +BITMAP +1D80 +3180 +3000 +FF80 +3180 +3180 +3180 +3180 +3180 +3180 +3180 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 711 0 +DWIDTH 10 0 +BBX 9 11 0 0 +BITMAP +1F80 +3180 +3180 +FD80 +3180 +3180 +3180 +3180 +3180 +3180 +3180 +ENDCHAR +ENDFONT diff --git a/bertos/fonts/ncenB18.bdf b/bertos/fonts/ncenB18.bdf new file mode 100644 index 00000000..d8eae064 --- /dev/null +++ b/bertos/fonts/ncenB18.bdf @@ -0,0 +1,16273 @@ +STARTFONT 2.1 +FONT -Adobe-New Century Schoolbook-Bold-R-Normal--18-180-75-75-P-113-ISO10646-1 +SIZE 18 75 75 +FONTBOUNDINGBOX 24 31 -3 -8 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn , 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "New Century Schoolbook" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 18 +POINT_SIZE 180 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 113 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +CAP_HEIGHT 14 +X_HEIGHT 9 +FONT_ASCENT 16 +FONT_DESCENT 4 +FACE_NAME "New Century Schoolbook Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "New Century Schoolbook is a trademark of Linotype-Hell AG and/or its subsidiaries." +_DEC_DEVICE_FONTNAMES "PS=NewCenturySchlbk-Bold" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +FULL_NAME "New Century Schoolbook Bold" +ENDPROPERTIES +CHARS 756 +STARTCHAR char0 +ENCODING 0 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 13 13 1 0 +BITMAP +AAA8 +0000 +8008 +0000 +8008 +0000 +8008 +0000 +8008 +0000 +8008 +0000 +AAA8 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 287 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 296 0 +DWIDTH 6 0 +BBX 4 14 1 0 +BITMAP +60 +F0 +F0 +F0 +F0 +F0 +60 +60 +60 +00 +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 5 5 1 9 +BITMAP +D8 +D8 +D8 +D8 +D8 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 574 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +0D80 +0D80 +0D80 +7FE0 +7FE0 +1B00 +1B00 +FFC0 +FFC0 +3600 +3600 +3600 +3600 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 18 1 -2 +BITMAP +0800 +0800 +3E00 +6B80 +C980 +C980 +E800 +F800 +7E00 +3F00 +0F80 +0B80 +C980 +C980 +EB80 +7F00 +0800 +0800 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +38C0 +6740 +C4C0 +C480 +C580 +C900 +7300 +0238 +0664 +04C4 +0CC4 +08C4 +18C8 +1070 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 852 0 +DWIDTH 17 0 +BBX 16 14 0 0 +BITMAP +0780 +0CC0 +1840 +18C0 +1D80 +1F00 +0E3E +3F18 +7790 +E3E0 +E1E0 +E0F1 +F1FE +3F1C +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 2 5 1 9 +BITMAP +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 16 1 -2 +BITMAP +18 +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +18 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 16 0 -2 +BITMAP +C0 +60 +30 +30 +18 +18 +18 +18 +18 +18 +18 +18 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 7 7 0 7 +BITMAP +38 +92 +D6 +38 +D6 +92 +38 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0C00 +0C00 +0C00 +0C00 +FFC0 +FFC0 +0C00 +0C00 +0C00 +0C00 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 7 0 -3 +BITMAP +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 4 +BITMAP +F8 +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 4 0 0 +BITMAP +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 7 0 +BBX 6 14 0 0 +BITMAP +0C +0C +0C +18 +18 +18 +30 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1C00 +7700 +6300 +E380 +E380 +E380 +E380 +E380 +E380 +E380 +E380 +6300 +7700 +1C00 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 7 14 2 0 +BITMAP +18 +38 +F8 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +FE +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1E00 +6700 +E380 +E380 +6380 +0380 +0700 +0700 +0E00 +1800 +3000 +6080 +FF80 +FF80 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1E00 +6700 +E380 +E380 +6380 +0300 +1C00 +0300 +0380 +6380 +E380 +E380 +6700 +3E00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +0700 +0F00 +0F00 +1700 +1700 +2700 +2700 +4700 +4700 +8700 +FF80 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +7F80 +7F00 +4000 +4000 +4000 +7E00 +4700 +0380 +0380 +6380 +E380 +E380 +6700 +3E00 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1F00 +7380 +6380 +E300 +E000 +EE00 +F700 +E380 +E380 +E380 +E380 +6380 +7300 +1C00 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +FF80 +FF80 +FF80 +8300 +0600 +0600 +0C00 +0C00 +1C00 +1C00 +3800 +3800 +3800 +3800 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1C00 +6300 +C180 +C180 +E180 +FB00 +7E00 +3F00 +4F80 +C380 +C180 +C180 +E300 +3C00 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1C00 +6700 +E300 +E380 +E380 +E380 +E380 +7780 +3B80 +0380 +6380 +E300 +E700 +7C00 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 278 0 +DWIDTH 6 0 +BBX 4 9 1 0 +BITMAP +60 +F0 +F0 +60 +00 +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 278 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +60 +F0 +F0 +60 +00 +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +00C0 +03C0 +0F00 +3C00 +F000 +F000 +3C00 +0F00 +03C0 +00C0 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 6 1 2 +BITMAP +FF80 +FF80 +0000 +0000 +FF80 +FF80 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +C000 +F000 +3C00 +0F00 +03C0 +03C0 +0F00 +3C00 +F000 +C000 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +1F00 +6780 +E380 +E380 +6380 +0300 +0600 +0C00 +1800 +0000 +1800 +3C00 +3C00 +1800 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 747 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +07F0 +1C1C +300C +63E6 +6666 +CC66 +CC66 +D8CC +D8CC +D9D8 +CEF0 +6008 +7870 +1FC0 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 14 0 0 +BITMAP +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 14 1 0 +BITMAP +FFC0 +71E0 +70E0 +70E0 +70E0 +71C0 +7F80 +70E0 +70F0 +7070 +7070 +7070 +70E0 +FF80 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 14 1 0 +BITMAP +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7320 +7F00 +7300 +7100 +7100 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 14 1 0 +BITMAP +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 14 2 0 +BITMAP +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +07E0 +01C0 +01C0 +01C0 +01C0 +01C0 +01C0 +01C0 +61C0 +F1C0 +F1C0 +C3C0 +4780 +3E00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 14 1 0 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 14 1 0 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 17 14 1 0 +BITMAP +7C0780 +3C0F00 +3E0F00 +2E1F00 +2F1700 +2F1700 +273700 +27A700 +23E700 +23C700 +23C700 +21C700 +718700 +F88F80 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 1 0 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 12 14 1 0 +BITMAP +FFE0 +70F0 +7070 +7070 +7070 +70F0 +71E0 +7F80 +7000 +7000 +7000 +7000 +7000 +FC00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 -4 +BITMAP +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F79E +79DC +70FC +3CF8 +0FE0 +0060 +0074 +007C +0038 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 14 0 0 +BITMAP +F87C +7038 +7830 +3820 +3820 +3C60 +1C40 +1E40 +0EC0 +0E80 +0780 +0780 +0300 +0300 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 14 0 0 +BITMAP +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 722 0 +DWIDTH 17 0 +BBX 16 14 0 0 +BITMAP +7E3F +3C1C +1E18 +0E30 +0F60 +07C0 +03C0 +03E0 +06F0 +0C70 +1878 +303C +703E +F87F +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 14 1 0 +BITMAP +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 16 1 -2 +BITMAP +F0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +F0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 606 0 +DWIDTH 9 0 +BBX 8 14 0 0 +BITMAP +C0 +C0 +60 +60 +30 +30 +18 +18 +0C +0C +06 +06 +03 +03 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 16 0 -2 +BITMAP +F0 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +F0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 606 0 +DWIDTH 9 0 +BBX 8 8 0 6 +BITMAP +18 +18 +3C +3C +66 +66 +C3 +C3 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 10 2 0 -3 +BITMAP +FFC0 +FFC0 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 10 +BITMAP +C0 +E0 +70 +18 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 12 14 -1 0 +BITMAP +F000 +7000 +7000 +7000 +7000 +7780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +6F80 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 8 14 0 0 +BITMAP +1E +37 +77 +70 +70 +FC +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 15 0 -4 +BITMAP +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 14 0 0 +BITMAP +70 +70 +70 +00 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 7 18 -3 -4 +BITMAP +0E +0E +0E +00 +00 +1E +0E +0E +0E +0E +0E +0E +0E +0E +0E +EE +EC +78 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 5 14 0 0 +BITMAP +F0 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 963 0 +DWIDTH 20 0 +BBX 19 9 0 0 +BITMAP +F7DF80 +79F3C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +F9F3E0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 9 0 0 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 12 13 -1 -4 +BITMAP +E780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +7780 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 12 13 0 -4 +BITMAP +1E60 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EE0 +00E0 +00E0 +00E0 +01F0 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 13 0 0 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 9 0 0 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 10 9 -1 0 +BITMAP +F9C0 +7080 +7080 +3900 +3900 +1E00 +1E00 +0C00 +0C00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 9 -1 0 +BITMAP +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +FCE0 +78C0 +3D00 +1E00 +0E00 +0F00 +1780 +63C0 +E7E0 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 -4 +BITMAP +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 9 0 0 +BITMAP +FF +CF +8E +1C +38 +39 +71 +F3 +FF +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 16 0 -2 +BITMAP +18 +20 +60 +60 +60 +60 +60 +C0 +60 +60 +60 +60 +60 +60 +20 +18 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 2 14 4 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 16 0 -2 +BITMAP +C0 +20 +30 +30 +30 +30 +30 +18 +30 +30 +30 +30 +30 +30 +20 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 606 0 +DWIDTH 12 0 +BBX 10 3 1 4 +BITMAP +39C0 +7F80 +E700 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 287 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 296 0 +DWIDTH 7 0 +BBX 4 14 1 -4 +BITMAP +60 +F0 +F0 +60 +00 +60 +60 +60 +F0 +F0 +F0 +F0 +F0 +60 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 13 1 -2 +BITMAP +0080 +0080 +1F00 +7380 +E380 +E400 +E400 +E800 +E880 +7180 +1E00 +2000 +2000 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +1F00 +3180 +7380 +7380 +7000 +7000 +3800 +FF80 +1C00 +1C00 +1840 +70C0 +9FC0 +EF80 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 606 0 +DWIDTH 10 0 +BBX 9 9 0 2 +BITMAP +DD80 +FF80 +6300 +C180 +C180 +C180 +6300 +FF80 +DD80 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 14 1 0 +BITMAP +F878 +7030 +7820 +3860 +1C40 +1CC0 +0F80 +1FC0 +0700 +1FC0 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 2 14 4 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +00 +00 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 500 0 +DWIDTH 8 0 +BBX 7 16 0 -2 +BITMAP +78 +CC +8C +C0 +70 +7C +9E +86 +C2 +F2 +7C +1C +04 +C4 +CC +78 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 10 0 +BBX 6 2 2 10 +BITMAP +CC +CC +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 747 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +0780 +1860 +2010 +47C8 +4CC8 +9844 +9804 +9804 +9804 +4C48 +4788 +2010 +1860 +0780 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 367 0 +DWIDTH 8 0 +BBX 7 8 0 6 +BITMAP +78 +CC +3C +CC +DC +6E +00 +FE +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 8 5 0 3 +BITMAP +11 +66 +CC +66 +11 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 606 0 +DWIDTH 10 0 +BBX 9 6 0 2 +BITMAP +FF80 +FF80 +0180 +0180 +0180 +0180 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 4 +BITMAP +F8 +F8 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 747 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +0780 +1860 +2010 +5F88 +4CC8 +8CC4 +8F84 +8D84 +8CC4 +5EE8 +4008 +2010 +1860 +0780 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 6 2 1 10 +BITMAP +FC +FC +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 7 0 +BBX 6 6 0 8 +BITMAP +78 +CC +84 +84 +CC +78 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 11 0 0 +BITMAP +0C00 +0C00 +0C00 +FFC0 +FFC0 +0C00 +0C00 +0C00 +0000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 6 +BITMAP +78 +CC +CC +18 +30 +60 +C4 +FC +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 6 +BITMAP +78 +CC +0C +38 +0C +CC +CC +78 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 10 +BITMAP +18 +38 +70 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 -4 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +7EF0 +6000 +7000 +7000 +2000 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 747 0 +DWIDTH 14 0 +BBX 13 14 0 0 +BITMAP +3FF8 +7E70 +FE70 +FE70 +FE70 +FE70 +7E70 +3E70 +0E70 +0E70 +0E70 +0E70 +0E70 +1FF8 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 4 0 3 +BITMAP +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 4 1 -4 +BITMAP +40 +70 +30 +E0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 6 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +FC +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 367 0 +DWIDTH 7 0 +BBX 6 8 0 6 +BITMAP +78 +CC +CC +CC +CC +78 +00 +FC +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 8 5 0 3 +BITMAP +88 +66 +33 +66 +88 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 861 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +3060 +F060 +30C0 +30C0 +3180 +3180 +3318 +FF38 +0678 +06D8 +0D98 +0DFC +1818 +183C +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 861 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +3060 +F060 +30C0 +30C0 +3180 +3180 +3378 +FFCC +06CC +0618 +0C30 +0C60 +18C4 +18FC +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 861 0 +DWIDTH 15 0 +BBX 14 14 0 0 +BITMAP +7860 +CC60 +0CC0 +38C0 +0D80 +CD80 +CF18 +7B38 +0678 +06D8 +0D98 +0DFC +1818 +183C +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 14 0 -4 +BITMAP +0C00 +1E00 +1E00 +0C00 +0000 +0C00 +1800 +3000 +6000 +E300 +E380 +E380 +F300 +7C00 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 19 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 19 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0380 +07C0 +0C60 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0620 +0FC0 +1180 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 17 0 0 +BITMAP +0CC0 +0CC0 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0300 +0480 +0480 +0300 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 981 0 +DWIDTH 21 0 +BBX 20 14 0 0 +BITMAP +03FFF0 +00B870 +01B830 +013890 +033890 +063980 +043F80 +0C3980 +1FF880 +103890 +203810 +203830 +603870 +F1FFF0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 18 1 -4 +BITMAP +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +0400 +0700 +0300 +0E00 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 0 +BITMAP +0E00 +1F00 +3180 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +1980 +1980 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 19 2 0 +BITMAP +C0 +E0 +70 +18 +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 19 2 0 +BITMAP +0C +1C +38 +60 +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 7 18 1 0 +BITMAP +38 +7C +C6 +00 +7C +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 17 2 0 +BITMAP +CC +CC +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +7FE0 +3878 +383C +381C +381E +380E +FE0E +380E +380E +381E +381C +383C +3878 +7FE0 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 1 0 +BITMAP +0310 +07E0 +08C0 +0000 +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 0 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 0 +BITMAP +0380 +07C0 +0C60 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 0 +BITMAP +0310 +07E0 +08C0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 0 0 +BITMAP +0660 +0660 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +C0C0 +E1C0 +7380 +3F00 +1E00 +1E00 +3F00 +7380 +E1C0 +C0C0 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +0FC8 +38F0 +7078 +7078 +E0BC +E11C +E21C +E21C +E41C +E83C +7038 +7078 +78F0 +8FC0 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 0 +BITMAP +0380 +07C0 +0C60 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0CC0 +0CC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 12 14 1 0 +BITMAP +F800 +7000 +7000 +7FC0 +70F0 +7070 +7070 +7070 +7070 +70E0 +7F80 +7000 +7000 +F800 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +1E00 +3380 +71C0 +71C0 +71C0 +7180 +7700 +71C0 +70E0 +70E0 +70E0 +70E0 +71C0 +F700 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +0600 +0E00 +1C00 +3000 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +1C00 +3E00 +6300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +1880 +3F00 +4600 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +3300 +3300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +0C00 +1200 +1200 +0C00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 870 0 +DWIDTH 17 0 +BBX 16 9 0 0 +BITMAP +3F78 +63CE +E387 +0787 +3BFF +E380 +E381 +E7C3 +78FC +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 13 0 -4 +BITMAP +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +1000 +1C00 +0C00 +3800 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +0600 +0E00 +1C00 +3000 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +0E00 +1F00 +3180 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +3300 +3300 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 14 0 0 +BITMAP +C0 +E0 +70 +18 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 14 0 0 +BITMAP +18 +38 +70 +C0 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 7 13 -1 0 +BITMAP +38 +7C +C6 +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 12 0 0 +BITMAP +CC +CC +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +6000 +1B00 +1C00 +6600 +0300 +1F80 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 0 +BITMAP +0C40 +1F80 +2300 +0000 +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +0E00 +1F00 +3180 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +1880 +3F00 +4600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 0 +BITMAP +1980 +1980 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0C00 +0C00 +0000 +0000 +FFC0 +FFC0 +0000 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 11 0 -1 +BITMAP +0100 +1F00 +7380 +E3C0 +E5C0 +E5C0 +E9C0 +E9C0 +7380 +3E00 +2000 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 0 +BITMAP +0700 +0F80 +18C0 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 0 +BITMAP +1980 +1980 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +0180 +0380 +0700 +0C00 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 12 18 -1 -4 +BITMAP +F000 +7000 +7000 +7000 +7000 +7780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +7780 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 -4 +BITMAP +1980 +1980 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 17 0 0 +BITMAP +0FC0 +0FC0 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +3F00 +3F00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0840 +0CC0 +0780 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +2100 +3300 +1E00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 -4 +BITMAP +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +0180 +0300 +0340 +0180 +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 13 0 -4 +BITMAP +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +0C00 +1800 +1A00 +0C00 +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 19 1 0 +BITMAP +0200 +0700 +0F80 +18C0 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +0800 +1C00 +3E00 +6300 +0000 +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 17 1 0 +BITMAP +0600 +0600 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 12 0 0 +BITMAP +0C00 +0C00 +0000 +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +6300 +3E00 +1C00 +0800 +0000 +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 875 0 +DWIDTH 17 0 +BBX 16 14 0 0 +BITMAP +01E6 +00EF +00EF +00E7 +00E2 +1EE4 +71E8 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +7FE0 +3878 +383C +381C +381E +380E +FE0E +380E +380E +381E +381C +383C +3878 +7FE0 +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +01E0 +00E0 +00E0 +01F0 +01F0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +1F80 +1F80 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +3F00 +3F00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 0 +BITMAP +1080 +1980 +0F00 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +2100 +3300 +1E00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +0C00 +0C00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 -4 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0600 +0C00 +0D00 +0600 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 -4 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0C00 +1800 +1A00 +0C00 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +0200 +0700 +0F80 +18C0 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 20 0 -4 +BITMAP +0200 +0700 +0F80 +18C0 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 18 1 0 +BITMAP +1080 +1980 +0F00 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 19 0 -4 +BITMAP +1080 +1980 +0F00 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 17 1 0 +BITMAP +0600 +0600 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 18 0 -4 +BITMAP +0600 +0600 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 22 1 -8 +BITMAP +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +0000 +0300 +0780 +0780 +0380 +0100 +0200 +0400 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 23 0 -4 +BITMAP +0100 +0200 +0400 +0E00 +0F00 +0F00 +0600 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0100 +0380 +07C0 +0C60 +0000 +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 19 0 0 +BITMAP +1000 +3800 +7C00 +C600 +0000 +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FCFC +7038 +7038 +7038 +FFFC +FFFC +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +F000 +7000 +7000 +7C00 +7C00 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 8 18 1 0 +BITMAP +31 +7E +8C +00 +7C +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 8 13 -1 0 +BITMAP +31 +7E +8C +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 17 2 0 +BITMAP +FC +FC +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 12 -1 0 +BITMAP +FC +FC +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 18 2 0 +BITMAP +84 +CC +78 +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 13 -1 0 +BITMAP +84 +CC +78 +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 18 2 -4 +BITMAP +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +30 +60 +68 +30 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 18 0 -4 +BITMAP +70 +70 +70 +00 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +30 +60 +68 +30 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 17 2 0 +BITMAP +30 +30 +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 1070 0 +DWIDTH 21 0 +BBX 18 14 2 0 +BITMAP +F80FC0 +700380 +700380 +700380 +700380 +700380 +700380 +700380 +70C380 +71E380 +71E380 +718780 +708F00 +F87C00 +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 704 0 +DWIDTH 12 0 +BBX 10 18 0 -4 +BITMAP +71C0 +71C0 +71C0 +0000 +0000 +F3C0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +F9C0 +01C0 +1DC0 +1D80 +0F00 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 11 19 0 0 +BITMAP +0100 +0380 +07C0 +0C60 +0000 +07E0 +01C0 +01C0 +01C0 +01C0 +01C0 +01C0 +01C0 +61C0 +F1C0 +F1C0 +C3C0 +4780 +3E00 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 8 18 -3 -4 +BITMAP +08 +1C +3E +63 +00 +1E +0E +0E +0E +0E +0E +0E +0E +0E +0E +EE +EC +78 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 22 1 -8 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +0000 +0180 +03C0 +03C0 +01C0 +0080 +0100 +0200 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 22 0 -8 +BITMAP +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +0000 +0600 +0F00 +0F00 +0700 +0200 +0400 +0800 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 9 0 0 +BITMAP +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 19 1 0 +BITMAP +0600 +0E00 +1C00 +3000 +0000 +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 5 19 0 0 +BITMAP +18 +38 +70 +C0 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 22 1 -8 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +0000 +0C00 +1E00 +1E00 +0E00 +0400 +0800 +1000 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 5 22 0 -8 +BITMAP +F0 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +00 +30 +78 +78 +38 +10 +20 +40 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 927 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FC18 +703C +703C +701C +7008 +7010 +7020 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 575 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +F180 +73C0 +73C0 +71C0 +7080 +7100 +7200 +7000 +7000 +7000 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 964 0 +DWIDTH 16 0 +BBX 14 14 1 0 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7018 +703C +703C +7038 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 612 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +F000 +7000 +7000 +7000 +7000 +7000 +7000 +7180 +73C0 +73C0 +7180 +7000 +7000 +F800 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 12 14 -1 0 +BITMAP +7E00 +3C00 +3C00 +3C00 +3D00 +3E00 +3C00 +3C00 +7C00 +BC10 +3C10 +3C30 +3C70 +7FF0 +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 6 14 0 0 +BITMAP +F0 +70 +70 +70 +74 +78 +70 +F0 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 22 1 -8 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +0000 +0300 +0780 +0780 +0380 +0100 +0200 +0400 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 -8 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +0600 +0F00 +0F00 +0700 +0200 +0400 +0800 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 914 0 +DWIDTH 18 0 +BBX 17 14 0 0 +BITMAP +600000 +F00000 +F00000 +700000 +200000 +47BE00 +83CF00 +038700 +038700 +038700 +038700 +038700 +038700 +07CF80 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 1 -4 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F838 +0038 +03B8 +03B0 +01E0 +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 11 13 0 -4 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F8E0 +00E0 +0EE0 +0EC0 +0780 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 0 0 +BITMAP +07E0 +07E0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 0 +BITMAP +1F80 +1F80 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 0 +BITMAP +0420 +0660 +03C0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +1080 +1980 +0F00 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 0 0 +BITMAP +0660 +0660 +0CC0 +0880 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +1980 +1980 +3300 +2200 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 22 0 +BBX 21 14 0 0 +BITMAP +0FFFF8 +3C7C38 +783C18 +783C48 +F03C48 +F03CC0 +F03FC0 +F03CC0 +F03C40 +F03C48 +783C08 +783C18 +3C7C38 +0FFFF8 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 907 0 +DWIDTH 19 0 +BBX 18 9 0 0 +BITMAP +1F1E00 +71F380 +E0E1C0 +E0E1C0 +E0FFC0 +E0E000 +E0E040 +71F0C0 +1F1F00 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 14 0 0 +BITMAP +06 +0E +1C +30 +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 22 1 -8 +BITMAP +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +0000 +0300 +0780 +0780 +0380 +0100 +0200 +0400 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 17 0 -8 +BITMAP +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +00 +30 +78 +78 +38 +10 +20 +40 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 14 0 0 +BITMAP +63 +3E +1C +08 +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 19 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +0600 +0E00 +1C00 +3000 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 19 0 0 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +0800 +1C00 +3E00 +6300 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 13 0 -4 +BITMAP +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +1000 +1C00 +0C00 +3800 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 10 14 0 0 +BITMAP +6180 +3300 +1E00 +0C00 +0000 +3F80 +7180 +7880 +7E00 +3F00 +0F80 +83C0 +C780 +BF00 +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 14 0 0 +BITMAP +C300 +6600 +3C00 +1800 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 18 1 -4 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 17 0 -4 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +20 +38 +18 +70 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 646 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +0060 +10F0 +30F0 +3070 +7020 +FC40 +7080 +7000 +7000 +7000 +7000 +7200 +7200 +3C00 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +1F00 +1F00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 13 0 0 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +7C +7C +72 +72 +3C +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 0 +BITMAP +0620 +0FC0 +1180 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 0 +BITMAP +0C40 +1F80 +2300 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0FC0 +0FC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 0 +BITMAP +1F80 +1F80 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 0 +BITMAP +0840 +0CC0 +0780 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 0 +BITMAP +1080 +1980 +0F00 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0300 +0480 +0480 +0300 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +0600 +0900 +0900 +0600 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0CC0 +0CC0 +1980 +1100 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +0CC0 +0CC0 +1980 +1100 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 -4 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +0600 +0C00 +0D00 +0600 +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 -4 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +0300 +0600 +0680 +0300 +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 19 0 0 +BITMAP +008000 +01C000 +03E000 +063000 +000000 +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 14 -1 0 +BITMAP +0100 +0380 +07C0 +0C60 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +0200 +0700 +0F80 +18C0 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +0800 +1C00 +3E00 +6300 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 14 0 0 +BITMAP +0CC0 +0CC0 +0000 +0000 +0000 +FCF8 +7870 +3CE0 +1FC0 +0F80 +0780 +0780 +0780 +0FC0 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 14 0 0 +BITMAP +06 +0E +1C +30 +00 +FF +CF +8E +1C +38 +39 +71 +F3 +FF +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 12 0 0 +BITMAP +18 +18 +00 +FF +CF +8E +1C +38 +39 +71 +F3 +FF +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +30C0 +1980 +0F00 +0600 +0000 +FFF0 +C1E0 +83C0 +0780 +0F10 +1E10 +3C30 +7870 +FFF0 +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 14 0 0 +BITMAP +C3 +66 +3C +18 +00 +FF +C7 +8F +1E +3C +79 +F1 +E3 +FF +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 14 1 0 +BITMAP +1F00 +63C0 +41E0 +80E0 +80F0 +0070 +0070 +0070 +8070 +80F0 +C0E0 +C1E0 +E3C0 +9F00 +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +7FE0 +3878 +383C +381C +381E +380E +FE0E +380E +380E +381E +381C +383C +3878 +7FE0 +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +E1C0 +C1C0 +81C0 +91C0 +11C0 +19C0 +1FC0 +19C0 +91C0 +91C0 +C1C0 +E1C0 +FFE0 +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 574 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +01C0 +0360 +0760 +0700 +0700 +1FC0 +0E00 +0E00 +0E00 +0E00 +0E00 +1C00 +1C00 +1C00 +1C00 +DC00 +D800 +7000 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 14 2 0 +BITMAP +F8 +70 +70 +70 +70 +70 +F8 +F8 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 5 14 0 0 +BITMAP +F0 +70 +70 +70 +70 +70 +F8 +F8 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 18 -1 -4 +BITMAP +3E0F80 +1F0700 +0F0200 +0F8200 +0BC200 +09E200 +08E200 +087200 +087A00 +083A00 +0E1E00 +0E1E00 +0E0E00 +0E0600 +0E0000 +EE0000 +EC0000 +780000 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 0 0 +BITMAP +0FE0 +3C78 +783C +701C +F01E +E00E +FFFE +FFFE +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 18 14 0 0 +BITMAP +0FE180 +3C7BC0 +783FC0 +701DC0 +F01E80 +E00F00 +E00E00 +E00E00 +E00E00 +F01E00 +701C00 +783C00 +3C7800 +0FE000 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 14 9 0 0 +BITMAP +1F18 +71FC +E0FC +E0FC +E0E8 +E0F0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni01A7 +ENCODING 423 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +5F80 +70C0 +6060 +4060 +00E0 +0FE0 +7FC0 +FFC0 +FE00 +E020 +C020 +C060 +60E0 +3FA0 +ENDCHAR +STARTCHAR uni01A8 +ENCODING 424 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +5E00 +6300 +4380 +1F80 +7F00 +F800 +E080 +6180 +3E80 +ENDCHAR +STARTCHAR uni01AE +ENCODING 430 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 18 1 -4 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0EE0 +06E0 +03C0 +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 14 1 0 +BITMAP +F87F00 +703F80 +701780 +701380 +701100 +701200 +701400 +701000 +701000 +701000 +701000 +701000 +382000 +1FC000 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 15 9 0 0 +BITMAP +F1EC +70FE +70FE +70EE +70E4 +70E8 +70F0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +1F00 +1F00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 9 0 0 +BITMAP +FF +CF +8E +3E +3E +39 +71 +F3 +FF +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +1E00 +6700 +E380 +E380 +6380 +0380 +FF80 +FF80 +0E00 +1800 +3000 +6080 +FF80 +FF80 +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 9 14 1 0 +BITMAP +7F80 +7F00 +4000 +4000 +4000 +7E00 +4700 +0380 +0380 +6380 +E380 +E380 +6700 +3E00 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 2 14 4 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 14 1 -2 +BITMAP +0C00 +0C00 +0C00 +0C00 +FF80 +FF80 +0C00 +0C00 +FF80 +FF80 +0C00 +0C00 +0C00 +0C00 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 296 0 +DWIDTH 6 0 +BBX 4 14 1 0 +BITMAP +60 +F0 +F0 +F0 +F0 +F0 +60 +60 +60 +00 +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 19 0 0 +BITMAP +0C60 +07C0 +0380 +0100 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +6300 +3E00 +1C00 +0800 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 7 19 1 0 +BITMAP +C6 +7C +38 +10 +00 +7C +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 7 14 -1 0 +BITMAP +C6 +7C +38 +10 +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 0 0 +BITMAP +0C60 +07C0 +0380 +0100 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +0FC0 +0FC0 +0000 +0CC0 +0CC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 15 0 0 +BITMAP +1F80 +1F80 +0000 +1980 +1980 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 22 1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0CC0 +0CC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +1980 +1980 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 22 1 0 +BITMAP +0C60 +07C0 +0380 +0100 +0000 +0CC0 +0CC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +3180 +1F00 +0E00 +0400 +0000 +1980 +1980 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 22 1 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +0CC0 +0CC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +1980 +1980 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +3E00 +C380 +81C0 +01C0 +FFC0 +E1C0 +E1C0 +7380 +1E00 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 20 0 0 +BITMAP +0FC0 +0FC0 +0000 +0CC0 +0CC0 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 15 0 0 +BITMAP +3F00 +3F00 +0000 +3300 +3300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 20 0 0 +BITMAP +0FC0 +0FC0 +0000 +0300 +0300 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 15 0 0 +BITMAP +3F00 +3F00 +0000 +0C00 +0C00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 981 0 +DWIDTH 21 0 +BBX 20 17 0 0 +BITMAP +007E00 +007E00 +000000 +03FFF0 +00B870 +01B830 +013890 +033890 +063980 +043F80 +0C3980 +1FF880 +103890 +203810 +203830 +603870 +F1FFF0 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 870 0 +DWIDTH 17 0 +BBX 16 12 0 0 +BITMAP +07E0 +07E0 +0000 +3F78 +63CE +E387 +0787 +3BFF +E380 +E381 +E7C3 +78FC +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 14 14 1 0 +BITMAP +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +787C +3CFC +0F90 +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 15 0 -4 +BITMAP +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +FFE0 +FFE0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 20 0 -4 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 19 1 0 +BITMAP +18C0 +0F80 +0700 +0200 +0000 +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 19 0 0 +BITMAP +C600 +7C00 +3800 +1000 +0000 +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 -4 +BITMAP +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +0180 +0300 +0340 +0180 +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 -4 +BITMAP +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +0600 +0C00 +0D00 +0600 +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 21 0 -4 +BITMAP +07E0 +07E0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +0180 +0300 +0340 +0180 +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 -4 +BITMAP +1F80 +1F80 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +0600 +0C00 +0D00 +0600 +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 8 18 -3 -4 +BITMAP +63 +3E +1C +08 +00 +1E +0E +0E +0E +0E +0E +0E +0E +0E +0E +EE +EC +78 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 20 0 -4 +BITMAP +0180 +0380 +0700 +0C00 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR uni01F8 +ENCODING 504 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 1 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR uni01F9 +ENCODING 505 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 23 0 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0300 +0480 +0480 +0300 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 19 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +0C00 +1200 +1200 +0C00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 981 0 +DWIDTH 21 0 +BBX 20 19 0 0 +BITMAP +000600 +000E00 +001C00 +003000 +000000 +03FFF0 +00B870 +01B830 +013890 +033890 +063980 +043F80 +0C3980 +1FF880 +103890 +203810 +203830 +603870 +F1FFF0 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 870 0 +DWIDTH 17 0 +BBX 16 14 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +3F78 +63CE +E387 +0787 +3BFF +E380 +E381 +E7C3 +78FC +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0FC8 +38F0 +7078 +7078 +E0BC +E11C +E21C +E21C +E41C +E83C +7038 +7078 +78F0 +8FC0 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 16 0 -1 +BITMAP +0300 +0700 +0E00 +1800 +0000 +0100 +1F00 +7380 +E3C0 +E5C0 +E5C0 +E9C0 +E9C0 +7380 +3E00 +2000 +ENDCHAR +STARTCHAR uni0200 +ENCODING 512 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 19 0 0 +BITMAP +1980 +1980 +0CC0 +0440 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni0201 +ENCODING 513 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +6600 +6600 +3300 +1100 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni0202 +ENCODING 514 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0780 +0CC0 +0840 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni0203 +ENCODING 515 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +1E00 +3300 +2100 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni0204 +ENCODING 516 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +3300 +3300 +1980 +0880 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni0205 +ENCODING 517 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 0 +BITMAP +6600 +6600 +3300 +1100 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni0206 +ENCODING 518 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 0 +BITMAP +0F00 +1980 +1080 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni0207 +ENCODING 519 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +1E00 +3300 +2100 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni0208 +ENCODING 520 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 7 19 1 0 +BITMAP +CC +CC +66 +22 +00 +7C +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR uni0209 +ENCODING 521 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 7 14 -2 0 +BITMAP +CC +CC +66 +22 +00 +3C +1C +1C +1C +1C +1C +1C +1C +3E +ENDCHAR +STARTCHAR uni020A +ENCODING 522 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 18 2 0 +BITMAP +78 +CC +84 +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni020B +ENCODING 523 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 13 -1 0 +BITMAP +78 +CC +84 +00 +78 +38 +38 +38 +38 +38 +38 +38 +7C +ENDCHAR +STARTCHAR uni020C +ENCODING 524 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 0 0 +BITMAP +0CC0 +0CC0 +0660 +0220 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni020D +ENCODING 525 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +3300 +3300 +1980 +0880 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni020E +ENCODING 526 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 18 0 0 +BITMAP +03C0 +0660 +0420 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni020F +ENCODING 527 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +0F00 +1980 +1080 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni0210 +ENCODING 528 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +1980 +1980 +0CC0 +0440 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR uni0211 +ENCODING 529 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 14 0 0 +BITMAP +CC +CC +66 +22 +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni0212 +ENCODING 530 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 18 1 0 +BITMAP +0F00 +1980 +1080 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR uni0213 +ENCODING 531 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 13 0 0 +BITMAP +3C +66 +42 +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni0214 +ENCODING 532 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +1980 +1980 +0CC0 +0440 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni0215 +ENCODING 533 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 0 +BITMAP +3300 +3300 +1980 +0880 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni0216 +ENCODING 534 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 0 +BITMAP +0780 +0CC0 +0840 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni0217 +ENCODING 535 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 0 +BITMAP +0F00 +1980 +1080 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 22 0 -8 +BITMAP +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +0000 +0C00 +1E00 +1E00 +0E00 +0400 +0800 +1000 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 17 0 -8 +BITMAP +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +0000 +1800 +3C00 +3C00 +1C00 +0800 +1000 +2000 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 22 1 -8 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +0000 +0600 +0F00 +0F00 +0700 +0200 +0400 +0800 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 21 0 -8 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +00 +30 +78 +78 +38 +10 +20 +40 +ENDCHAR +STARTCHAR uni021E +ENCODING 542 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 19 1 0 +BITMAP +0C60 +07C0 +0380 +0100 +0000 +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR uni021F +ENCODING 543 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 19 0 0 +BITMAP +C600 +7C00 +3800 +1000 +0000 +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR uni0226 +ENCODING 550 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 17 0 0 +BITMAP +0300 +0300 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni0227 +ENCODING 551 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 12 0 0 +BITMAP +0C00 +0C00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni0228 +ENCODING 552 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 -4 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR uni0229 +ENCODING 553 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 -4 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR uni022A +ENCODING 554 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 20 0 0 +BITMAP +07E0 +07E0 +0000 +0660 +0660 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni022B +ENCODING 555 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 15 0 0 +BITMAP +1F80 +1F80 +0000 +1980 +1980 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni022C +ENCODING 556 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 21 0 0 +BITMAP +07E0 +07E0 +0000 +0310 +07E0 +08C0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni022D +ENCODING 557 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 0 +BITMAP +3F00 +3F00 +0000 +1880 +3F00 +4600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni022E +ENCODING 558 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 0 0 +BITMAP +0180 +0180 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni022F +ENCODING 559 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 0 +BITMAP +0600 +0600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni0230 +ENCODING 560 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 20 0 0 +BITMAP +07E0 +07E0 +0000 +0180 +0180 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni0231 +ENCODING 561 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 15 0 0 +BITMAP +1F80 +1F80 +0000 +0600 +0600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni0232 +ENCODING 562 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 17 1 0 +BITMAP +1F80 +1F80 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR uni0233 +ENCODING 563 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 -4 +BITMAP +3F00 +3F00 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR uni0250 +ENCODING 592 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +F780 +79C0 +71C0 +71C0 +7700 +7800 +70C0 +71C0 +3F80 +ENDCHAR +STARTCHAR uni0254 +ENCODING 596 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +7C00 +E700 +C380 +0380 +0380 +0380 +8380 +C700 +3C00 +ENDCHAR +STARTCHAR uni0258 +ENCODING 600 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +01C0 +81C0 +C380 +3E00 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +3E00 +C380 +81C0 +01C0 +FFC0 +E1C0 +E1C0 +7380 +1E00 +ENDCHAR +STARTCHAR uni025F +ENCODING 607 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 8 14 0 -5 +BITMAP +1F +0E +0E +0E +0E +0E +0E +0E +3F +0E +0E +EE +EC +78 +ENDCHAR +STARTCHAR uni0265 +ENCODING 613 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 -5 +BITMAP +F9F0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EE0 +00E0 +00E0 +00E0 +00E0 +00F0 +ENDCHAR +STARTCHAR uni0275 +ENCODING 629 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +1F00 +71C0 +E0E0 +FFE0 +FFE0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni0279 +ENCODING 633 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +1F +0E +0E +0E +0E +0E +CE +DE +EF +ENDCHAR +STARTCHAR uni0287 +ENCODING 647 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 13 0 0 +BITMAP +78 +9C +9C +1C +1C +1C +1C +1C +7E +1C +18 +18 +10 +ENDCHAR +STARTCHAR uni0288 +ENCODING 648 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 8 17 0 -4 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +70 +70 +70 +70 +77 +37 +1E +ENDCHAR +STARTCHAR uni0289 +ENCODING 649 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 9 0 0 +BITMAP +F1E0 +70E0 +70E0 +FFF0 +FFF0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni028C +ENCODING 652 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 10 9 -1 0 +BITMAP +0C00 +0C00 +1E00 +1E00 +2700 +2700 +4380 +4380 +E7C0 +ENDCHAR +STARTCHAR uni028D +ENCODING 653 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 9 -1 0 +BITMAP +0C30 +0C30 +1E78 +1E78 +279C +279C +438E +438E +E7DF +ENDCHAR +STARTCHAR uni028E +ENCODING 654 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 13 0 0 +BITMAP +01C0 +02E0 +0460 +0400 +0E00 +0E00 +1700 +1700 +2380 +2380 +41C0 +41C0 +E3E0 +ENDCHAR +STARTCHAR uni029E +ENCODING 670 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 14 0 -5 +BITMAP +FDF0 +78E0 +3CE0 +1EE0 +0FE0 +06E0 +04E0 +18E0 +7CE0 +00E0 +00E0 +00E0 +00E0 +00F0 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +10 +20 +40 +E0 +F0 +F0 +60 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +60 +F0 +F0 +E0 +40 +20 +10 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 7 4 0 10 +BITMAP +10 +38 +7C +C6 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 333 0 +DWIDTH 10 0 +BBX 7 4 1 10 +BITMAP +C6 +7C +38 +10 +ENDCHAR +STARTCHAR uni02C8 +ENCODING 712 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 2 5 1 9 +BITMAP +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 6 2 1 10 +BITMAP +FC +FC +ENDCHAR +STARTCHAR uni02CA +ENCODING 714 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 10 +BITMAP +18 +38 +70 +C0 +ENDCHAR +STARTCHAR uni02CB +ENCODING 715 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 10 +BITMAP +C0 +E0 +70 +18 +ENDCHAR +STARTCHAR uni02CD +ENCODING 717 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 6 2 1 -3 +BITMAP +FC +FC +ENDCHAR +STARTCHAR uni02CE +ENCODING 718 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 -5 +BITMAP +C0 +E0 +70 +18 +ENDCHAR +STARTCHAR uni02CF +ENCODING 719 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 -5 +BITMAP +18 +38 +70 +C0 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 333 0 +DWIDTH 8 0 +BBX 6 3 1 10 +BITMAP +84 +CC +78 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 2 2 2 10 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 4 1 10 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 4 1 -4 +BITMAP +60 +C0 +D0 +60 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 333 0 +DWIDTH 10 0 +BBX 8 3 1 10 +BITMAP +31 +7E +8C +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 333 0 +DWIDTH 9 0 +BBX 7 4 1 10 +BITMAP +66 +66 +CC +88 +ENDCHAR +STARTCHAR uni02EE +ENCODING 750 +SWIDTH 481 0 +DWIDTH 10 0 +BBX 9 7 0 7 +BITMAP +6300 +F780 +F780 +7380 +2100 +4200 +8400 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 278 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +60 +F0 +F0 +60 +00 +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 333 0 +DWIDTH 7 0 +BBX 5 4 1 10 +BITMAP +18 +38 +70 +C0 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 333 0 +DWIDTH 10 0 +BBX 6 7 2 10 +BITMAP +0C +1C +38 +60 +00 +CC +CC +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 4 0 3 +BITMAP +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 -4 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +7EF0 +6000 +7000 +7000 +2000 +ENDCHAR +STARTCHAR uni1E00 +ENCODING 7680 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 19 0 -5 +BITMAP +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +0000 +0180 +0240 +0240 +0180 +ENDCHAR +STARTCHAR uni1E01 +ENCODING 7681 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 14 0 -5 +BITMAP +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +0000 +0C00 +1200 +1200 +0C00 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 17 1 0 +BITMAP +0600 +0600 +0000 +FFC0 +71E0 +70E0 +70E0 +70E0 +71C0 +7F80 +70E0 +70F0 +7070 +7070 +7070 +70E0 +FF80 +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 12 17 -1 0 +BITMAP +1800 +1800 +0000 +F000 +7000 +7000 +7000 +7000 +7780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +6F80 +ENDCHAR +STARTCHAR uni1E04 +ENCODING 7684 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 17 1 -3 +BITMAP +FFC0 +71E0 +70E0 +70E0 +70E0 +71C0 +7F80 +70E0 +70F0 +7070 +7070 +7070 +70E0 +FF80 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E05 +ENCODING 7685 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 12 17 -1 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +7780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +6F80 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E06 +ENCODING 7686 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 17 1 -3 +BITMAP +FFC0 +71E0 +70E0 +70E0 +70E0 +71C0 +7F80 +70E0 +70F0 +7070 +7070 +7070 +70E0 +FF80 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E07 +ENCODING 7687 +SWIDTH 648 0 +DWIDTH 12 0 +BBX 12 17 -1 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +7780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +6F80 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 12 23 1 -4 +BITMAP +0180 +0380 +0700 +0C00 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E000 +F010 +7010 +7820 +3C60 +0F80 +0400 +0700 +0300 +0E00 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 18 0 -4 +BITMAP +0600 +0E00 +1C00 +3000 +0000 +1F00 +7380 +E180 +E000 +E000 +E000 +E080 +7180 +1E00 +1000 +1C00 +0C00 +3800 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0300 +0300 +0000 +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +0180 +0180 +0000 +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +ENDCHAR +STARTCHAR uni1E0C +ENCODING 7692 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E0D +ENCODING 7693 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E0E +ENCODING 7694 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +0000 +0FC0 +0FC0 +ENDCHAR +STARTCHAR uni1E0F +ENCODING 7695 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E10 +ENCODING 7696 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 -4 +BITMAP +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +0400 +0700 +0300 +0E00 +ENDCHAR +STARTCHAR uni1E11 +ENCODING 7697 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 18 0 -4 +BITMAP +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +0400 +0700 +0300 +0E00 +ENDCHAR +STARTCHAR uni1E12 +ENCODING 7698 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 -5 +BITMAP +FFC0 +70F0 +7078 +7038 +703C +701C +701C +701C +701C +703C +7038 +7078 +70F0 +FFC0 +0000 +0200 +0700 +0F80 +18C0 +ENDCHAR +STARTCHAR uni1E13 +ENCODING 7699 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 19 0 -5 +BITMAP +01E0 +00E0 +00E0 +00E0 +00E0 +1EE0 +71E0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71E0 +1EF0 +0000 +0200 +0700 +0F80 +18C0 +ENDCHAR +STARTCHAR uni1E14 +ENCODING 7700 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 22 1 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +1F80 +1F80 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1E15 +ENCODING 7701 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 17 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +3F00 +3F00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1E16 +ENCODING 7702 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 22 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +1F80 +1F80 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1E17 +ENCODING 7703 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 17 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +3F00 +3F00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1E18 +ENCODING 7704 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 19 1 -5 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0000 +0400 +0E00 +1F00 +3180 +ENDCHAR +STARTCHAR uni1E19 +ENCODING 7705 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 14 0 -5 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0000 +0800 +1C00 +3E00 +6300 +ENDCHAR +STARTCHAR uni1E1A +ENCODING 7706 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 -4 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0000 +1880 +3F00 +4600 +ENDCHAR +STARTCHAR uni1E1B +ENCODING 7707 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 -4 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0000 +1880 +3F00 +4600 +ENDCHAR +STARTCHAR uni1E1C +ENCODING 7708 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 22 1 -4 +BITMAP +2100 +3300 +1E00 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR uni1E1D +ENCODING 7709 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 17 0 -4 +BITMAP +2100 +3300 +1E00 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0800 +0E00 +0600 +1C00 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7320 +7F00 +7300 +7100 +7100 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 389 0 +DWIDTH 7 0 +BBX 8 17 0 0 +BITMAP +18 +18 +00 +1E +37 +77 +70 +70 +FC +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni1E20 +ENCODING 7712 +SWIDTH 833 0 +DWIDTH 15 0 +BBX 13 17 1 0 +BITMAP +1F80 +1F80 +0000 +0F90 +3C70 +7830 +7030 +F010 +E010 +E000 +E000 +E0F8 +F070 +7070 +7870 +3CF0 +0F90 +ENDCHAR +STARTCHAR uni1E21 +ENCODING 7713 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 11 18 0 -4 +BITMAP +1F80 +1F80 +0000 +0060 +00E0 +3F00 +7380 +6180 +6180 +7380 +3F00 +6000 +7F80 +3FC0 +C1C0 +C0C0 +E180 +7F00 +ENDCHAR +STARTCHAR uni1E22 +ENCODING 7714 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0300 +0300 +0000 +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR uni1E23 +ENCODING 7715 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +1800 +1800 +0000 +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR uni1E24 +ENCODING 7716 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E25 +ENCODING 7717 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E26 +ENCODING 7718 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0CC0 +0CC0 +0000 +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +ENDCHAR +STARTCHAR uni1E27 +ENCODING 7719 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 0 +BITMAP +6600 +6600 +0000 +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR uni1E28 +ENCODING 7720 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 18 1 -4 +BITMAP +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +0200 +0380 +0180 +0700 +ENDCHAR +STARTCHAR uni1E29 +ENCODING 7721 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 18 0 -4 +BITMAP +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0400 +0700 +0300 +0E00 +ENDCHAR +STARTCHAR uni1E2A +ENCODING 7722 +SWIDTH 870 0 +DWIDTH 16 0 +BBX 14 18 1 -4 +BITMAP +FCFC +7038 +7038 +7038 +7038 +7038 +7FF8 +7038 +7038 +7038 +7038 +7038 +7038 +FCFC +0000 +0840 +0CC0 +0780 +ENDCHAR +STARTCHAR uni1E2B +ENCODING 7723 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 18 0 -4 +BITMAP +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +1080 +1980 +0F00 +ENDCHAR +STARTCHAR uni1E2C +ENCODING 7724 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 8 18 0 -4 +BITMAP +3E +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +3E +00 +31 +7E +8C +ENDCHAR +STARTCHAR uni1E2D +ENCODING 7725 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 8 18 -2 -4 +BITMAP +1C +1C +1C +00 +00 +3C +1C +1C +1C +1C +1C +1C +1C +3E +00 +31 +7E +8C +ENDCHAR +STARTCHAR uni1E2E +ENCODING 7726 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 6 22 2 0 +BITMAP +0C +1C +38 +60 +00 +CC +CC +00 +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni1E2F +ENCODING 7727 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 6 17 0 0 +BITMAP +0C +1C +38 +60 +00 +CC +CC +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni1E30 +ENCODING 7728 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +ENDCHAR +STARTCHAR uni1E31 +ENCODING 7729 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 19 0 0 +BITMAP +0C00 +1C00 +3800 +6000 +0000 +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +ENDCHAR +STARTCHAR uni1E32 +ENCODING 7730 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 17 1 -3 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1E33 +ENCODING 7731 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E34 +ENCODING 7732 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 17 1 -3 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +0000 +07E0 +07E0 +ENDCHAR +STARTCHAR uni1E35 +ENCODING 7733 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +73E0 +7180 +7200 +7600 +7F00 +7780 +73C0 +71E0 +FBF0 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E36 +ENCODING 7734 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 17 1 -3 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E37 +ENCODING 7735 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 5 17 0 -3 +BITMAP +F0 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E38 +ENCODING 7736 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 20 1 -3 +BITMAP +7E00 +7E00 +0000 +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E39 +ENCODING 7737 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 6 20 -1 -3 +BITMAP +FC +FC +00 +78 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +00 +18 +18 +ENDCHAR +STARTCHAR uni1E3A +ENCODING 7738 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 17 1 -3 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +0000 +3F00 +3F00 +ENDCHAR +STARTCHAR uni1E3B +ENCODING 7739 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 6 17 0 -3 +BITMAP +F0 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +00 +FC +FC +ENDCHAR +STARTCHAR uni1E3C +ENCODING 7740 +SWIDTH 722 0 +DWIDTH 12 0 +BBX 11 19 1 -5 +BITMAP +FC00 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7000 +7020 +7020 +7060 +70E0 +FFE0 +0000 +0400 +0E00 +1F00 +3180 +ENDCHAR +STARTCHAR uni1E3D +ENCODING 7741 +SWIDTH 352 0 +DWIDTH 6 0 +BBX 7 19 -1 -5 +BITMAP +78 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +38 +7C +00 +10 +38 +7C +C6 +ENDCHAR +STARTCHAR uni1E3E +ENCODING 7742 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 17 19 1 0 +BITMAP +003000 +007000 +00E000 +018000 +000000 +7C0780 +3C0F00 +3E0F00 +2E1F00 +2F1700 +2F1700 +273700 +27A700 +23E700 +23C700 +23C700 +21C700 +718700 +F88F80 +ENDCHAR +STARTCHAR uni1E3F +ENCODING 7743 +SWIDTH 963 0 +DWIDTH 20 0 +BBX 19 14 0 0 +BITMAP +003000 +007000 +00E000 +018000 +000000 +F7DF80 +79F3C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +F9F3E0 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 17 17 1 0 +BITMAP +00C000 +00C000 +000000 +7C0780 +3C0F00 +3E0F00 +2E1F00 +2F1700 +2F1700 +273700 +27A700 +23E700 +23C700 +23C700 +21C700 +718700 +F88F80 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 963 0 +DWIDTH 20 0 +BBX 19 12 0 0 +BITMAP +00C000 +00C000 +000000 +F7DF80 +79F3C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +F9F3E0 +ENDCHAR +STARTCHAR uni1E42 +ENCODING 7746 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 17 17 1 -3 +BITMAP +7C0780 +3C0F00 +3E0F00 +2E1F00 +2F1700 +2F1700 +273700 +27A700 +23E700 +23C700 +23C700 +21C700 +718700 +F88F80 +000000 +00C000 +00C000 +ENDCHAR +STARTCHAR uni1E43 +ENCODING 7747 +SWIDTH 963 0 +DWIDTH 20 0 +BBX 19 12 0 -3 +BITMAP +F7DF80 +79F3C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +F9F3E0 +000000 +006000 +006000 +ENDCHAR +STARTCHAR uni1E44 +ENCODING 7748 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 1 0 +BITMAP +0300 +0300 +0000 +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR uni1E45 +ENCODING 7749 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 0 +BITMAP +0600 +0600 +0000 +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +ENDCHAR +STARTCHAR uni1E46 +ENCODING 7750 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 1 -3 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E47 +ENCODING 7751 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 -3 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E48 +ENCODING 7752 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 1 -3 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +0000 +0FC0 +0FC0 +ENDCHAR +STARTCHAR uni1E49 +ENCODING 7753 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 -3 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E4A +ENCODING 7754 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 19 1 -5 +BITMAP +F83E +7C1C +3C08 +3E08 +2F08 +2788 +2388 +21C8 +21E8 +20E8 +2078 +2078 +7038 +F818 +0000 +0100 +0380 +07C0 +0C60 +ENDCHAR +STARTCHAR uni1E4B +ENCODING 7755 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 -5 +BITMAP +F7C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +0200 +0700 +0F80 +18C0 +ENDCHAR +STARTCHAR uni1E4C +ENCODING 7756 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 23 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +0310 +07E0 +08C0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1E4D +ENCODING 7757 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +1880 +3F00 +4600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1E4E +ENCODING 7758 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 21 0 0 +BITMAP +0660 +0660 +0000 +0310 +07E0 +08C0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1E4F +ENCODING 7759 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 0 +BITMAP +3300 +3300 +0000 +1880 +3F00 +4600 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1E50 +ENCODING 7760 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 22 0 0 +BITMAP +0600 +0700 +0380 +00C0 +0000 +07E0 +07E0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1E51 +ENCODING 7761 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 17 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +1F80 +1F80 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1E52 +ENCODING 7762 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 22 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +07E0 +07E0 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1E53 +ENCODING 7763 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 17 0 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +1F80 +1F80 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1E54 +ENCODING 7764 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 12 19 1 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +FFE0 +70F0 +7070 +7070 +7070 +70F0 +71E0 +7F80 +7000 +7000 +7000 +7000 +7000 +FC00 +ENDCHAR +STARTCHAR uni1E55 +ENCODING 7765 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 12 18 -1 -4 +BITMAP +0180 +0380 +0700 +0C00 +0000 +E780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +7780 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 12 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +70F0 +7070 +7070 +7070 +70F0 +71E0 +7F80 +7000 +7000 +7000 +7000 +7000 +FC00 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 12 16 -1 -4 +BITMAP +0600 +0600 +0000 +E780 +78E0 +7070 +7070 +7070 +7070 +7070 +78E0 +7780 +7000 +7000 +7000 +F800 +ENDCHAR +STARTCHAR uni1E58 +ENCODING 7768 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +ENDCHAR +STARTCHAR uni1E59 +ENCODING 7769 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 12 0 0 +BITMAP +18 +18 +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +ENDCHAR +STARTCHAR uni1E5A +ENCODING 7770 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E5B +ENCODING 7771 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 12 0 -3 +BITMAP +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E5C +ENCODING 7772 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 20 1 -3 +BITMAP +0FC0 +0FC0 +0000 +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E5D +ENCODING 7773 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 15 0 -3 +BITMAP +7E +7E +00 +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1E5E +ENCODING 7774 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +FFE0 +70F0 +7070 +7070 +70F0 +71E0 +7F80 +71C0 +71E0 +70E0 +70E0 +70F0 +7074 +F878 +0000 +0FC0 +0FC0 +ENDCHAR +STARTCHAR uni1E5F +ENCODING 7775 +SWIDTH 519 0 +DWIDTH 9 0 +BBX 8 12 0 -3 +BITMAP +F7 +7B +73 +70 +70 +70 +70 +70 +F8 +00 +FC +FC +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 17 0 0 +BITMAP +0C00 +0C00 +0000 +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 12 0 0 +BITMAP +1800 +1800 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR uni1E62 +ENCODING 7778 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 17 0 -3 +BITMAP +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E63 +ENCODING 7779 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 12 0 -3 +BITMAP +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1E64 +ENCODING 7780 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 22 0 0 +BITMAP +0600 +0600 +0000 +0300 +0700 +0E00 +1800 +0000 +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +ENDCHAR +STARTCHAR uni1E65 +ENCODING 7781 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 17 0 0 +BITMAP +0C00 +0C00 +0000 +0600 +0E00 +1C00 +3000 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR uni1E66 +ENCODING 7782 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 10 17 0 0 +BITMAP +0C00 +0C00 +0000 +6180 +3300 +1E00 +0C00 +0000 +3F80 +7180 +7880 +7E00 +3F00 +0F80 +83C0 +C780 +BF00 +ENDCHAR +STARTCHAR uni1E67 +ENCODING 7783 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 17 0 0 +BITMAP +1800 +1800 +0000 +C300 +6600 +3C00 +1800 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +ENDCHAR +STARTCHAR uni1E68 +ENCODING 7784 +SWIDTH 667 0 +DWIDTH 12 0 +BBX 11 20 0 -3 +BITMAP +0C00 +0C00 +0000 +3F40 +61C0 +C0C0 +C040 +E000 +FE00 +7FC0 +7FE0 +0FE0 +80E0 +8060 +C060 +E0C0 +BF80 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E69 +ENCODING 7785 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 15 0 -3 +BITMAP +1800 +1800 +0000 +3D00 +6300 +E100 +FC00 +7F00 +0F80 +8380 +C300 +BE00 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 17 1 0 +BITMAP +0600 +0600 +0000 +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 16 0 0 +BITMAP +30 +30 +00 +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +ENDCHAR +STARTCHAR uni1E6C +ENCODING 7788 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 17 1 -3 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1E6D +ENCODING 7789 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 16 0 -3 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +00 +30 +30 +ENDCHAR +STARTCHAR uni1E6E +ENCODING 7790 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 17 1 -3 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E6F +ENCODING 7791 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 16 0 -3 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +00 +FC +FC +ENDCHAR +STARTCHAR uni1E70 +ENCODING 7792 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 19 1 -5 +BITMAP +FFE0 +CE60 +CE60 +8E20 +8E20 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +0000 +0400 +0E00 +1F00 +3180 +ENDCHAR +STARTCHAR uni1E71 +ENCODING 7793 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 18 0 -5 +BITMAP +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +00 +10 +38 +7C +C6 +ENDCHAR +STARTCHAR uni1E72 +ENCODING 7794 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +0000 +1980 +1980 +ENDCHAR +STARTCHAR uni1E73 +ENCODING 7795 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 -3 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +0000 +1980 +1980 +ENDCHAR +STARTCHAR uni1E74 +ENCODING 7796 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 18 1 -4 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +0000 +0C40 +1F80 +2300 +ENDCHAR +STARTCHAR uni1E75 +ENCODING 7797 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 13 0 -4 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +0000 +0C40 +1F80 +2300 +ENDCHAR +STARTCHAR uni1E76 +ENCODING 7798 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 19 1 -5 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +0000 +0200 +0700 +0F80 +18C0 +ENDCHAR +STARTCHAR uni1E77 +ENCODING 7799 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 14 0 -5 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +0000 +0200 +0700 +0F80 +18C0 +ENDCHAR +STARTCHAR uni1E78 +ENCODING 7800 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 23 1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0620 +0FC0 +1180 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni1E79 +ENCODING 7801 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 18 0 0 +BITMAP +0180 +0380 +0700 +0C00 +0000 +0C40 +1F80 +2300 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni1E7A +ENCODING 7802 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 20 1 0 +BITMAP +0CC0 +0CC0 +0000 +0FC0 +0FC0 +0000 +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +ENDCHAR +STARTCHAR uni1E7B +ENCODING 7803 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 15 0 0 +BITMAP +1980 +1980 +0000 +1F80 +1F80 +0000 +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni1E7C +ENCODING 7804 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0620 +0FC0 +1180 +0000 +F87C +7038 +7830 +3820 +3820 +3C60 +1C40 +1E40 +0EC0 +0E80 +0780 +0780 +0300 +0300 +ENDCHAR +STARTCHAR uni1E7D +ENCODING 7805 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 10 13 -1 0 +BITMAP +1880 +3F00 +4600 +0000 +F9C0 +7080 +7080 +3900 +3900 +1E00 +1E00 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E7E +ENCODING 7806 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 17 0 -3 +BITMAP +F87C +7038 +7830 +3820 +3820 +3C60 +1C40 +1E40 +0EC0 +0E80 +0780 +0780 +0300 +0300 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1E7F +ENCODING 7807 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 10 12 -1 -3 +BITMAP +F9C0 +7080 +7080 +3900 +3900 +1E00 +1E00 +0C00 +0C00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 19 0 0 +BITMAP +030000 +038000 +01C000 +006000 +000000 +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 14 -1 0 +BITMAP +0600 +0700 +0380 +00C0 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 19 0 0 +BITMAP +003000 +007000 +00E000 +018000 +000000 +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 14 -1 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 17 0 0 +BITMAP +033000 +033000 +000000 +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 12 -1 0 +BITMAP +0CC0 +0CC0 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 17 0 0 +BITMAP +00C000 +00C000 +000000 +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 12 -1 0 +BITMAP +0300 +0300 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR uni1E88 +ENCODING 7816 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 17 0 -3 +BITMAP +FBF3E0 +71E1C0 +70E180 +78E100 +38F100 +39F300 +3D7200 +1D3A00 +1F3E00 +1E3C00 +0E1C00 +0E1C00 +0C1800 +040800 +000000 +00C000 +00C000 +ENDCHAR +STARTCHAR uni1E89 +ENCODING 7817 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 12 -1 -3 +BITMAP +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1E8A +ENCODING 7818 +SWIDTH 722 0 +DWIDTH 17 0 +BBX 16 17 0 0 +BITMAP +0180 +0180 +0000 +7E3F +3C1C +1E18 +0E30 +0F60 +07C0 +03C0 +03E0 +06F0 +0C70 +1878 +303C +703E +F87F +ENDCHAR +STARTCHAR uni1E8B +ENCODING 7819 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 0 +BITMAP +0C00 +0C00 +0000 +FCE0 +78C0 +3D00 +1E00 +0E00 +0F00 +1780 +63C0 +E7E0 +ENDCHAR +STARTCHAR uni1E8C +ENCODING 7820 +SWIDTH 722 0 +DWIDTH 17 0 +BBX 16 17 0 0 +BITMAP +0660 +0660 +0000 +7E3F +3C1C +1E18 +0E30 +0F60 +07C0 +03C0 +03E0 +06F0 +0C70 +1878 +303C +703E +F87F +ENDCHAR +STARTCHAR uni1E8D +ENCODING 7821 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 0 +BITMAP +3300 +3300 +0000 +FCE0 +78C0 +3D00 +1E00 +0E00 +0F00 +1780 +63C0 +E7E0 +ENDCHAR +STARTCHAR uni1E8E +ENCODING 7822 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 17 1 0 +BITMAP +0600 +0600 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR uni1E8F +ENCODING 7823 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 -4 +BITMAP +0C00 +0C00 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR uni1E90 +ENCODING 7824 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 19 1 0 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +ENDCHAR +STARTCHAR uni1E91 +ENCODING 7825 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 14 0 0 +BITMAP +08 +1C +3E +63 +00 +FF +CF +8E +1C +38 +39 +71 +F3 +FF +ENDCHAR +STARTCHAR uni1E92 +ENCODING 7826 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 17 1 -3 +BITMAP +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1E93 +ENCODING 7827 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 12 0 -3 +BITMAP +FF +CF +8E +1C +38 +39 +71 +F3 +FF +00 +18 +18 +ENDCHAR +STARTCHAR uni1E94 +ENCODING 7828 +SWIDTH 667 0 +DWIDTH 13 0 +BBX 11 17 1 -3 +BITMAP +FFE0 +E1E0 +C1C0 +83C0 +8780 +0700 +0F00 +1E00 +1C00 +3C20 +7820 +7060 +F0E0 +FFE0 +0000 +3F00 +3F00 +ENDCHAR +STARTCHAR uni1E95 +ENCODING 7829 +SWIDTH 537 0 +DWIDTH 10 0 +BBX 8 12 0 -3 +BITMAP +FF +CF +8E +1C +38 +39 +71 +F3 +FF +00 +7E +7E +ENDCHAR +STARTCHAR uni1E96 +ENCODING 7830 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 17 0 -3 +BITMAP +F000 +7000 +7000 +7000 +7000 +77C0 +79E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +F9F0 +0000 +1F80 +1F80 +ENDCHAR +STARTCHAR uni1E97 +ENCODING 7831 +SWIDTH 426 0 +DWIDTH 8 0 +BBX 7 16 0 0 +BITMAP +CC +CC +00 +10 +30 +30 +70 +FC +70 +70 +70 +70 +70 +72 +72 +3C +ENDCHAR +STARTCHAR uni1E98 +ENCODING 7832 +SWIDTH 889 0 +DWIDTH 15 0 +BBX 16 14 -1 0 +BITMAP +0300 +0480 +0480 +0300 +0000 +FBE7 +71C2 +71C2 +39E4 +39E4 +1E78 +1E78 +0C30 +0C30 +ENDCHAR +STARTCHAR uni1E99 +ENCODING 7833 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +0C00 +1200 +1200 +0C00 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR uni1EA0 +ENCODING 7840 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 17 0 -3 +BITMAP +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1EA1 +ENCODING 7841 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 12 0 -3 +BITMAP +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EA4 +ENCODING 7844 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 23 0 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0380 +07C0 +0C60 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EA5 +ENCODING 7845 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +1C00 +3E00 +6300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EA6 +ENCODING 7846 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 23 0 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +0380 +07C0 +0C60 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EA7 +ENCODING 7847 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +1C00 +3E00 +6300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EAA +ENCODING 7850 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 22 0 0 +BITMAP +0310 +07E0 +08C0 +0000 +0380 +07C0 +0C60 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EAB +ENCODING 7851 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 17 0 0 +BITMAP +1880 +3F00 +4600 +0000 +1C00 +3E00 +6300 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EAC +ENCODING 7852 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 22 0 -3 +BITMAP +0200 +0700 +0F80 +18C0 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1EAD +ENCODING 7853 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 17 0 -3 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EAE +ENCODING 7854 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 23 0 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0840 +0CC0 +0780 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EAF +ENCODING 7855 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +2100 +3300 +1E00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EB0 +ENCODING 7856 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 23 0 0 +BITMAP +0C00 +0E00 +0700 +0180 +0000 +0840 +0CC0 +0780 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EB1 +ENCODING 7857 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +2100 +3300 +1E00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EB4 +ENCODING 7860 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 22 0 0 +BITMAP +0620 +0FC0 +1180 +0000 +0840 +0CC0 +0780 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni1EB5 +ENCODING 7861 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 17 0 0 +BITMAP +1880 +3F00 +4600 +0000 +2100 +3300 +1E00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +ENDCHAR +STARTCHAR uni1EB6 +ENCODING 7862 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 21 0 -3 +BITMAP +0840 +0CC0 +0780 +0000 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1EB7 +ENCODING 7863 +SWIDTH 611 0 +DWIDTH 11 0 +BBX 10 16 0 -3 +BITMAP +2100 +3300 +1E00 +0000 +7F00 +E380 +C380 +0780 +3B80 +E380 +E380 +E780 +7BC0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EB8 +ENCODING 7864 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 17 1 -3 +BITMAP +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EB9 +ENCODING 7865 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 12 0 -3 +BITMAP +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EBC +ENCODING 7868 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 18 1 0 +BITMAP +0C40 +1F80 +2300 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1EBD +ENCODING 7869 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 13 0 0 +BITMAP +1880 +3F00 +4600 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1EBE +ENCODING 7870 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 23 1 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +0E00 +1F00 +3180 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1EBF +ENCODING 7871 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +0E00 +1F00 +3180 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1EC0 +ENCODING 7872 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 23 1 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +0E00 +1F00 +3180 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1EC1 +ENCODING 7873 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 18 0 0 +BITMAP +3000 +3800 +1C00 +0600 +0000 +0E00 +1F00 +3180 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1EC4 +ENCODING 7876 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 22 1 0 +BITMAP +0C40 +1F80 +2300 +0000 +0E00 +1F00 +3180 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +ENDCHAR +STARTCHAR uni1EC5 +ENCODING 7877 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 17 0 0 +BITMAP +0C40 +1F80 +2300 +0000 +0E00 +1F00 +3180 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +ENDCHAR +STARTCHAR uni1EC6 +ENCODING 7878 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 22 1 -3 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +FFE0 +70E0 +7060 +7120 +7120 +7300 +7F00 +7300 +7100 +7120 +7020 +7060 +70E0 +FFE0 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1EC7 +ENCODING 7879 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 10 17 0 -3 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +1E00 +7380 +E1C0 +E1C0 +FFC0 +E000 +E040 +70C0 +1F00 +0000 +0C00 +0C00 +ENDCHAR +STARTCHAR uni1ECA +ENCODING 7882 +SWIDTH 444 0 +DWIDTH 9 0 +BBX 5 17 2 -3 +BITMAP +F8 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +70 +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1ECB +ENCODING 7883 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 17 0 -3 +BITMAP +70 +70 +70 +00 +00 +F0 +70 +70 +70 +70 +70 +70 +70 +F8 +00 +30 +30 +ENDCHAR +STARTCHAR uni1ECC +ENCODING 7884 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 17 0 -3 +BITMAP +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1ECD +ENCODING 7885 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 12 0 -3 +BITMAP +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1ED0 +ENCODING 7888 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 23 0 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +0380 +07C0 +0C60 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1ED1 +ENCODING 7889 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 0 +BITMAP +0300 +0700 +0E00 +1800 +0000 +0E00 +1F00 +3180 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1ED2 +ENCODING 7890 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 23 0 0 +BITMAP +0600 +0700 +0380 +00C0 +0000 +0380 +07C0 +0C60 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1ED3 +ENCODING 7891 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +0E00 +1F00 +3180 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1ED6 +ENCODING 7894 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 22 0 0 +BITMAP +0310 +07E0 +08C0 +0000 +0380 +07C0 +0C60 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +ENDCHAR +STARTCHAR uni1ED7 +ENCODING 7895 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 17 0 0 +BITMAP +0C40 +1F80 +2300 +0000 +0E00 +1F00 +3180 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1ED8 +ENCODING 7896 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 22 0 -3 +BITMAP +0100 +0380 +07C0 +0C60 +0000 +0FE0 +3C78 +783C +701C +F01E +E00E +E00E +E00E +E00E +F01E +701C +783C +3C78 +0FE0 +0000 +0180 +0180 +ENDCHAR +STARTCHAR uni1ED9 +ENCODING 7897 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 17 0 -3 +BITMAP +0400 +0E00 +1F00 +3180 +0000 +1F00 +71C0 +E0E0 +E0E0 +E0E0 +E0E0 +E0E0 +71C0 +1F00 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1EDA +ENCODING 7898 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 18 19 0 0 +BITMAP +001800 +003800 +007000 +00C000 +000000 +0FE180 +3C7BC0 +783FC0 +701DC0 +F01E80 +E00F00 +E00E00 +E00E00 +E00E00 +F01E00 +701C00 +783C00 +3C7800 +0FE000 +ENDCHAR +STARTCHAR uni1EDB +ENCODING 7899 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 14 14 0 0 +BITMAP +00C0 +01C0 +0380 +0600 +0000 +1F18 +71FC +E0FC +E0FC +E0E8 +E0F0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1EDC +ENCODING 7900 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 18 19 0 0 +BITMAP +018000 +01C000 +00E000 +003000 +000000 +0FE180 +3C7BC0 +783FC0 +701DC0 +F01E80 +E00F00 +E00E00 +E00E00 +E00E00 +F01E00 +701C00 +783C00 +3C7800 +0FE000 +ENDCHAR +STARTCHAR uni1EDD +ENCODING 7901 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 14 14 0 0 +BITMAP +0600 +0700 +0380 +00C0 +0000 +1F18 +71FC +E0FC +E0FC +E0E8 +E0F0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1EE0 +ENCODING 7904 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 18 18 0 0 +BITMAP +00C400 +01F800 +023000 +000000 +0FE180 +3C7BC0 +783FC0 +701DC0 +F01E80 +E00F00 +E00E00 +E00E00 +E00E00 +F01E00 +701C00 +783C00 +3C7800 +0FE000 +ENDCHAR +STARTCHAR uni1EE1 +ENCODING 7905 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 14 13 0 0 +BITMAP +0310 +07E0 +08C0 +0000 +1F18 +71FC +E0FC +E0FC +E0E8 +E0F0 +E0E0 +71C0 +1F00 +ENDCHAR +STARTCHAR uni1EE2 +ENCODING 7906 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 18 17 0 -3 +BITMAP +0FE180 +3C7BC0 +783FC0 +701DC0 +F01E80 +E00F00 +E00E00 +E00E00 +E00E00 +F01E00 +701C00 +783C00 +3C7800 +0FE000 +000000 +018000 +018000 +ENDCHAR +STARTCHAR uni1EE3 +ENCODING 7907 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 14 12 0 -3 +BITMAP +1F18 +71FC +E0FC +E0FC +E0E8 +E0F0 +E0E0 +71C0 +1F00 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1EE4 +ENCODING 7908 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 14 17 1 -3 +BITMAP +F87C +7038 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +7010 +3820 +1FC0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1EE5 +ENCODING 7909 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 12 12 0 -3 +BITMAP +F1E0 +70E0 +70E0 +70E0 +70E0 +70E0 +70E0 +79E0 +3EF0 +0000 +0600 +0600 +ENDCHAR +STARTCHAR uni1EE8 +ENCODING 7912 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 19 1 0 +BITMAP +003000 +007000 +00E000 +018000 +000000 +F87F00 +703F80 +701780 +701380 +701100 +701200 +701400 +701000 +701000 +701000 +701000 +701000 +382000 +1FC000 +ENDCHAR +STARTCHAR uni1EE9 +ENCODING 7913 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 15 14 0 0 +BITMAP +0060 +00E0 +01C0 +0300 +0000 +F1EC +70FE +70FE +70EE +70E4 +70E8 +70F0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni1EEA +ENCODING 7914 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 19 1 0 +BITMAP +030000 +038000 +01C000 +006000 +000000 +F87F00 +703F80 +701780 +701380 +701100 +701200 +701400 +701000 +701000 +701000 +701000 +701000 +382000 +1FC000 +ENDCHAR +STARTCHAR uni1EEB +ENCODING 7915 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 15 14 0 0 +BITMAP +0600 +0700 +0380 +00C0 +0000 +F1EC +70FE +70FE +70EE +70E4 +70E8 +70F0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni1EEE +ENCODING 7918 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 18 1 0 +BITMAP +018800 +03F000 +046000 +000000 +F87F00 +703F80 +701780 +701380 +701100 +701200 +701400 +701000 +701000 +701000 +701000 +701000 +382000 +1FC000 +ENDCHAR +STARTCHAR uni1EEF +ENCODING 7919 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 15 13 0 0 +BITMAP +0310 +07E0 +08C0 +0000 +F1EC +70FE +70FE +70EE +70E4 +70E8 +70F0 +79E0 +3EF0 +ENDCHAR +STARTCHAR uni1EF0 +ENCODING 7920 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 17 17 1 -3 +BITMAP +F87F00 +703F80 +701780 +701380 +701100 +701200 +701400 +701000 +701000 +701000 +701000 +701000 +382000 +1FC000 +000000 +030000 +030000 +ENDCHAR +STARTCHAR uni1EF1 +ENCODING 7921 +SWIDTH 685 0 +DWIDTH 13 0 +BBX 15 12 0 -3 +BITMAP +F1EC +70FE +70FE +70EE +70E4 +70E8 +70F0 +79E0 +3EF0 +0000 +0300 +0300 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 19 1 0 +BITMAP +1800 +1C00 +0E00 +0300 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 18 0 -4 +BITMAP +3000 +3800 +1C00 +0600 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR uni1EF4 +ENCODING 7924 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 17 1 -3 +BITMAP +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +0000 +0300 +0300 +ENDCHAR +STARTCHAR uni1EF5 +ENCODING 7925 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 16 0 -7 +BITMAP +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +0000 +1800 +1800 +ENDCHAR +STARTCHAR uni1EF8 +ENCODING 7928 +SWIDTH 722 0 +DWIDTH 15 0 +BBX 13 18 1 0 +BITMAP +0C40 +1F80 +2300 +0000 +F878 +7030 +7820 +3860 +3C40 +1CC0 +1F80 +0F80 +0F00 +0700 +0700 +0700 +0700 +0F80 +ENDCHAR +STARTCHAR uni1EF9 +ENCODING 7929 +SWIDTH 611 0 +DWIDTH 12 0 +BBX 11 17 0 -4 +BITMAP +1880 +3F00 +4600 +0000 +F8E0 +7040 +7040 +3880 +3880 +1D00 +1D00 +0E00 +0E00 +0400 +C400 +E800 +7000 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 1000 0 +DWIDTH 19 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 1000 0 +DWIDTH 19 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 250 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 167 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 574 0 +DWIDTH 11 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 200 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 100 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200B +ENCODING 8203 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 4 +BITMAP +F8 +F8 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 2 0 4 +BITMAP +F8 +F8 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 9 2 0 4 +BITMAP +FF80 +FF80 +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 500 0 +DWIDTH 9 0 +BBX 9 2 0 4 +BITMAP +FF80 +FF80 +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 18 0 +BBX 18 2 0 4 +BITMAP +FFFFC0 +FFFFC0 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 18 0 +BBX 18 2 0 4 +BITMAP +FFFFC0 +FFFFC0 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +10 +20 +40 +E0 +F0 +F0 +60 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 241 0 +DWIDTH 6 0 +BBX 4 7 1 -3 +BITMAP +60 +F0 +F0 +70 +20 +40 +80 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 241 0 +DWIDTH 5 0 +BBX 4 7 0 7 +BITMAP +60 +F0 +F0 +E0 +40 +20 +10 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 481 0 +DWIDTH 10 0 +BBX 9 7 0 7 +BITMAP +1080 +2100 +4200 +E700 +F780 +F780 +6300 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 481 0 +DWIDTH 10 0 +BBX 9 7 0 7 +BITMAP +6300 +F780 +F780 +7380 +2100 +4200 +8400 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 481 0 +DWIDTH 11 0 +BBX 9 7 1 -3 +BITMAP +6300 +F780 +F780 +7380 +2100 +4200 +8400 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 481 0 +DWIDTH 10 0 +BBX 9 7 0 7 +BITMAP +6300 +F780 +F780 +E700 +4200 +2100 +1080 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 16 0 -2 +BITMAP +1C00 +1C00 +0800 +C980 +FF80 +C980 +0800 +1C00 +1C00 +0800 +0800 +0800 +0800 +0800 +0800 +0800 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 500 0 +DWIDTH 10 0 +BBX 9 16 0 -2 +BITMAP +1C00 +1C00 +0800 +C980 +FF80 +C980 +0800 +1C00 +1C00 +0800 +C980 +FF80 +C980 +0800 +1C00 +1C00 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 6 6 2 4 +BITMAP +78 +FC +FC +FC +FC +78 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 18 0 +BBX 16 4 1 0 +BITMAP +6186 +F3CF +F3CF +6186 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1000 0 +DWIDTH 22 0 +BBX 21 15 0 -1 +BITMAP +38C000 +674000 +C4C000 +C48000 +C58000 +C90000 +730000 +023870 +0664C8 +04C588 +0CC588 +08C588 +18C990 +1070E0 +100000 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 5 0 3 +BITMAP +30 +60 +C0 +60 +30 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 5 0 3 +BITMAP +C0 +60 +30 +60 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 167 0 +DWIDTH 3 0 +BBX 8 14 -3 0 +BITMAP +03 +03 +06 +06 +0C +0C +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 -4 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +FC +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 -4 +BITMAP +78 +CC +CC +18 +30 +60 +C4 +FC +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 344 0 +DWIDTH 6 0 +BBX 6 8 0 -4 +BITMAP +78 +CC +0C +38 +0C +CC +CC +78 +ENDCHAR +STARTCHAR uni20A5 +ENCODING 8357 +SWIDTH 963 0 +DWIDTH 20 0 +BBX 19 14 0 -2 +BITMAP +001800 +001800 +001800 +F7FF80 +79F3C0 +70F1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +70E1C0 +F9F3E0 +018000 +018000 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 833 0 +DWIDTH 16 0 +BBX 15 14 1 0 +BITMAP +F83E +7C1C +3C08 +3E08 +3FF8 +3FF8 +2388 +21C8 +3FF8 +3FF8 +2078 +2078 +7038 +F818 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 981 0 +DWIDTH 19 0 +BBX 19 14 0 0 +BITMAP +FBF3E0 +71E1C0 +70E180 +78E100 +3FFD00 +3FFF00 +3D7200 +1D3A00 +1FFE00 +1FFC00 +0E1C00 +0E1C00 +0C1800 +040800 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 778 0 +DWIDTH 14 0 +BBX 14 14 -1 0 +BITMAP +03E4 +0F1C +1E0C +1C0C +FF84 +FF84 +3800 +3800 +FF80 +FF84 +1C04 +1E08 +0F18 +03E0 +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 14 1 0 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +FFFE +FFFE +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 1158 0 +DWIDTH 21 0 +BBX 20 14 0 0 +BITMAP +780F90 +CC3C70 +847830 +847030 +CCF010 +78E010 +00E000 +00E000 +00E000 +00F010 +007010 +007820 +003C60 +000F80 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 1102 0 +DWIDTH 20 0 +BBX 19 14 0 0 +BITMAP +78FFE0 +CC70E0 +847060 +847120 +CC7120 +787320 +007F00 +007300 +007100 +007100 +007000 +007000 +007000 +00F800 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 1000 0 +DWIDTH 20 0 +BBX 19 8 0 6 +BITMAP +FFF1E0 +9971C0 +185AC0 +185AC0 +185AC0 +184CC0 +184CC0 +3CEDE0 +ENDCHAR +STARTCHAR uni212A +ENCODING 8490 +SWIDTH 815 0 +DWIDTH 16 0 +BBX 15 14 1 0 +BITMAP +FC7C +7030 +7060 +70C0 +7180 +7300 +7780 +7FC0 +7BC0 +71E0 +70F0 +70F8 +707C +FCFE +ENDCHAR +STARTCHAR uni212B +ENCODING 8491 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 18 0 0 +BITMAP +0300 +0480 +0480 +0300 +0300 +0300 +0780 +0780 +0F80 +09C0 +09C0 +19E0 +10E0 +3FE0 +20F0 +6070 +4078 +E0FC +ENDCHAR +STARTCHAR uni2132 +ENCODING 8498 +SWIDTH 722 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +03E0 +01C0 +01C0 +01C0 +11C0 +11C0 +19C0 +1FC0 +99C0 +91C0 +91C0 +C1C0 +E1C0 +FFE0 +ENDCHAR +STARTCHAR universal +ENCODING 8704 +SWIDTH 759 0 +DWIDTH 14 0 +BBX 14 14 0 0 +BITMAP +E0FC +4078 +6070 +20F0 +3FE0 +10E0 +19E0 +09C0 +09C0 +0F80 +0780 +0780 +0300 +0300 +ENDCHAR +STARTCHAR existential +ENCODING 8707 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +E1C0 +C1C0 +91C0 +91C0 +19C0 +1FC0 +19C0 +11C0 +91C0 +81C0 +C1C0 +E1C0 +FFE0 +ENDCHAR +STARTCHAR uni2204 +ENCODING 8708 +SWIDTH 759 0 +DWIDTH 13 0 +BBX 11 14 1 0 +BITMAP +FFE0 +E1C0 +C1C0 +93C0 +93C0 +1BC0 +1FC0 +1FC0 +17C0 +9DC0 +8DC0 +CDC0 +F9C0 +FFE0 +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 606 0 +DWIDTH 10 0 +BBX 9 2 0 4 +BITMAP +FF80 +FF80 +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 167 0 +DWIDTH 3 0 +BBX 8 14 -3 0 +BITMAP +03 +03 +06 +06 +0C +0C +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 4 4 0 3 +BITMAP +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR uni2236 +ENCODING 8758 +SWIDTH 278 0 +DWIDTH 6 0 +BBX 4 9 1 0 +BITMAP +60 +F0 +F0 +60 +00 +60 +F0 +F0 +60 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 11 1 2 +BITMAP +0800 +1C00 +3E00 +6300 +0000 +FF80 +FF80 +0000 +0000 +FF80 +FF80 +ENDCHAR +STARTCHAR uni225A +ENCODING 8794 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 11 1 2 +BITMAP +6300 +3E00 +1C00 +0800 +0000 +FF80 +FF80 +0000 +0000 +FF80 +FF80 +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 14 1 -2 +BITMAP +0300 +0300 +0300 +0600 +FF80 +FF80 +0C00 +0C00 +FF80 +FF80 +1800 +1800 +3000 +3000 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 8 0 1 +BITMAP +FF80 +FF80 +0000 +FF80 +FF80 +0000 +FF80 +FF80 +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 9 14 0 -2 +BITMAP +0300 +0300 +0300 +FF80 +FF80 +0600 +FF80 +FF80 +0C00 +FF80 +FF80 +1800 +3000 +3000 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 13 0 -3 +BITMAP +00C0 +03C0 +0F00 +3C00 +F000 +F000 +3C00 +0F00 +03C0 +00C0 +0000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 13 0 -3 +BITMAP +C000 +F000 +3C00 +0F00 +03C0 +03C0 +0F00 +3C00 +F000 +C000 +0000 +FFC0 +FFC0 +ENDCHAR +STARTCHAR uni226E +ENCODING 8814 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 14 0 -2 +BITMAP +0300 +0300 +03C0 +07C0 +0F00 +3E00 +FC00 +FC00 +3C00 +1F00 +1BC0 +18C0 +3000 +3000 +ENDCHAR +STARTCHAR uni226F +ENCODING 8815 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 14 0 -2 +BITMAP +0300 +0300 +C300 +F600 +3E00 +0F00 +0FC0 +0FC0 +0F00 +3C00 +F800 +D800 +3000 +3000 +ENDCHAR +STARTCHAR uni2270 +ENCODING 8816 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 14 0 -3 +BITMAP +0300 +03C0 +03C0 +0F00 +3E00 +F600 +FC00 +3C00 +0F00 +1BC0 +18C0 +1800 +FFC0 +FFC0 +ENDCHAR +STARTCHAR uni2271 +ENCODING 8817 +SWIDTH 606 0 +DWIDTH 11 0 +BBX 10 14 0 -3 +BITMAP +0300 +C300 +F300 +3E00 +0F00 +07C0 +0FC0 +0F00 +3C00 +F800 +D800 +1800 +FFC0 +FFC0 +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 685 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +0F80 +39C0 +31C0 +7000 +7000 +FFC0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +FBE0 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 685 0 +DWIDTH 12 0 +BBX 11 14 0 0 +BITMAP +1EC0 +33C0 +71C0 +71C0 +71C0 +FFC0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +71C0 +FBE0 +ENDCHAR +ENDFONT diff --git a/bertos/fs/battfs.c b/bertos/fs/battfs.c new file mode 100644 index 00000000..fd8fe1c6 --- /dev/null +++ b/bertos/fs/battfs.c @@ -0,0 +1,826 @@ +/** + * \file + * + * + * \version $Id:$ + * + * \author Francesco Sacchi + * + * \brief BattFS: a filesystem for embedded platforms (implementation). + */ + +#include "battfs.h" + +#include +#include /* MIN, MAX */ +#include /* cpu_to_xx */ + + +#include /* memset, memmove */ + + +/** + * Convert from memory representation to disk structure. + * \note filesystem is in little-endian format. + */ +INLINE void battfs_to_disk(struct BattFsPageHeader *hdr, uint8_t *buf) +{ + STATIC_ASSERT(BATTFS_HEADER_LEN == 12); + buf[0] = hdr->inode; + + buf[1] = hdr->fill; + buf[2] = hdr->fill >> 8; + + buf[3] = hdr->pgoff; + buf[4] = hdr->pgoff >> 8; + + /* + * Mark is at least 1 bit longer than page address. + * Needed to take care of wraparonds. + */ + buf[5] = hdr->mark; + buf[6] = hdr->mark >> 8; + + /* + * First bit used by mark, last 2 bits used by seq. + * Since only 2 pages with the same inode and pgoff + * can exist at the same time, 2 bit for seq are enough. + * Unused bits are set to 1. + */ + buf[7] = ((hdr->mark >> 16) & 0x01) | (hdr->seq << 6) | ~(BV(7) | BV(6) | BV(0)); + + /* + * This field must be the before the last one! + */ + buf[8] = hdr->fcs_free; + buf[9] = hdr->fcs_free >> 8; + + /* + * This field must be the last one! + * This is needed because if the page is only partially + * written, we can use this to detect it. + */ + buf[10] = hdr->fcs; + buf[11] = hdr->fcs >> 8; +} + +/** + * Convert from disk structure to memory representation. + * \note filesystem is in little-endian format. + */ +INLINE void disk_to_battfs(uint8_t *buf, struct BattFsPageHeader *hdr) +{ + STATIC_ASSERT(BATTFS_HEADER_LEN == 12); + hdr->inode = buf[0]; + hdr->fill = buf[2] << 8 | buf[1]; + hdr->pgoff = buf[4] << 8 | buf[3]; + hdr->mark = (mark_t)(buf[7] & 0x01) << 16 | buf[6] << 8 | buf[5]; + hdr->seq = buf[7] >> 6; + hdr->fcs_free = buf[9] << 8 | buf[8]; + hdr->fcs = buf[11] << 8 | buf[10]; +} + +/** + * Compute the fcs of the header. + */ +static fcs_t computeFcs(struct BattFsPageHeader *hdr) +{ + uint8_t buf[BATTFS_HEADER_LEN]; + fcs_t cks; + + battfs_to_disk(hdr, buf); + rotating_init(&cks); + /* fcs is at the end of whole header */ + rotating_update(buf, BATTFS_HEADER_LEN - sizeof(fcs_t), &cks); + return cks; +} + +/** + * Compute the fcs of the header marked as free. + */ +static fcs_t computeFcsFree(struct BattFsPageHeader *hdr) +{ + uint8_t buf[BATTFS_HEADER_LEN]; + fcs_t cks; + + battfs_to_disk(hdr, buf); + rotating_init(&cks); + /* fcs_free is just before fcs of whole header */ + rotating_update(buf, BATTFS_HEADER_LEN - 2 * sizeof(fcs_t), &cks); + return cks; +} + + +/** + * Read header of page \a page. + * \return true on success, false otherwise. + * \note \a hdr is dirtyed even on errors. + */ +static bool battfs_readHeader(struct BattFsSuper *disk, pgcnt_t page, struct BattFsPageHeader *hdr) +{ + uint8_t buf[BATTFS_HEADER_LEN]; + /* + * Read header from disk. + * Header is actually a footer, and so + * resides at page end. + */ + if (disk->read(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) + != BATTFS_HEADER_LEN) + { + TRACEMSG("Error: page[%d]\n", page); + return false; + } + + /* Fill header */ + disk_to_battfs(buf, hdr); + + return true; +} + +/** + * Write header of page \a page. + * \return true on success, false otherwise. + * \note \a hdr is dirtyed even on errors. + */ +static bool battfs_writeHeader(struct BattFsSuper *disk, pgcnt_t page, struct BattFsPageHeader *hdr) +{ + uint8_t buf[BATTFS_HEADER_LEN]; + + /* Fill buffer */ + battfs_to_disk(hdr, buf); + + /* + * write header to disk. + * Header is actually a footer, and so + * resides at page end. + */ + if (disk->write(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) + != BATTFS_HEADER_LEN) + { + TRACEMSG("Error: page[%d]\n", page); + return false; + } + return true; +} + +/** + * Count the number of pages from + * inode 0 to \a inode in \a filelen_table. + */ +static pgcnt_t countPages(pgoff_t *filelen_table, inode_t inode) +{ + pgcnt_t cnt = 0; + + for (inode_t i = 0; i < inode; i++) + cnt += filelen_table[i]; + + return cnt; +} + +/** + * Move all pages in page allocation array from \a src to \a src + \a offset. + * The number of pages moved is page_count - MAX(dst, src). + */ +static void movePages(struct BattFsSuper *disk, pgcnt_t src, int offset) +{ + pgcnt_t dst = src + offset; + memmove(&disk->page_array[dst], &disk->page_array[src], (disk->page_count - MAX(dst, src)) * sizeof(pgcnt_t)); + + if (offset < 0) + { + /* Fill empty space in array with sentinel */ + for (pgcnt_t page = disk->page_count + offset; page < disk->page_count; page++) + disk->page_array[page] = PAGE_UNSET_SENTINEL; + } +} + +/** + * Insert \a page into page allocation array of \a disk, + * using \a mark to compute position. + */ +static void insertFreePage(struct BattFsSuper *disk, mark_t mark, pgcnt_t page) +{ + ASSERT(mark - disk->free_start < disk->free_next - disk->free_start); + + pgcnt_t free_pos = disk->page_count - disk->free_next + mark; + ASSERT(free_pos < disk->page_count); + + TRACEMSG("mark:%u, page:%u, free_start:%u, free_next:%u, free_pos:%u\n", + mark, page, disk->free_start, disk->free_next, free_pos); + + ASSERT(disk->page_array[free_pos] == PAGE_UNSET_SENTINEL); + disk->page_array[free_pos] = page; +} + +/** + * Mark \a page of \a disk as free. + * \note free_next of \a disk is used as \a page free marker + * and is increased by 1. + */ +static bool battfs_markFree(struct BattFsSuper *disk, struct BattFsPageHeader *hdr, pgcnt_t page) +{ + uint8_t buf[BATTFS_HEADER_LEN]; + + hdr->mark = disk->free_next; + hdr->fcs_free = computeFcsFree(hdr); + battfs_to_disk(hdr, buf); + + if (!disk->write(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN)) + { + TRACEMSG("error marking page [%d]\n", page); + return false; + } + else + { + disk->free_next++; + return true; + } +} + +/** + * Determine free_start and free_next blocks for \a disk + * using \a minl, \a maxl, \a minh, \a maxh. + * + * Mark_t is a type that has at least 1 bit more than + * pgaddr_t. So all free blocks can be numbered using + * at most half numbers of a mark_t type. + * The free blocks algorithm increments by 1 the disk->free_next + * every time a page becomes free. So the free block sequence is + * guaranteed to be countiguous. + * Only wrap arounds may happen, but due to half size sequence limitation, + * there are only 4 possible situations: + * + * \verbatim + * |------lower half------|-------upper half-------| + * + * 1) |------minl*****maxl---|------------------------| + * 2) |------minl********maxl|minh******maxh----------| + * 3) |----------------------|----minh*******maxh-----| + * 4) |minl******maxl--------|------------minh****maxh| + * \endverbatim + * + * Situations 1 and 3 are easy to detect, while 2 and 4 require more care. + */ +static void findFreeStartNext(struct BattFsSuper *disk, mark_t minl, mark_t maxl, mark_t minh, mark_t maxh) +{ + /* Determine free_start & free_next */ + if (maxl >= minl) + { + /* Valid interval found in lower half */ + if (maxh >= minh) + { + /* Valid interval also found in upper half */ + if (maxl == minh - 1) + { + /* Interval starts in lower half and ends in upper */ + disk->free_start = minl; + disk->free_next = maxh; + } + else + { + /* Interval starts in upper half and ends in lower */ + ASSERT(minl == 0); + ASSERT(maxh == (MAX_PAGE_ADDR | MARK_HALF_SIZE)); + + disk->free_start = minh; + disk->free_next = maxl; + } + } + else + { + /* + * Upper interval is invalid. + * Use lower values. + */ + + disk->free_start = minl; + disk->free_next = maxl; + } + } + else if (maxh >= minh) + { + /* + * Lower interval is invalid. + * Use upper values. + */ + disk->free_start = minh; + disk->free_next = maxh; + } + else + { + /* + * No valid interval found. + * Hopefully the disk is brand new (or full). + */ + TRACEMSG("No valid marked free block found, new disk or disk full\n"); + disk->free_start = 0; + disk->free_next = -1; //to be increased later + } + + /* free_next should contain the first usable address */ + disk->free_next++; + + TRACEMSG("Free markers:\n minl %u\n maxl %u\n minh %u\n maxh %u\n free_start %u\n free_next %u\n", + minl, maxl, minh, maxh, disk->free_start, disk->free_next); +} + +/** + * Count number of pages per file on \a disk. + * This information is registered in \a filelen_table. + * Array index represent file inode, while value contained + * is the number of pages used by that file. + * + * \return true if ok, false on disk read errors. + * \note The whole disk is scanned once. + */ +static bool countDiskFilePages(struct BattFsSuper *disk, pgoff_t *filelen_table) +{ + BattFsPageHeader hdr; + mark_t minl, maxl, minh, maxh; + + /* Initialize min and max counters to keep trace od free blocks */ + minl = MAX_PAGE_ADDR; + maxl = 0; + minh = MAX_PAGE_ADDR | MARK_HALF_SIZE; + maxh = 0 | MARK_HALF_SIZE; + + + /* Count the number of disk page per file */ + for (pgcnt_t page = 0; page < disk->page_count; page++) + { + if (!battfs_readHeader(disk, page, &hdr)) + return false; + + /* Check header FCS */ + if (hdr.fcs == computeFcs(&hdr)) + { + ASSERT(hdr.mark == MARK_PAGE_VALID); + ASSERT(hdr.fcs_free == FCS_FREE_VALID); + ASSERT(hdr.fill <= disk->page_size - BATTFS_HEADER_LEN); + + /* Page is valid and is owned by a file */ + filelen_table[hdr.inode]++; + + /* Keep trace of free space */ + disk->free_bytes += disk->page_size - BATTFS_HEADER_LEN - hdr.fill; + } + else + { + /* Increase free space */ + disk->free_bytes += disk->page_size - BATTFS_HEADER_LEN; + + /* Check if page is marked free */ + if (hdr.fcs_free == computeFcsFree(&hdr)) + { + /* + * This page is a valid and marked free page. + * Update min and max free page markers. + */ + if (hdr.mark < MARK_HALF_SIZE) + { + minl = MIN(minl, hdr.mark); + maxl = MAX(maxl, hdr.mark); + } + else + { + minh = MIN(minh, hdr.mark); + maxh = MAX(maxh, hdr.mark); + } + } + else + TRACEMSG("page [%d] invalid, keeping as free\n", page); + } + } + findFreeStartNext(disk, minl, maxl, minh, maxh); + return true; +} + +/** + * Fill page allocation array of \a disk + * using file lenghts in \a filelen_table. + * + * The page allocation array is an array containings all file infos. + * Is ordered by file, and within each file is ordered by page offset + * inside file. + * e.g. : at page array[0] you will find page address of the first page + * of the first file (if present). + * Free blocks are allocated after the last file, starting from invalid ones + * and continuing with the marked free ones. + * + * \return true if ok, false on disk read errors. + * \note The whole disk is scanned once. + */ +static bool fillPageArray(struct BattFsSuper *disk, pgoff_t *filelen_table) +{ + BattFsPageHeader hdr; + /* Fill page allocation array */ + for (pgcnt_t page = 0; page < disk->page_count; page++) + { + if (!battfs_readHeader(disk, page, &hdr)) + return false; + + /* Check header FCS */ + if (hdr.fcs == computeFcs(&hdr)) + { + /* Page is valid and is owned by a file */ + ASSERT(hdr.mark == MARK_PAGE_VALID); + ASSERT(hdr.fcs_free == FCS_FREE_VALID); + + /* Compute array position */ + pgcnt_t array_pos = countPages(filelen_table, hdr.inode); + array_pos += hdr.pgoff; + + /* Check if position is already used by another page of the same file */ + if (LIKELY(disk->page_array[array_pos] == PAGE_UNSET_SENTINEL)) + disk->page_array[array_pos] = page; + else + { + BattFsPageHeader hdr_old; + + if (!battfs_readHeader(disk, disk->page_array[array_pos], &hdr_old)) + return false; + + /* Check header FCS */ + ASSERT(hdr_old.fcs == computeFcs(&hdr_old)); + + /* Only the very same page with a different seq number can be here */ + ASSERT(hdr.inode == hdr_old.inode); + ASSERT(hdr.pgoff == hdr_old.pgoff); + ASSERT(hdr.mark == hdr_old.mark); + ASSERT(hdr.fcs_free == hdr_old.fcs_free); + ASSERT(hdr.seq != hdr_old.seq); + + pgcnt_t new_page, old_page; + fill_t old_fill; + + /* Fancy check to handle seq wraparound (2 bits only) */ + if (((hdr.seq - hdr_old.seq) & 0x03) < 2) + { + /* Current header is newer than the previuos one */ + old_page = disk->page_array[array_pos]; + new_page = page; + old_fill = hdr_old.fill; + } + else + { + /* Previous header is newer than the current one */ + old_page = page; + new_page = disk->page_array[array_pos]; + old_fill = hdr.fill; + } + + /* Set new page */ + disk->page_array[array_pos] = new_page; + + /* Add free space */ + disk->free_bytes += old_fill; + + /* Shift all array one position to the left, overwriting duplicate page */ + array_pos -= hdr.pgoff; + array_pos += filelen_table[hdr.inode]; + movePages(disk, array_pos, -1); + + /* Decrease file page count */ + filelen_table[hdr.inode]--; + + /* Add old page to free pages pool */ + if (!battfs_markFree(disk, &hdr, old_page)) + return false; + + insertFreePage(disk, hdr.mark, old_page); + } + } + else + { + /* Check if page is free */ + if (hdr.fcs_free != computeFcsFree(&hdr)) + /* Page is not a valid marked page, insert at list beginning */ + hdr.mark = --disk->free_start; + + insertFreePage(disk, hdr.mark, page); + } + } + return true; +} + +/** + * Initialize and mount disk described by + * \a disk. + * \return false on errors, true otherwise. + */ +bool battfs_init(struct BattFsSuper *disk) +{ + pgoff_t filelen_table[BATTFS_MAX_FILES]; + + /* Sanity check */ + ASSERT(disk->open); + + /* Init disk device */ + if (!disk->open(disk)) + { + TRACEMSG("open error\n"); + return false; + } + + /* Disk open must set all of these */ + ASSERT(disk->read); + ASSERT(disk->write); + ASSERT(disk->erase); + ASSERT(disk->close); + ASSERT(disk->page_size); + ASSERT(disk->page_count); + ASSERT(disk->page_count < PAGE_UNSET_SENTINEL - 1); + ASSERT(disk->page_array); + + memset(filelen_table, 0, BATTFS_MAX_FILES * sizeof(pgoff_t)); + + disk->free_bytes = 0; + disk->disk_size = (disk_size_t)(disk->page_size - BATTFS_HEADER_LEN) * disk->page_count; + + /* Count pages per file */ + if (!countDiskFilePages(disk, filelen_table)) + { + TRACEMSG("error counting file pages\n"); + return false; + } + + /* Once here, we have filelen_table filled with file lengths */ + + /* Fill page array with sentinel */ + for (pgcnt_t page = 0; page < disk->page_count; page++) + disk->page_array[page] = PAGE_UNSET_SENTINEL; + + /* Fill page allocation array using filelen_table */ + if (!fillPageArray(disk, filelen_table)) + { + TRACEMSG("error filling page array\n"); + return false; + } + + /* Init list for opened files. */ + LIST_INIT(&disk->file_opened_list); + return true; +} + +/** + * Flush file \a fd. + * \return 0 if ok, EOF on errors. + */ +static int battfs_flush(struct KFile *fd) +{ + (void)fd; + #warning TODO + return 0; +} + +/** + * Close file \a fd. + * \return 0 if ok, EOF on errors. + */ +static int battfs_fileclose(struct KFile *fd) +{ + KFileBattFs *fdb = KFILEBATTFS(fd); + + battfs_flush(fd); + REMOVE(&fdb->link); + return 0; +} + +/** + * Read from file \a fd \a size bytes in \a buf. + * \return The number of bytes read. + */ +static size_t battfs_read(struct KFile *fd, void *_buf, size_t size) +{ + KFileBattFs *fdb = KFILEBATTFS(fd); + uint8_t *buf = (uint8_t *)_buf; + + size_t total_read = 0; + pgoff_t pg_offset; + pgaddr_t addr_offset; + pgaddr_t read_len; + + size = MIN(size, fd->size - fd->seek_pos); + + while (size) + { + pg_offset = fd->seek_pos / (fdb->disk->page_size - BATTFS_HEADER_LEN); + addr_offset = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); + read_len = MIN(size, (size_t)(fdb->disk->page_size - BATTFS_HEADER_LEN - addr_offset)); + + /* Read from disk */ + if (fdb->disk->read(fdb->disk, fdb->start[pg_offset], addr_offset, buf, read_len) != read_len) + { + #warning TODO set error? + } + + size -= read_len; + fd->seek_pos += read_len; + total_read += read_len; + buf += read_len; + } + return total_read; +} + + +/** + * Search file \a inode in \a disk using a binary search. + * \return pointer to file start in disk->page_array + * if file exists, NULL otherwise. + */ +static pgcnt_t *findFile(BattFsSuper *disk, inode_t inode) +{ + BattFsPageHeader hdr; + pgcnt_t first = 0, page, last = disk->page_count -1; + fcs_t fcs; + + while (first <= last) + { + page = (first + last) / 2; + + if (!battfs_readHeader(disk, disk->page_array[page], &hdr)) + return NULL; + + fcs = computeFcs(&hdr); + if (hdr.fcs == fcs && hdr.inode == inode) + return (&disk->page_array[page]) - hdr.pgoff; + else if (hdr.fcs == fcs && hdr.inode < inode) + first = page + 1; + else + last = page - 1; + } + + return NULL; +} + +/** + * \return true if file \a inode exists on \a disk, false otherwise. + */ +bool battfs_fileExists(BattFsSuper *disk, inode_t inode) +{ + return findFile(disk, inode) != NULL; +} + +/** + * Count size of file \a inode on \a disk, starting at pointer \a start + * in disk->page_array. Size is written in \a size. + * \return true if all s ok, false on disk read errors. + */ +static bool countFileSize(BattFsSuper *disk, pgcnt_t *start, inode_t inode, file_size_t *size) +{ + *size = 0; + BattFsPageHeader hdr; + + for (;;) + { + if (!battfs_readHeader(disk, *start++, &hdr)) + return false; + if (hdr.fcs == computeFcs(&hdr) && hdr.inode == inode) + *size += hdr.fill; + else + return true; + } +} + +/** + * Open file \a inode from \a disk in \a mode. + * File context is stored in \a fd. + * \return true if ok, false otherwise. + */ +bool battfs_fileopen(BattFsSuper *disk, KFileBattFs *fd, inode_t inode, filemode_t mode) +{ + Node *n; + + memset(fd, 0, sizeof(*fd)); + + /* Search file start point in disk page array */ + fd->start = findFile(disk, inode); + if (fd->start == NULL) + { + if (!(mode & BATTFS_CREATE)) + return false; + + /* File does not exist, create it */ + BattFsPageHeader hdr; + hdr.inode = inode; + hdr.seq = 0; + hdr.fill = 0; + hdr.pgoff = 0; + hdr.mark = MARK_PAGE_VALID; + hdr.fcs_free = FCS_FREE_VALID; + hdr.fcs = computeFcs(&hdr); + #warning TODO: get a free block and write on disk! + } + + /* Fill file size */ + if (!countFileSize(disk, fd->start, inode, &fd->fd.size)) + return false; + + /* Reset seek position */ + fd->fd.seek_pos = 0; + + /* Insert file handle in list, ordered by inode, ascending. */ + FOREACH_NODE(n, &disk->file_opened_list) + { + KFileBattFs *file = containerof(n, KFileBattFs, link); + if (file->inode >= inode) + break; + } + INSERT_BEFORE(&fd->link, n); + + /* Fill in data */ + fd->inode = inode; + fd->mode = mode; + fd->disk = disk; + + fd->fd.close = battfs_fileclose; + fd->fd.flush = battfs_flush; + fd->fd.read = battfs_read; + fd->fd.reopen = kfile_genericReopen; + fd->fd.seek = kfile_genericSeek; + +#warning TODO battfs_write, battfs_error, battfs_clearerr +#if 0 + fd->fd.write = battfs_write; + fd->fd.error = battfs_error; + fd->fd.clearerr = battfs_clearerr; +#endif + + DB(fd->fd._type = KFT_BATTFS); + + return true; +} + +/** + * Close \a disk. + */ +bool battfs_close(struct BattFsSuper *disk) +{ + Node *n; + int res = 0; + + /* Close all open files */ + FOREACH_NODE(n, &disk->file_opened_list) + { + KFileBattFs *file = containerof(n, KFileBattFs, link); + res += battfs_fileclose(&file->fd); + } + + /* Close disk */ + return disk->close(disk) && (res == 0); +} + + +bool battfs_writeTestBlock(struct BattFsSuper *disk, pgcnt_t page, inode_t inode, seq_t seq, fill_t fill, pgoff_t pgoff, mark_t mark) +{ + BattFsPageHeader hdr; + + hdr.inode = inode; + hdr.seq = seq; + hdr.fill = fill; + hdr.pgoff = pgoff; + hdr.mark = MARK_PAGE_VALID; + hdr.fcs_free = FCS_FREE_VALID; + hdr.fcs = computeFcs(&hdr); + if (mark != MARK_PAGE_VALID) + { + hdr.mark = mark; + hdr.fcs_free = computeFcsFree(&hdr); + } + + if (!battfs_writeHeader(disk, page, &hdr)) + { + TRACEMSG("error writing hdr\n"); + return false; + } + + return true; +} diff --git a/bertos/fs/battfs.h b/bertos/fs/battfs.h new file mode 100644 index 00000000..59d8fece --- /dev/null +++ b/bertos/fs/battfs.h @@ -0,0 +1,264 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Francesco Sacchi + * + * \brief BattFS: a filesystem for embedded platforms (interface). + * TODO: Add detailed filesystem description. + */ + +#ifndef FS_BATTFS_H +#define FS_BATTFS_H + +#include // uintXX_t; STATIC_ASSERT +#include // CPU_BITS_PER_CHAR +#include +#include +#include + +typedef uint16_t fill_t; ///< Type for keeping trace of space filled inside a page +typedef fill_t pgaddr_t; ///< Type for addressing space inside a page +typedef uint16_t pgcnt_t; ///< Type for counting pages on disk +typedef pgcnt_t pgoff_t; ///< Type for counting pages inside a file +typedef uint32_t mark_t; ///< Type for marking pages as free +typedef uint8_t inode_t; ///< Type for file inodes +typedef uint8_t seq_t; ///< Type for page seq number +typedef rotating_t fcs_t; ///< Type for header FCS. + +/** + * Size required for free block allocation is at least 1 bit more + * than page addressing. + */ +STATIC_ASSERT(sizeof(mark_t) > sizeof(pgcnt_t)); + +/** + * BattFS page header, used to represent a page + * header in memory. + * To see how this is stored on disk: + * \see battfs_to_disk + * \see disk_to_battfs + */ +typedef struct BattFsPageHeader +{ + inode_t inode; ///< File inode (file identifier). + seq_t seq; ///< Page sequence number. + fill_t fill; ///< Filled bytes in page. + pgoff_t pgoff; ///< Page offset inside file. + mark_t mark; ///< Marker used to keep trace of free/used pages. + + /** + * FCS (Frame Check Sequence) of the page header once the page + * as been marked as free. + */ + fcs_t fcs_free; + + /** + * FCS (Frame Check Sequence) of the page header. + */ + fcs_t fcs; +} BattFsPageHeader; + +/** + * Size of the header once saved on disk. + * \see battfs_to_disk + * \see disk_to_battfs + */ +#define BATTFS_HEADER_LEN 12 + +/** + * Marks for valid pages. + * Simply set to 1 all field bits. + * \{ + */ +#define MARK_PAGE_VALID ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t) + 1)) - 1) +#define FCS_FREE_VALID ((1 << (CPU_BITS_PER_CHAR * sizeof(fcs_t))) - 1) +/* \} */ + + +/** + * Half-size of free page marker. + * Used to keep trace of free marker wrap-arounds. + */ +#define MARK_HALF_SIZE (1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t) + 1)) + +/** + * Maximum page address. + */ +#define MAX_PAGE_ADDR ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t))) - 1) + +/** + * Max number of files. + */ +#define BATTFS_MAX_FILES (1 << (CPU_BITS_PER_CHAR * sizeof(inode_t))) + +/* Fwd decl */ +struct BattFsSuper; + +/** + * Sentinel used to keep trace of unset pages in disk->page_array. + */ +#define PAGE_UNSET_SENTINEL ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t))) - 1) + +/** + * Type interface for disk init function. + * \return true if all is ok, false otherwise. + */ +typedef bool (*disk_open_t) (struct BattFsSuper *d); + +/** + * Type interface for disk page read function. + * \a page is the page address, \a addr the address inside the page, + * \a size the lenght to be read. + * \return the number of bytes read. + */ +typedef size_t (*disk_page_read_t) (struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t); + +/** + * Type interface for disk page write function. + * \a page is the page address, \a addr the address inside the page, + * \a size the lenght to be written. + * \return the number of bytes written. + */ +typedef size_t (*disk_page_write_t) (struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, const void *buf, size_t); + +/** + * Type interface for disk page erase function. + * \a page is the page address. + * \return true if all is ok, false otherwise. + */ +typedef bool (*disk_page_erase_t) (struct BattFsSuper *d, pgcnt_t page); + +/** + * Type interface for disk deinit function. + * \return true if all is ok, false otherwise. + */ +typedef bool (*disk_close_t) (struct BattFsSuper *d); + + +typedef uint32_t disk_size_t; ///< Type for disk sizes. + +/** + * Context used to describe a disk. + * This context structure will be used to access disk. + * Must be initialized by hw memory driver. + */ +typedef struct BattFsSuper +{ + disk_open_t open; ///< Disk init. + disk_page_read_t read; ///< Page read. + disk_page_write_t write; ///< Page write. + disk_page_erase_t erase; ///< Page erase. + disk_close_t close; ///< Disk deinit. + + pgaddr_t page_size; ///< Size of a disk page, in bytes. + pgcnt_t page_count; ///< Number of pages on disk. + + /** + * Page allocation array. + * This array must be allocated somewhere and + * must have enough space for page_count elements. + * Is used by the filesystem to represent + * the entire disk in memory. + */ + pgcnt_t *page_array; + + /** + * Lowest free page counter. + * This is the counter of the first availble free page. + */ + mark_t free_start; + + /** + * Highest free page counter. + * This value is the next to be used to mark a block as free. + */ + mark_t free_next; + + disk_size_t disk_size; ///< Size of the disk, in bytes (page_count * page_size). + disk_size_t free_bytes; ///< Free space on the disk. + + List file_opened_list; ///< List used to keep trace of open files. + /* TODO add other fields. */ +} BattFsSuper; + +typedef uint8_t filemode_t; ///< Type for file open modes. +typedef uint32_t file_size_t; ///< Type for file sizes. + +/** + * Modes for battfs_fileopen. + * \{ + */ +#define BATTFS_CREATE BV(0) ///< Create file if does not exist +#define BATTFS_RD BV(1) ///< Open file for reading +#define BATTFS_WR BV(2) ///< Open file fir writing +/*/}*/ + + +/** + * Describe a BattFs file usign a KFile. + */ +typedef struct KFileBattFs +{ + KFile fd; ///< KFile context + Node link; ///< Link for inserting in opened file list + inode_t inode; ///< inode of the opened file + BattFsSuper *disk; ///< Disk context + filemode_t mode; ///< File open mode + pgcnt_t *start; ///< Pointer to page_array file start position. +} KFileBattFs; + +/** + * Id for battfs file descriptors. + */ +#define KFT_BATTFS MAKE_ID('B', 'T', 'F', 'S') + +/** + * Macro used to cast a KFile to a KFileBattFs. + * Also perform dynamic type check. + */ +INLINE KFileBattFs * KFILEBATTFS(KFile *fd) +{ + ASSERT(fd->_type == KFT_BATTFS); + return (KFileBattFs *)fd; +} + +bool battfs_init(struct BattFsSuper *d); +bool battfs_close(struct BattFsSuper *disk); + +bool battfs_fileExists(BattFsSuper *disk, inode_t inode); +bool battfs_fileopen(BattFsSuper *disk, KFileBattFs *fd, inode_t inode, filemode_t mode); + +bool battfs_writeTestBlock(struct BattFsSuper *disk, pgcnt_t page, inode_t inode, seq_t seq, fill_t fill, pgoff_t pgoff, mark_t mark); + +#endif /* FS_BATTFS_H */ diff --git a/bertos/gfx/bitmap.c b/bertos/gfx/bitmap.c new file mode 100644 index 00000000..d4c447e6 --- /dev/null +++ b/bertos/gfx/bitmap.c @@ -0,0 +1,265 @@ +/** + * \file + * + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief Bitmap manipulation routines. + */ + +#include "gfx.h" +#include "gfx_p.h" + +#include /* ASSERT() */ +#include /* CPU_HARVARD */ +#include /* MIN() */ +#include /* CONFIG_GFX_CLIPPING */ + +#include /* memset() */ + +#if CONFIG_GFX_TEXT +#include /* default_font */ +#endif + + +/** + * Initialize a Bitmap structure with the provided parameters. + * + * \note The pen position is reset to the origin. + */ +void gfx_bitmapInit(Bitmap *bm, uint8_t *raster, coord_t w, coord_t h) +{ + bm->raster = raster; + bm->width = w; + bm->height = h; + #if (CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB) + bm->stride = (w + 7) / 8; + #elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB + bm->stride = w; + #else + #error Unknown value of CONFIG_BITMAP_FMT + #endif /* CONFIG_BITMAP_FMT */ + bm->penX = 0; + bm->penY = 0; + +#if CONFIG_GFX_TEXT + gfx_setFont(bm, &default_font); + bm->styles = 0; +#endif + +#if CONFIG_GFX_CLIPPING + bm->cr.xmin = 0; + bm->cr.ymin = 0; + bm->cr.xmax = w; + bm->cr.ymax = h; +#endif /* CONFIG_GFX_CLIPPING */ +} + + +/** + * Clear the whole bitmap surface to the background color. + * + * \note This function does \b not update the current pen position. + * \note This function bypasses the current clipping area. + */ +void gfx_bitmapClear(Bitmap *bm) +{ + memset(bm->raster, 0, RAST_SIZE(bm->width, bm->height)); +} + + +#if CPU_HARVARD + +#include /* FIXME: memcpy_P() */ + +/** + * 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. + * + * \note This function does \b not update the current pen position + */ +void gfx_blit_P(Bitmap *bm, const pgm_uint8_t *raster) +{ + memcpy_P(bm->raster, raster, RAST_SIZE(bm->width, bm->height)); +} +#endif /* CPU_HARVARD */ + +#if CONFIG_GFX_CLIPPING + /** + * Clip destination coordinates inside a clipping range. + * + * This macro helps a drawing operation to adjust its + * destination X and Y coordinates inside the destination + * clipping range. + * + * The source start coordinate is adjusted as well + * when destination start clipping occurs. + */ + #define gfx_clip(dmin, dmax, smin, cmin, cmax) \ + do { \ + if ((dmin) < (cmin)) \ + { \ + (smin) += (cmin) - (dmin); \ + (dmin) = (cmin); \ + } \ + (dmax) = MIN((dmax), (cmax)); \ + } while(0) + +#else /* !CONFIG_GFX_CLIPPING */ + + #define gfx_clip(dmin, dmax, smin, cmin, cmax) do { } while (0) + +#endif /* !CONFIG_GFX_CLIPPING */ + + +/** + * Copy a rectangular area of a bitmap on another bitmap. + * + * Blitting is a common copy operation involving two bitmaps. + * A rectangular area of the source bitmap is copied bit-wise + * to a different position in the destination bitmap. + * + * \note Using the same bitmap for \a src and \a dst is unsupported. + * + * \param dst Bitmap where the operation writes. + * \param rect The (xmin;ymin) coordinates provide the top/left offset + * for drawing in the destination bitmap. If the source + * bitmap is larger than the rectangle, drawing is clipped. + * \param src Bitmap containing the source pixels. + * \param srcx Starting X offset in the source bitmap. + * \param srcy Starting Y offset in the source bitmap. + */ +void gfx_blit(Bitmap *dst, const Rect *rect, const Bitmap *src, coord_t srcx, coord_t srcy) +{ + coord_t dxmin, dymin, dxmax, dymax; + coord_t dx, dy, sx, sy; + + /* + * Pre-clip coordinates inside src->width/height. + */ + dxmin = rect->xmin; + dymin = rect->ymin; + dxmax = MIN(rect->xmax, rect->xmin + src->width); + dymax = MIN(rect->ymax, rect->ymin + src->height); + + /* Perform regular clipping */ + gfx_clip(dxmin, dxmax, srcx, dst->cr.xmin, dst->cr.xmax); + gfx_clip(dymin, dymax, srcy, dst->cr.ymin, dst->cr.ymax); + + //kprintf("dxmin=%d, sxmin=%d, dxmax=%d; ", dxmin, sxmin, dxmax); + //kprintf("dymin=%d, symin=%d, dymax=%d\n", dymin, symin, dymax); + + /* TODO: make it not as dog slow as this */ + for (dx = dxmin, sx = srcx; dx < dxmax; ++dx, ++sx) + for (dy = dymin, sy = srcy; dy < dymax; ++dy, ++sy) + BM_DRAWPIXEL(dst, dx, dy, BM_READPIXEL(src, sx, sy)); +} + +/** + * Blit a raster to a Bitmap. + * + * \todo Merge this function into gfx_blit() + * + * \see gfx_blit() + */ +void gfx_blitRaster(Bitmap *dst, coord_t dxmin, coord_t dymin, + const uint8_t *raster, coord_t w, coord_t h, coord_t stride) +{ + coord_t dxmax = dxmin + w, dymax = dymin + h; + coord_t sxmin = 0, symin = 0; + coord_t dx, dy, sx, sy; + + /* Perform regular clipping */ + gfx_clip(dxmin, dxmax, sxmin, dst->cr.xmin, dst->cr.xmax); + gfx_clip(dymin, dymax, symin, dst->cr.ymin, dst->cr.ymax); + + //kprintf("dxmin=%d, sxmin=%d, dxmax=%d; ", dxmin, sxmin, dxmax); + //kprintf("dymin=%d, symin=%d, dymax=%d\n", dymin, symin, dymax); + + /* TODO: make it not as dog slow as this */ + for (dx = dxmin, sx = sxmin; dx < dxmax; ++dx, ++sx) + for (dy = dymin, sy = symin; dy < dymax; ++dy, ++sy) + BM_DRAWPIXEL(dst, dx, dy, RAST_READPIXEL(raster, sx, sy, stride)); +} + +/** + * Blit an Image to a Bitmap. + * + * \see gfx_blit() + */ +void gfx_blitImage(Bitmap *dst, coord_t dxmin, coord_t dymin, const Image *image) +{ + ASSERT(image); + + gfx_blitRaster(dst, dxmin, dymin, + image->raster, image->width, image->height, image->stride); +} + + +#if CONFIG_GFX_CLIPPING || CONFIG_GFX_VCOORDS + +/** + * Set the bitmap clipping rectangle to the specified coordinates. + * + * All drawing performed on the bitmap will be clipped inside this + * rectangle. + * + * The clipping rectangle is also used as a bounding box for the + * logical view of the virtual coordinate system. + * + * \note Following the convention used for all other operations, the + * top-left pixels of the rectangle are included, while the + * bottom-right pixels are considered outside the clipping region. + * + * \see gfx_setViewRect + */ +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; + +// 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); +} + +#endif /* CONFIG_GFX_CLIPPING */ + diff --git a/bertos/gfx/charts.c b/bertos/gfx/charts.c new file mode 100644 index 00000000..b4abbea0 --- /dev/null +++ b/bertos/gfx/charts.c @@ -0,0 +1,195 @@ +/** + * \file + * + * + * \brief Simple charts on top of mware/gfx routines (implementation). + * + * Sample usage: + * + * \code + * bm = chart_init(0, ymax, N_POINTS_CURVE, ymin); + * + * chart_drawCurve(bm, curve_y, curve_points + 1); + * gfx_setViewRect(bm, xmin, ymax, xmax, ymin); + * chart_drawDots(bm, samples_x, samples_y, samples_cnt); + * + * print_bitmap(bm); + * \endcode + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2005/11/27 23:33:29 bernie + *#* Reorder includes. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.7 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.6 2004/11/16 21:04:23 bernie + *#* Update to new naming scheme in mware/gfx.c. + *#* + *#* Revision 1.5 2004/09/14 20:56:39 bernie + *#* Make more generic and adapt to new gfx functions. + *#* + *#* Revision 1.3 2004/08/11 19:39:12 bernie + *#* Use chart_x_t and chart_y_t for the input dataset. + *#* + *#* Revision 1.1 2004/08/04 03:16:30 bernie + *#* Import simple chart drawing code. + *#* + *#*/ + +#include "charts.h" +#include + + +#ifndef CONFIG_CHART_ARROWS +#define CONFIG_CHART_ARROWS 0 +#endif + + +void chart_init(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax) +{ + /* Clear the chart area */ + gfx_rectClear(bm, xmin, ymin, xmax, ymax); + + gfx_setClipRect(bm, xmin + CHART_BORDERLEFT, ymin + CHART_BORDERTOP, + xmax - CHART_BORDERRIGHT, ymax - CHART_BORDERBOTTOM); + + chart_drawAxis(bm); +} + + +void chart_setScale(Bitmap *bm, chart_x_t xmin, chart_y_t ymin, chart_x_t xmax, chart_y_t ymax) +{ + gfx_setViewRect(bm, xmin, ymin, xmax, ymax); +} + + +/** + * Draw the chart axes + */ +void chart_drawAxis(Bitmap *bm) +{ +#if CONFIG_CHART_ARROWS + + /* Draw axis */ + gfx_moveTo(bm, bm->cr.xmin, bm->cr.ymin + 4); + gfx_lineTo(bm, bm->cr.xmin, bm->cr.ymax - 1); + gfx_lineTo(bm, bm->cr.xmax - 4 - 1, bm->cr.ymax - 1); + + /* Draw up arrow */ + gfx_moveTo(bm, bm->cr.xmin - 2, bm->cr.ymin + 3); + gfx_lineTo(bm, bm->cr.xmin + 2, bm->cr.ymin + 3); + gfx_lineTo(bm, bm->cr.xmin, bm->cr.ymin); + gfx_lineTo(bm, bm->cr.xmin - 2, bm->cr.ymin + 3); + + /* Draw right arrow */ + gfx_moveTo(bm, bm->cr.xmax - 4, bm->cr.ymax - 3); + gfx_lineTo(bm, bm->cr.xmax - 4, bm->cr.ymax + 1); + gfx_lineTo(bm, bm->cr.xmax - 1, bm->cr.ymax - 1); + gfx_lineTo(bm, bm->cr.xmax - 4, bm->cr.ymax - 3); + +#else /* CONFIG_CHART_ARROWS */ + + /* Draw a box around the chart */ + gfx_rectDraw(bm, bm->cr.xmin, bm->cr.ymin, bm->cr.xmax, bm->cr.ymax); + +#endif /* CONFIG_CHART_ARROWS */ + + //CHECK_WALL(wall_before_raster, WALL_SIZE); + //CHECK_WALL(wall_after_raster, WALL_SIZE); +} + + +/** + * Draw a set of \a curve_cnt connected segments, whose Y coordinates + * are identified by the \a curve_y array and X-coordinates are + * are evenly spaced by one virtual unit. + */ +void chart_drawCurve(Bitmap *bm, const chart_y_t *curve_y, int curve_cnt) +{ + int i; + + gfx_moveTo(bm, gfx_transformX(bm, 0), gfx_transformY(bm, curve_y[0])); + + for (i = 1; i < curve_cnt; i++) + gfx_lineTo(bm, gfx_transformX(bm, i), gfx_transformY(bm, curve_y[i])); + + //CHECK_WALL(wall_before_raster, WALL_SIZE); + //CHECK_WALL(wall_after_raster, WALL_SIZE); +} + + +/** + * Disegna dei dot in corrispondenza delle coppie (dotsx[i];dotsy[i]) + * Se dotsx e' NULL, i punti vengono disegnati ad intervalli regolari. + */ +void chart_drawDots(Bitmap *bm, const chart_x_t *dots_x, const chart_y_t *dots_y, int cnt) +{ + int i; + coord_t x, y; + + for (i = 0; i < cnt; i++) + { + if (dots_x) + x = gfx_transformX(bm, dots_x[i]); + else + x = gfx_transformX(bm, i); + + y = gfx_transformY(bm, dots_y[i]); + + /* Draw tick over the curve */ + gfx_rectFill(bm, + x - TICKS_WIDTH / 2, y - TICKS_HEIGHT / 2, + x + (TICKS_WIDTH + 1) / 2, y + (TICKS_HEIGHT + 1) / 2); + + /* Draw vertical line from the curve to the X-axis */ + //gfx_drawLine(bm, x, y, x, bm->cr.ymax - 1); + } + + //CHECK_WALL(wall_before_raster, WALL_SIZE); + //CHECK_WALL(wall_after_raster, WALL_SIZE); +} + diff --git a/bertos/gfx/charts.h b/bertos/gfx/charts.h new file mode 100644 index 00000000..ce4bd883 --- /dev/null +++ b/bertos/gfx/charts.h @@ -0,0 +1,120 @@ +/** + * \file + * + * + * \brief Simple charts on top of mware/gfx routines (interface). + * + * Configuration: + * - \c CONFIG_CHART_TYPE_X: type for the input dataset of X-coordinates + * - \c CONFIG_CHART_TYPE_Y: type for the input dataset of Y-coordinates + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.5 2006/08/01 12:23:03 bernie + *#* Indentation fix. + *#* + *#* Revision 1.4 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2005/11/27 23:36:18 bernie + *#* Use appconfig.h instead of cfg/config.h. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.7 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.6 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.5 2004/09/14 20:56:39 bernie + *#* Make more generic and adapt to new gfx functions. + *#* + *#* Revision 1.3 2004/08/11 19:39:12 bernie + *#* Use chart_x_t and chart_y_t for the input dataset. + *#* + *#* Revision 1.1 2004/08/04 03:16:30 bernie + *#* Import simple chart drawing code. + *#* + *#*/ +#ifndef GFX_CHARTS_H +#define GFX_CHARTS_H + +#include /* vcoord_t */ +#include /* CONFIG_ stuff */ + +/** + * \name Width/height of the small ticks drawn over the axes + * \{ + */ +#define TICKS_HEIGHT 2 +#define TICKS_WIDTH 2 +/*\}*/ + +/** + * \name Chart frame dimensions + * \{ + */ +#define CHART_BORDERTOP 0 +#define CHART_BORDERBOTTOM 0 +#define CHART_BORDERLEFT 0 +#define CHART_BORDERRIGHT 0 +/*\}*/ + +#ifndef CONFIG_CHART_TYPE_X +#define CONFIG_CHART_TYPE_X vcoord_t +#endif +#ifndef CONFIG_CHART_TYPE_Y +#define CONFIG_CHART_TYPE_Y vcoord_t +#endif + + +typedef CONFIG_CHART_TYPE_X chart_x_t; +typedef CONFIG_CHART_TYPE_Y chart_y_t; + + +/* Public function protos */ +void chart_init(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax); +void chart_setScale(Bitmap *bm, chart_x_t xmin, chart_y_t ymin, chart_x_t xmax, chart_y_t ymax); +void chart_drawAxis(Bitmap *bm); +void chart_drawCurve(Bitmap *bm, const chart_y_t *curve_y, int curve_cnt); +void chart_drawDots(Bitmap *bm, const chart_x_t *dots_x, const chart_y_t *dots_y, int cnt); + +#endif /* GFX_CHARTS_H */ diff --git a/bertos/gfx/fillpoly.cpp b/bertos/gfx/fillpoly.cpp new file mode 100644 index 00000000..36483bf6 --- /dev/null +++ b/bertos/gfx/fillpoly.cpp @@ -0,0 +1,405 @@ +/** + * \file + * + * + * \version $Id$ + * \author Massimiliano Corsini + * + * + * \brief Low-level drawing routines. + * + * This file contains the implementation of the low-level drawing routines + * to draw fill rectangle, fill triangle and so on. + * + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/07/19 13:00:01 bernie + *#* Import into DevLib. + *#* + *#* Revision 1.10 2005/10/15 15:03:43 rasky + *#* Remove per-pixel clipping from line(). + *#* Use clipLine() also for a-scope. + *#* + *#* Revision 1.9 2005/10/14 15:21:32 eldes + *#* Implement the cohen-sutherland clipping on the buffer + *#* + *#* Revision 1.8 2005/09/27 13:28:10 rasky + *#* Add clipping capabilities to line() + *#* Fix off-by-one computation of rectangles of drawing. + *#* + *#* Revision 1.7 2005/09/27 10:41:35 rasky + *#* Import line-drawing routine from Devlib + *#* + *#* Revision 1.6 2005/09/19 16:36:05 chad + *#* Fix doxygen autobrief + *#* + *#* Revision 1.5 2005/07/06 12:51:47 chad + *#* Make the fillRectangle() independent of the order of the points of the rectangle + *#* + *#* Revision 1.4 2005/06/17 15:06:36 chad + *#* Remove conversion warning + *#* + *#* Revision 1.3 2005/06/17 15:04:47 chad + *#* Add line clipping capability + *#* + *#* Revision 1.2 2005/06/15 14:04:43 chad + *#* Add line routine + *#* + *#* Revision 1.1 2005/06/15 13:34:34 chad + *#* Low-level drawing routines + *#* + *#*/ + +// Qt-specific headers +#include + + +/** + * Low-level routine to draw a line. + * + * This routine is based on the Bresenham Line-Drawing Algorithm. + * + * The \a stride represents the width of the image buffer. + * (\a x1, \a y1) are the coordinates of the starting point. + * (\a x2, \a y2) are the coordinates of the ending point. + * + * The line has no anti-alias, and clipping is not performed. The line + * must be fully contained in the buffer (use clipLine() if you need + * to clip it). + */ +void line(unsigned char *buf, + unsigned long bufw, unsigned long bufh, unsigned long stride, + int x1, int y1, int x2, int y2, unsigned char color) +{ + int x, y, e, len, adx, ady, signx, signy; + + 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 */ + assert(y >= 0 && y < static_cast(bufh) && + x >= 0 && x < static_cast(bufw)); + buf[y * stride + x] = color; + 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 */ + assert(y >= 0 && y < static_cast(bufh) && + x >= 0 && x < static_cast(bufw)); + buf[y * stride + x] = color; + y += signy; + e += adx; + if (e >= 0) + { + x += signx; + e -= ady; + } + } + } +} + +/// Helper routine for clipLine(). +static int region(int x, int y, int w, int h) +{ + int code = 0; + + if (y >= h) + code |= 1; // top + else if (y < 0) + code |= 2; // bottom + + if (x >= w) + code |= 4; // right + else if (x < 0) + code |= 8; // left + + return code; +} + +/** + * Low-level routine to draw a line, clipped to the buffer extents. + * + * This routine executes the clipping, and then invokes line(). + * Parameters are the same of line(). The clipping is performed + * using the Cohen-Sutherland algorithm, which is very fast. + */ +void clipLine(unsigned char *buf, + unsigned long w, unsigned long h, unsigned long stride, + int x1, int y1, int x2, int y2, unsigned char color) +{ + int code1 = region(x1, y1, w, h); + int code2 = region(x2, y2, w, h); + + // Loop while there is at least one point outside + while (code1 | code2) + { + // Check for line totally outside + if (code1 & code2) + return; + + int c = code1 ? code1 : code2; + int x, y; + + if (c & 1) // top + { + x = x1 + (x2 - x1) * (h - y1) / (y2 - y1); + y = h - 1; + } + else if (c & 2) //bottom + { + x = x1 + (x2 - x1) * -y1 / (y2 - y1); + y = 0; + } + else if (c & 4) //right + { + y = y1 + (y2 - y1) * (w - x1) / (x2 - x1); + x = w - 1; + } + else //left + { + y = y1 + (y2 - y1) * -x1 / (x2 - x1); + x = 0; + } + + if (c == code1) // first endpoint was clipped + { + x1 = x; y1 = y; + code1 = region(x1, y1, w, h); + } + else //second endpoint was clipped + { + x2 = x; y2 = y; + code2 = region(x2, y2, w, h); + } + } + + line(buf, w, h, stride, x1, y1, x2, y2, color); +} + + +/** + * Low-level routine to draw a filled rectangle. + * + * The triangle is filled with the given color. + * + * The \a stride represents the width of the image buffer. + * The points \a p1 and \a p2 are two opposite corners of the + * rectangle. + */ +void fillRectangle(unsigned char *buf, unsigned long stride, + QPoint p1, QPoint p2, unsigned char color) +{ + QPoint ul; // upper-left corner + QPoint lr; // lower-right corner + + if (p2.x() > p1.x()) + { + ul.setX(p1.x()); + lr.setX(p2.x()); + } + else + { + ul.setX(p2.x()); + lr.setX(p1.x()); + } + + if (p2.y() > p1.y()) + { + ul.setY(p1.y()); + lr.setY(p2.y()); + } + else + { + ul.setY(p2.y()); + lr.setY(p1.y()); + } + + int width = lr.x() - ul.x(); + unsigned long offset = ul.x() + ul.y()*stride; + + for (int h = ul.y(); h < lr.y(); h++) + { + memset(buf+offset, color, width); + offset += stride; + } +} + +/** + * Low-level routines to draw a filled triangle. + * + * The triangle is filled with the given \a color. + * The \a stride represents the width of the image buffer (\a buf). + * + * The routine use fixed-point arithmetic. + */ +void fillTriangle(unsigned char* buf, unsigned long stride, + QPoint v1, QPoint v2, QPoint v3, unsigned char color) +{ + int altezza[3]; + + // Sort by vertical coordinate + if (v1.y() > v2.y()) + std::swap(v1, v2); + if (v1.y() > v3.y()) + std::swap(v1, v3); + if (v2.y() > v3.y()) + std::swap(v2, v3); + + altezza[0] = v3.y() - v1.y(); + if (!altezza[0]) + return; + + int sezioni = 2; + int sezione = 1; + + buf += v1.y() * stride; + + altezza[1] = v2.y() - v1.y(); + altezza[2] = v3.y() - v2.y(); + + int sinistra = v1.x(); + int destra = sinistra; + + if (v1.y() == v2.y()) + { + if (v1.x() < v2.x()) + destra = v2.x(); + else + sinistra = v2.x(); + } + + sinistra <<= 16; + destra <<= 16; + + int stmp1, stmp2, stmp3; + + stmp1 = (altezza[1] << 16) / altezza[0]; + int lunghezza = stmp1 * (v3.x() - v1.x()) + ((v1.x() - v2.x()) << 16); + + if (!lunghezza ) + return; + + int delta_sinistra[2]; + int delta_destra[2]; + + stmp1 = ((v3.x() - v1.x()) << 16) / altezza[0]; + + if (altezza[1]) + stmp2 = ((v2.x() - v1.x()) << 16) / altezza[1]; + if (altezza[2]) + stmp3 = ((v3.x() - v2.x()) << 16) / altezza[2]; + + if (lunghezza < 0) // Il secondo vertice ~J a destra + { + delta_sinistra[0] = stmp1; + delta_sinistra[1] = stmp1; + delta_destra[0] = stmp2; + delta_destra[1] = stmp3; + } + else // Il secondo vertice ~J a sinistra + { + delta_sinistra[0] = stmp2; + delta_sinistra[1] = stmp3; + delta_destra[0] = stmp1; + delta_destra[1] = stmp1; + } + + int len2 = lunghezza; + + do + { + while (altezza [sezione]) + { + unsigned char* curpos = buf + ((sinistra )>> 16); + lunghezza = ((destra ) >> 16) - ((sinistra ) >> 16); + assert(lunghezza >= 0); + if (lunghezza) + memset(curpos, color, lunghezza); + buf += stride; + destra += delta_destra[sezione - 1]; + sinistra += delta_sinistra[sezione - 1]; + altezza[sezione]--; + } + if (len2 < 0) + destra = v2.x() << 16; + else + sinistra = v2.x() << 16; + sezione++; + } while (--sezioni); +} diff --git a/bertos/gfx/font.h b/bertos/gfx/font.h new file mode 100644 index 00000000..b62b0b7c --- /dev/null +++ b/bertos/gfx/font.h @@ -0,0 +1,125 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Stefano Fedrigo + * + * \brief Font 8x6 IBM-PC 8bit + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2006/05/27 22:31:34 bernie + *#* Switch to a smaller default fount. + *#* + *#* Revision 1.5 2006/03/13 02:06:04 bernie + *#* FONT_HAS_GLYPH(): New macro. + *#* + *#* Revision 1.4 2006/02/15 09:10:15 bernie + *#* Implement prop fonts; Fix algo styles. + *#* + *#* Revision 1.3 2006/02/10 12:29:05 bernie + *#* Add multiple font support in bitmaps. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.6 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.5 2005/03/01 23:26:45 bernie + *#* Use new CPU-neutral program-memory API. + *#* + *#* Revision 1.4 2004/12/31 16:42:55 bernie + *#* Sanitize for non-Harvard processors. + *#* + *#* Revision 1.3 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* 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 GFX_FONT_H +#define GFX_FONT_H + +#include /* uint8_t */ +#include /* PROGMEM */ + +typedef struct Font +{ + /** + * Pointer to glyph data. + * + * Data is an array of at most 256 glyphs packed together. + * Raster format must be the same of the bitmap. + */ + const PROGMEM uint8_t *glyph; + + uint8_t width; /**< Pixel width of character cell. */ + uint8_t height; /**< Pixel height of character cell. */ + + uint8_t first; /**< First encoded character in glyph array. */ + uint8_t last; /**< Last encoded character in glyph array (inclusive). */ + + /** Array of glyph offsets in bytes. NULL for fixed-width fonts. */ + const PROGMEM uint16_t *offset; + const PROGMEM uint8_t *widths; + +} Font; + + +/** Return true if glyph \a c is available in \a font. */ +#define FONT_HAS_GLYPH(font, c) ((c) >= (font)->first && (c) <= (font)->last) + + +/** The default font. */ +#define default_font font_luBS14 +extern const struct Font default_font; + +#endif /* GFX_FONT_H */ diff --git a/bertos/gfx/font_10x20.c b/bertos/gfx/font_10x20.c new file mode 100644 index 00000000..35cb9ad0 --- /dev/null +++ b/bertos/gfx/font_10x20.c @@ -0,0 +1,5736 @@ +/* Generated by convbdf on Fri Feb 10 01:05:15 CET 2006. */ +#include "font.h" + +/* Font information: + + name: -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO8859-1 + pixel size: 20 + ascent: 16 + descent: 4 +*/ + +/* Font character bitmap data. */ +static const PROGMEM uint8_t font_10x20_glyphs[] = { + +/* Character (0x00): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | *** *** | + | * * | + | * * | + | | + | | + | * * | + | * * | + | * * | + | | + | | + | * * | + | * * | + | *** *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0073, 0x0080, +0x0040, 0x0080, +0x0040, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0040, 0x0080, +0x0040, 0x0080, +0x0040, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0040, 0x0080, +0x0040, 0x0080, +0x0073, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x01): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | ** | + | **** | + | ****** | + | ******** | + | ******** | + | ****** | + | **** | + | ** | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x003f, 0x0000, +0x007f, 0x0080, +0x007f, 0x0080, +0x003f, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x02): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + | * * * * * | + |* * * * * | + +----------------+ */ +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, +0x0055, 0x0040, +0x00aa, 0x0080, + +/* Character (0x03): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x007e, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x0000, 0x0000, +0x001f, 0x0080, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x04): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | ***** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | ***** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x007c, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0078, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x000f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000f, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x05): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | **** | + | ** ** | + | ** | + | ** | + | ** ** | + | **** | + | | + | ***** | + | ** ** | + | ** ** | + | ***** | + | **** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x003c, 0x0000, +0x0066, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0066, 0x0000, +0x003c, 0x0000, +0x0000, 0x0000, +0x001f, 0x0000, +0x0019, 0x0080, +0x0019, 0x0080, +0x001f, 0x0000, +0x001e, 0x0000, +0x001b, 0x0000, +0x0019, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x06): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | | + | ***** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x003e, 0x0000, +0x0000, 0x0000, +0x000f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000f, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x07): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | **** | + | ** ** | + | ** ** | + | **** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x08): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ******** | + | ** | + | ** | + | | + | ******** | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x09): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | ** ** | + | *** ** | + | ****** | + | ****** | + | ** *** | + | ** ** | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0066, 0x0000, +0x0076, 0x0000, +0x007e, 0x0000, +0x007e, 0x0000, +0x006e, 0x0000, +0x0066, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x0a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x003c, 0x0000, +0x003c, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0000, 0x0000, +0x001f, 0x0080, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x0b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + |***** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x00f8, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x0c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + |***** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00f8, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x0d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ****** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000f, 0x00c0, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x0e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | ****** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x000f, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x0f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + |********** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x00ff, 0x00c0, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x10): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + |********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x00ff, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x11): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + |********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x12): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + |********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x13): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + |********** | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x14): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + |********** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x00c0, + +/* Character (0x15): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | ****** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x000f, 0x00c0, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x16): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + |***** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x00f8, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x17): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + |********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x00ff, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x18): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + |********** | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x00c0, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x19): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +----------------+ */ +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, +0x0008, 0x0000, + +/* Character (0x1a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + |*** | + | *** | + | *** | + | *** | + | | + | | + |********* | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0003, 0x0080, +0x000e, 0x0000, +0x0038, 0x0000, +0x00e0, 0x0000, +0x0038, 0x0000, +0x000e, 0x0000, +0x0003, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x1b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + |*** | + | *** | + | *** | + | *** | + | *** | + | *** | + |*** | + | | + | | + |********* | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00e0, 0x0000, +0x0038, 0x0000, +0x000e, 0x0000, +0x0003, 0x0080, +0x000e, 0x0000, +0x0038, 0x0000, +0x00e0, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x00ff, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x1c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x1d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0006, 0x0000, +0x007f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x0018, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x1e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ***** | + | * * ** ** | + | *** *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000f, 0x0000, +0x0019, 0x0080, +0x0019, 0x0080, +0x0018, 0x0000, +0x0018, 0x0000, +0x007e, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x007c, 0x0000, +0x0056, 0x00c0, +0x0073, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x1f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x20): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x21): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x22): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | * * | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0012, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x23): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000d, 0x0080, +0x000d, 0x0080, +0x000d, 0x0080, +0x003f, 0x00c0, +0x001b, 0x0000, +0x001b, 0x0000, +0x001b, 0x0000, +0x007f, 0x0080, +0x0036, 0x0000, +0x0036, 0x0000, +0x0036, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x24): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ****** | + | ** ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ****** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x003f, 0x0000, +0x006d, 0x0080, +0x006c, 0x0000, +0x006c, 0x0000, +0x006c, 0x0000, +0x003f, 0x0000, +0x000d, 0x0080, +0x000d, 0x0080, +0x000d, 0x0080, +0x006d, 0x0080, +0x003f, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x25): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | *** ** | + | ** ** ** | + | ** **** | + | *** ** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | **** ** | + | ** ** ** | + | ** *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0039, 0x0080, +0x006d, 0x0080, +0x006f, 0x0000, +0x003b, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x001b, 0x0080, +0x001e, 0x00c0, +0x0036, 0x00c0, +0x0033, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x26): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | *** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** | + | *** | + | ** ** | + | ** ** ** | + | ** *** | + | ** ** | + | *** **** | + | **** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001c, 0x0000, +0x0036, 0x0000, +0x0036, 0x0000, +0x0036, 0x0000, +0x003c, 0x0000, +0x0018, 0x0000, +0x0038, 0x0000, +0x006c, 0x0000, +0x0066, 0x00c0, +0x0063, 0x0080, +0x0063, 0x0000, +0x0077, 0x0080, +0x003c, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x27): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | * | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0008, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x28): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0003, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0003, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x29): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0030, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | **** | + | ******** | + | **** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x007f, 0x0080, +0x001e, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x001c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x2f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x0003, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x30): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x31): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | *** | + | **** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001c, 0x0000, +0x003c, 0x0000, +0x006c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x32): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x000e, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x33): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | *** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x000e, 0x0000, +0x0003, 0x0000, +0x0001, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x34): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | * | + | ** | + | *** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0001, 0x0000, +0x0003, 0x0000, +0x0007, 0x0000, +0x000f, 0x0000, +0x001b, 0x0000, +0x0033, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x007f, 0x0080, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x35): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | *** ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x36): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** * | + | ** | + | ** | + | ** *** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x37): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x0003, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x38): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x39): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | *** ** | + | ** | + | ** | + | * ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001d, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0021, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | | + | | + | | + | | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000e, 0x0000, +0x000e, 0x0000, +0x001c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | * | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | * | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0001, 0x0000, +0x0003, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0060, 0x0000, +0x0030, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0003, 0x0000, +0x0001, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | ******** | + | | + | | + | | + | | + | ******** | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | * | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | * | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0020, 0x0000, +0x0030, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0003, 0x0000, +0x0001, 0x0080, +0x0003, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0020, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x3f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0003, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x40): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** **** | + | ** ***** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** **** | + | ** ** | + | ** | + | ** ** | + | ***** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0067, 0x0080, +0x006f, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006f, 0x0000, +0x0066, 0x0000, +0x0060, 0x0000, +0x0031, 0x0080, +0x001f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x41): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x007f, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x42): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ***** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007c, 0x0000, +0x0066, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x0066, 0x0000, +0x007e, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0063, 0x0000, +0x007e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x43): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x44): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007e, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0063, 0x0000, +0x007e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x45): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007e, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x46): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007e, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x47): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | **** * | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0067, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001e, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x48): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x007f, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x49): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000f, 0x00c0, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x0036, 0x0000, +0x001c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ***** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0063, 0x0000, +0x0063, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x007c, 0x0000, +0x0066, 0x0000, +0x0066, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | *** *** | + | *** *** | + | ******** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0073, 0x0080, +0x0073, 0x0080, +0x007f, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | *** ** | + | *** ** | + | **** ** | + | **** ** | + | ** ** ** | + | ** ** ** | + | ** **** | + | ** **** | + | ** *** | + | ** *** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0071, 0x0080, +0x0071, 0x0080, +0x0079, 0x0080, +0x0079, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x0067, 0x0080, +0x0067, 0x0080, +0x0063, 0x0080, +0x0063, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x4f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x50): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007e, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0063, 0x0000, +0x007e, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x51): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** **** | + | ** ** | + | ***** | + | ** | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x006d, 0x0080, +0x0067, 0x0080, +0x0033, 0x0000, +0x001f, 0x0000, +0x0001, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x52): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007e, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0063, 0x0000, +0x007e, 0x0000, +0x0066, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x53): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0030, 0x0000, +0x001e, 0x0000, +0x0003, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x54): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x55): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x56): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | **** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x57): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | *** *** | + | *** *** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x0073, 0x0080, +0x0073, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x58): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | **** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x59): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003f, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x003f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0006, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003f, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x0003, 0x0000, +0x003f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | **** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x5f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x007f, 0x00c0, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x60): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0018, 0x0000, +0x000c, 0x0000, +0x0006, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x61): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ***** | + | ** ** | + | ** | + | ******* | + | ** ** | + | ** ** | + | ** ** | + | ***** * | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001f, 0x0000, +0x0031, 0x0080, +0x0001, 0x0080, +0x003f, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x003e, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x62): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ** *** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0073, 0x0000, +0x006e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x63): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ***** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ***** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001f, 0x0000, +0x0031, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0031, 0x0080, +0x001f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x64): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** ** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | *** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x001d, 0x0080, +0x0033, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001d, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x65): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** ** | + | ***** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x007f, 0x0080, +0x0060, 0x0000, +0x0060, 0x0000, +0x0031, 0x0080, +0x001f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x66): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000f, 0x0000, +0x0019, 0x0080, +0x0019, 0x0080, +0x0018, 0x0000, +0x0018, 0x0000, +0x007e, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x67): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ***** * | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ***** | + | ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003e, 0x0080, +0x0063, 0x0080, +0x0063, 0x0000, +0x0063, 0x0000, +0x0063, 0x0000, +0x003e, 0x0000, +0x0060, 0x0000, +0x003f, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x003f, 0x0000, + +/* Character (0x68): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x69): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x003c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x6a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | ***** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0000, 0x0000, +0x0007, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0031, 0x0080, +0x0031, 0x0080, +0x0031, 0x0080, +0x001f, 0x0000, + +/* Character (0x6b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ***** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0063, 0x0000, +0x0066, 0x0000, +0x006c, 0x0000, +0x0078, 0x0000, +0x007c, 0x0000, +0x0066, 0x0000, +0x0063, 0x0000, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x6c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x007f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x6d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | * ** ** | + | ******** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x005b, 0x0000, +0x007f, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x6e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** *** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x6f): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x70): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** *** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ** *** | + | ** | + | ** | + | ** | + | ** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x006e, 0x0000, +0x0073, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0073, 0x0000, +0x006e, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, +0x0060, 0x0000, + +/* Character (0x71): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | *** ** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | *** ** | + | ** | + | ** | + | ** | + | ** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x001d, 0x0080, +0x0033, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001d, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, +0x0001, 0x0080, + +/* Character (0x72): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** **** | + | *** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x006f, 0x0000, +0x0039, 0x0080, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0030, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x73): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ****** | + | ** ** | + | ** | + | ****** | + | ** | + | ** | + | ** ** | + | ****** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003f, 0x0000, +0x0061, 0x0080, +0x0060, 0x0000, +0x003f, 0x0000, +0x0001, 0x0080, +0x0001, 0x0080, +0x0061, 0x0080, +0x003f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x74): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x007e, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0018, 0x0000, +0x0019, 0x0080, +0x000f, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x75): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | *** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001d, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x76): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x0033, 0x0000, +0x001e, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x77): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ******** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x006d, 0x0080, +0x007f, 0x0080, +0x0033, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x78): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | **** | + | ** | + | ** | + | **** | + | ** ** | + | ** ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x001e, 0x0000, +0x0033, 0x0000, +0x0061, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x79): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | *** ** | + | ** | + | ** ** | + | ** ** | + | **** | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0061, 0x0080, +0x0033, 0x0080, +0x001d, 0x0080, +0x0001, 0x0080, +0x0061, 0x0080, +0x0033, 0x0000, +0x001e, 0x0000, + +/* Character (0x7a): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******* | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x003f, 0x0080, +0x0001, 0x0080, +0x0003, 0x0000, +0x0006, 0x0000, +0x000c, 0x0000, +0x0018, 0x0000, +0x0030, 0x0000, +0x003f, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x7b): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0007, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0078, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0007, 0x0080, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x7c): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x7d): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | **** | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0078, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0007, 0x0080, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x000c, 0x0000, +0x0078, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, + +/* Character (0x7e): + bbw=10, bbh=20, bbx=0, bby=-4, width=10 + +----------------+ + | | + | | + | | + | *** ** | + | ** ** ** | + | ** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ */ +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0039, 0x0080, +0x006d, 0x0080, +0x0067, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +0x0000, 0x0000, +}; + +/* Exported structure definition. */ +Font font_10x20 = { + font_10x20_glyphs, + 10, + 20 +}; diff --git a/bertos/gfx/gfx.h b/bertos/gfx/gfx.h new file mode 100644 index 00000000..a852c54d --- /dev/null +++ b/bertos/gfx/gfx.h @@ -0,0 +1,204 @@ +/** + * \file + * Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/) + * Copyright 1999 Bernardo Innocenti + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief General pourpose graphics routines + */ + +#ifndef GFX_GFX_H +#define GFX_GFX_H + +#include +#include /* CPU_HARVARD */ + +#include /* CONFIG_GFX_* */ + +/** + * \name Known pixel formats for bitmap representation. + * \{ + */ +#define BITMAP_FMT_PLANAR_H_MSB 1 /**< Planar pixels, horizontal bytes, MSB left. */ +#define BITMAP_FMT_PLANAR_V_LSB 2 /**< Planar pixels, vertical bytes, LSB top. */ +/* \} */ + +#if !defined(CONFIG_BITMAP_FMT) || (CONFIG_BITMAP_FMT != BITMAP_FMT_PLANAR_H_MSB && CONFIG_BITMAP_FMT != BITMAP_FMT_PLANAR_V_LSB) + #error CONFIG_BITMAP_FMT must be defined to either BITMAP_FMT_PLANAR_H_LSB or BITMAP_FMT_PLANAR_V_LSB +#endif +#if !defined(CONFIG_GFX_CLIPPING) || (CONFIG_GFX_CLIPPING != 0 && CONFIG_GFX_CLIPPING != 1) + #error CONFIG_GFX_CLIPPING must be defined to either 0 or 1 +#endif +#if !defined(CONFIG_GFX_TEXT) || (CONFIG_GFX_TEXT != 0 && CONFIG_GFX_TEXT != 1) + #error CONFIG_GFX_TEXT must be defined to either 0 or 1 +#endif + +EXTERN_C_BEGIN + +/** Common type for coordinates expressed in pixel units */ +typedef int coord_t; +typedef unsigned int ucoord_t; + +#if CONFIG_GFX_VCOORDS +/** Common type for coordinates expressed in logical units */ +typedef float vcoord_t; +#endif /* CONFIG_GFX_VCOORDS */ + + +/** + * Describe a rectangular area with coordinates expressed in pixels. + * + * The rectangle is represented in terms of its top/left and + * right/bottom borders. + * + * In some cases, rectangles are assumed to obey to the + * following invariants: + * + * xmin <= xmax + * ymin <= ymax + * + * Oddly, the xmin and ymin coordinates are inclusive, while the + * xmax and ymax coordinates are non-inclusive. This design + * decision makes several computations simpler and lets you + * specify empty (0x0) rectangles without breaking the + * invariants. + * + * Computing the size of a rectangle can be done by simply + * subtracting the maximum X or Y coordinate from the minimum + * X or Y coordinate. + */ +typedef struct Rect { coord_t xmin, ymin, xmax, ymax; } Rect; + +/** + * Return the width of a rectangle in pixels. + * + * \note The argument \a r is evaluated twice. + */ +#define RECT_WIDTH(r) ((r)->xmax - (r)->xmin) + +/** + * Return the height of a rectangle in pixels. + * + * \note The argument \a r is evaluated twice. + */ +#define RECT_HEIGHT(r) ((r)->ymax - (r)->ymin) + +/* Fwd decl */ +struct Font; + +/** + * Control structure to draw in a bitmap + * + * \todo For better ortogonality, split this structure into + * an Image and a plain drawing context called Painter. + */ +typedef struct Bitmap +{ + uint8_t *raster; /**< Pointer to byte array to hold the data */ + coord_t width, height; /**< Width/Height in pixels */ + coord_t stride; /**< Bytes per row. */ + coord_t penX, penY; /**< Current pen position MoveTo()/LineTo() */ + +#if CONFIG_GFX_CLIPPING || CONFIG_GFX_VCOORDS + Rect cr; /**< Clip drawing inside this rectangle */ +#endif + +#if CONFIG_GFX_TEXT + const struct Font *font;/**< Current font for text rendering. */ + + /** + * Algorithmic text style flags. + * + * The text rendering routine can apply a few simple transformations + * to the current font in order to generate common styles such as + * bold, italic and underline from plain glyphs. + * + * \see text_style() + */ + uint8_t styles; +#endif /* CONFIG_GFX_TEXT */ + +#if CONFIG_GFX_VCOORDS + /** + * \name Logical coordinate system + * \{ + */ + vcoord_t orgX, orgY; + vcoord_t scaleX, scaleY; + /*\}*/ +#endif /* CONFIG_GFX_VCOORDS */ + +} Bitmap; + +/** + * Hold image pixels. + * + * \todo Use this as Bitmap and change Bitmap to Drawable. + */ +typedef struct Image +{ + const uint8_t *raster; /**< Pointer to byte array to hold the data. */ + coord_t width; /**< Raster width in pixels. */ + coord_t height; /**< Raster height in pixels. */ + coord_t stride; /**< Bytes per row. */ +} Image; + +#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB + /** + * Compute the size in bytes of a raster suitable for + * holding a bitmap of \a width x \a height pixels. + */ + #define RAST_SIZE(width, height) ( ((width) + 7 / 8) * (height) ) + +#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB + /** + * Compute the size in bytes of a raster suitable for + * holding a bitmap of \a width x \a height pixels. + */ + #define RAST_SIZE(width, height) ( (width) * (((height) + 7) / 8) ) +#else + #error Unknown value of CONFIG_BITMAP_FMT +#endif /* CONFIG_BITMAP_FMT */ + +/* Function prototypes */ +void gfx_bitmapInit (Bitmap *bm, uint8_t *raster, coord_t w, coord_t h); +void gfx_bitmapClear(Bitmap *bm); +void gfx_blit (Bitmap *dst, const Rect *rect, const Bitmap *src, coord_t srcx, coord_t srcy); +void gfx_blitRaster (Bitmap *dst, coord_t dx, coord_t dy, const uint8_t *raster, coord_t w, coord_t h, coord_t stride); +void gfx_blitImage (Bitmap *dst, coord_t dx, coord_t dy, const Image *image); +void gfx_line (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); +void gfx_rectDraw (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); +void gfx_rectFillC (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t color); +void gfx_rectFill (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); +void gfx_rectClear (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); +void gfx_moveTo (Bitmap *bm, coord_t x, coord_t y); +void gfx_lineTo (Bitmap *bm, coord_t x, coord_t y); +void gfx_setClipRect(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax); + +#if CPU_HARVARD + #include + void gfx_blit_P(Bitmap *bm, const pgm_uint8_t *raster); +#endif + +#if CONFIG_GFX_TEXT +INLINE void gfx_setFont(Bitmap *bm, const struct Font *font) +{ + bm->font = font; +} +#endif + +#if CONFIG_GFX_VCOORDS +void gfx_setViewRect(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2); +coord_t gfx_transformX(Bitmap *bm, vcoord_t x); +coord_t gfx_transformY(Bitmap *bm, vcoord_t y); +void gfx_vline(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2); +#endif /* CONFIG_GFX_VCOORDS */ + +EXTERN_C_END + +#endif /* GFX_GFX_H */ diff --git a/bertos/gfx/gfx_p.h b/bertos/gfx/gfx_p.h new file mode 100644 index 00000000..c2f10b49 --- /dev/null +++ b/bertos/gfx/gfx_p.h @@ -0,0 +1,140 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Graphics private header. + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2006/05/27 17:17:34 bernie + *#* Optimize away divisions in RAST_ADDR/MASK macros. + *#* + *#* Revision 1.5 2006/05/25 23:35:40 bernie + *#* Cleanup. + *#* + *#* Revision 1.4 2006/03/22 09:50:37 bernie + *#* Use the same format for fonts and rasters. + *#* + *#* Revision 1.3 2006/02/15 09:10:15 bernie + *#* Implement prop fonts; Fix algo styles. + *#* + *#* Revision 1.2 2006/02/10 12:28:33 bernie + *#* Add font support in bitmaps; Make bitmap formats public. + *#* + *#* Revision 1.1 2006/01/26 00:32:49 bernie + *#* Graphics private header. + *#* + *#*/ + +#ifndef GFX_GFX_P_H +#define GFX_GFX_P_H + +#include + +#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB + + /* We use ucoord_t to let the compiler optimize away the division/modulo. */ + #define RAST_ADDR(raster, x, y, stride) \ + ((raster) + (ucoord_t)(y) * (ucoord_t)(stride) + (ucoord_t)(x) / 8) + #define RAST_MASK(raster, x, y) \ + (1 << (7 - (ucoord_t)(x) % 8)) + +#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB + + /* We use ucoord_t to let the compiler optimize away the division/modulo. */ + #define RAST_ADDR(raster, x, y, stride) \ + ((raster) + ((ucoord_t)(y) / 8) * (ucoord_t)(stride) + (ucoord_t)(x)) + #define RAST_MASK(raster, x, y) \ + (1 << ((ucoord_t)(y) % 8)) + +#else + #error Unknown value of CONFIG_BITMAP_FMT +#endif /* CONFIG_BITMAP_FMT */ + +#define BM_ADDR(bm, x, y) RAST_ADDR((bm)->raster, (x), (y), (bm)->stride) +#define BM_MASK(bm, x, y) RAST_MASK((bm)->raster, (x), (y)) + +/** + * Plot a pixel in bitmap \a bm. + * + * \note bm is evaluated twice. + * \see BM_CLEAR BM_DRAWPIXEL + */ +#define BM_PLOT(bm, x, y) \ + ( *BM_ADDR(bm, x, y) |= BM_MASK(bm, x, y) ) + +/** + * Clear a pixel in bitmap \a bm. + * + * \note bm is evaluated twice. + * \see BM_PLOT BM_DRAWPIXEL + */ +#define BM_CLEAR(bm, x, y) \ + ( *BM_ADDR(bm, x, y) &= ~BM_MASK(bm, x, y) ) + +/** + * Set a pixel in bitmap \a bm to the specified color. + * + * \note bm is evaluated twice. + * \note This macro is somewhat slower than BM_PLOT and BM_CLEAR. + * \see BM_PLOT BM_CLEAR + */ +#define BM_DRAWPIXEL(bm, x, y, fg_pen) \ + do { \ + uint8_t *p = BM_ADDR(bm, x, y); \ + uint8_t mask = BM_MASK(bm, x, y); \ + *p = (*p & ~mask) | ((fg_pen) ? mask : 0); \ + } while (0) + +/** + * Get the value of the pixel in bitmap \a bm. + * + * \return The returned value is either 0 or 1. + * + * \note bm is evaluated twice. + * \see BM_DRAWPIXEL + */ +#define BM_READPIXEL(bm, x, y) \ + ( *BM_ADDR(bm, x, y) & BM_MASK(bm, x, y) ? 1 : 0 ) + +#define RAST_READPIXEL(raster, x, y, stride) \ + ( *RAST_ADDR(raster, x, y, stride) & RAST_MASK(raster, x, y) ? 1 : 0 ) + +#endif /* GFX_GFX_P_H */ diff --git a/bertos/gfx/line.c b/bertos/gfx/line.c new file mode 100644 index 00000000..f3909b15 --- /dev/null +++ b/bertos/gfx/line.c @@ -0,0 +1,408 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief Line drawing graphics routines + */ + +#include "gfx.h" +#include "gfx_p.h" + +#include /* ASSERT() */ +#include /* SWAP() */ +#include /* CONFIG_GFX_CLIPPING */ + +/* Configuration sanity checks */ +#if !defined(CONFIG_GFX_CLIPPING) || (CONFIG_GFX_CLIPPING != 0 && CONFIG_GFX_CLIPPING != 1) + #error CONFIG_GFX_CLIPPING must be defined to either 0 or 1 +#endif +#if !defined(CONFIG_GFX_VCOORDS) || (CONFIG_GFX_VCOORDS != 0 && CONFIG_GFX_VCOORDS != 1) + #error CONFIG_GFX_VCOORDS must be defined to either 0 or 1 +#endif + +/** + * Draw a sloped line without performing clipping. + * + * Parameters are the same of gfx_line(). + * This routine is based on the Bresenham Line-Drawing Algorithm. + * + * \note Passing coordinates outside the bitmap boundaries will + * result in memory trashing. + * + * \todo Optimize for vertical and horiziontal lines. + * + * \sa gfx_line() + */ +static void gfx_lineUnclipped(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ + int x, y, e, len, adx, ady, signx, signy; + + 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 */ + ASSERT((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 */ + ASSERT ((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; + } + } + } +} + +#if CONFIG_GFX_CLIPPING + +/// Helper routine for gfx_line(). +static int gfx_findRegion(int x, int y, Rect *cr) +{ + int code = 0; + + if (y >= cr->ymax) + code |= 1; /* below */ + else if (y < cr->ymin) + code |= 2; /* above */ + + if (x >= cr->xmax) + code |= 4; /* right */ + else if (x < cr->xmin) + code |= 8; /* left */ + + return code; +} + +#endif /* CONFIG_CLIPPING */ + +/** + * Draw a sloped line segment. + * + * Draw a sloped line segment identified by the provided + * start and end coordinates on the bitmap \a bm. + * + * The line endpoints are clipped inside the current bitmap + * clipping rectangle using the Cohen-Sutherland algorithm, + * which is very fast. + * + * \note The point at coordinates \a x2 \a y2 is not drawn. + * + * \note This function does \b not update the current pen position. + * + * \todo Compute updated Bresenham error term. + */ +void gfx_line(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ +#if CONFIG_GFX_CLIPPING + int clip1 = gfx_findRegion(x1, y1, &bm->cr); + int clip2 = gfx_findRegion(x2, y2, &bm->cr); + + /* Loop while there is at least one point outside */ + while (clip1 | clip2) + { + /* Check for line totally outside */ + if (clip1 & clip2) + return; + + int c = clip1 ? clip1 : clip2; + int x, y; + + if (c & 1) /* Below */ + { + x = x1 + (x2 - x1) * (bm->cr.ymax - y1) / (y2 - y1); + y = bm->cr.ymax - 1; + } + else if (c & 2) /* Above */ + { + x = x1 + (x2 - x1) * (bm->cr.ymin - y1) / (y2 - y1); + y = bm->cr.ymin; + } + else if (c & 4) /* Right */ + { + y = y1 + (y2 - y1) * (bm->cr.xmax - x1) / (x2 - x1); + x = bm->cr.xmax - 1; + } + else /* Left */ + { + y = y1 + (y2 - y1) * (bm->cr.xmin - x1) / (x2 - x1); + x = bm->cr.xmin; + } + + if (c == clip1) /* First endpoint was clipped */ + { + // TODO: adjust Bresenham error term + //coord_t clipdx = ABS(x - x1); + //coord_t clipdy = ABS(y - y1); + //e += (clipdy * e2) + ((clipdx - clipdy) * e1); + + x1 = x; + y1 = y; + clip1 = gfx_findRegion(x1, y1, &bm->cr); + } + else /* Second endpoint was clipped */ + { + x2 = x; + y2 = y; + clip2 = gfx_findRegion(x2, y2, &bm->cr); + } + } +#endif /* CONFIG_GFX_CLIPPING */ + + gfx_lineUnclipped(bm, x1, y1, x2, y2); +} + +/** + * Move the current pen position to the specified coordinates. + * + * The pen position is used for drawing operations such as + * gfx_lineTo(), which can be used to draw polygons. + */ +void gfx_moveTo(Bitmap *bm, coord_t x, coord_t y) +{ + bm->penX = x; + bm->penY = y; +} + +/** + * Draw a line from the current pen position to the new coordinates. + * + * \note This function moves the current pen position to the + * new coordinates. + * + * \sa gfx_line() + */ +void gfx_lineTo(Bitmap *bm, coord_t x, coord_t y) +{ + gfx_line(bm, bm->penX, bm->penY, x, y); + gfx_moveTo(bm, x, y); +} + + +/** + * Draw the perimeter of an hollow rectangle. + * + * \note The bottom-right corner of the rectangle is drawn at (x2-1;y2-1). + * \note This function does \b not update the current pen position. + */ +void gfx_rectDraw(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ + /* Sort coords (needed for correct bottom-right semantics) */ + if (x1 > x2) SWAP(x1, x2); + if (y1 > y2) SWAP(y1, y2); + + /* Draw rectangle */ + gfx_line(bm, x1, y1, x2-1, y1); + gfx_line(bm, x2-1, y1, x2-1, y2-1); + gfx_line(bm, x2-1, y2-1, x1, y2-1); + gfx_line(bm, x1, y2-1, x1, y1); +} + + +/** + * Fill a rectangular area with \a color. + * + * \note The bottom-right border of the rectangle is not drawn. + * + * \note This function does \b not update the current pen position. + */ +void gfx_rectFillC(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t color) +{ + coord_t x, y; + + /* Sort coords */ + if (x1 > x2) SWAP(x1, x2); + if (y1 > y2) SWAP(y1, y2); + +#if CONFIG_GFX_CLIPPING + /* Clip rect to bitmap clip region */ + if (x1 < bm->cr.xmin) x1 = bm->cr.xmin; + if (x2 < bm->cr.xmin) x2 = bm->cr.xmin; + if (x1 > bm->cr.xmax) x1 = bm->cr.xmax; + if (x2 > bm->cr.xmax) x2 = bm->cr.xmax; + if (y1 < bm->cr.ymin) y1 = bm->cr.ymin; + if (y2 < bm->cr.ymin) y2 = bm->cr.ymin; + if (y1 > bm->cr.ymax) y1 = bm->cr.ymax; + if (y2 > bm->cr.ymax) y2 = bm->cr.ymax; +#endif /* CONFIG_GFX_CLIPPING */ + + /* NOTE: Code paths are duplicated for efficiency */ + if (color) /* fill */ + { + for (x = x1; x < x2; x++) + for (y = y1; y < y2; y++) + BM_PLOT(bm, x, y); + } + else /* clear */ + { + for (x = x1; x < x2; x++) + for (y = y1; y < y2; y++) + BM_CLEAR(bm, x, y); + } +} + + +/** + * Draw a filled rectangle. + * + * \note The bottom-right border of the rectangle is not drawn. + * + * \note This function does \b not update the current pen position. + */ +void gfx_rectFill(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ + gfx_rectFillC(bm, x1, y1, x2, y2, 0xFF); +} + + +/** + * Clear a rectangular area. + * + * \note The bottom-right border of the rectangle is not cleared. + * + * \note This function does \b not update the current pen position. + */ +void gfx_rectClear(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ + gfx_rectFillC(bm, x1, y1, x2, y2, 0x00); +} + + +#if CONFIG_GFX_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 - 1) / (vcoord_t)(x2 - x1); + bm->scaleY = (vcoord_t)(bm->cr.ymax - bm->cr.ymin - 1) / (vcoord_t)(y2 - y1); + +/* 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_vline(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2) +{ + gfx_line(bm, + gfx_transformX(bm, x1), gfx_transformY(bm, y1), + gfx_transformY(bm, x2), gfx_transformY(bm, y2)); +} +#endif /* CONFIG_GFX_VCOORDS */ diff --git a/bertos/gfx/text.c b/bertos/gfx/text.c new file mode 100644 index 00000000..c37e871e --- /dev/null +++ b/bertos/gfx/text.c @@ -0,0 +1,418 @@ +/** + * \file + * + * + * \brief Text graphic routines + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.13 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.12 2006/05/25 23:35:22 bernie + *#* Implement correct and faster clipping for algo text. + *#* + *#* Revision 1.11 2006/05/15 07:21:06 bernie + *#* Doxygen fix. + *#* + *#* Revision 1.10 2006/04/27 05:39:23 bernie + *#* Enhance text rendering to arbitrary x,y coords. + *#* + *#* Revision 1.9 2006/04/11 00:08:24 bernie + *#* text_offset(): New function, but I'm not quite confident with the design. + *#* + *#* Revision 1.8 2006/03/22 09:50:37 bernie + *#* Use the same format for fonts and rasters. + *#* + *#* Revision 1.7 2006/03/20 17:51:55 bernie + *#* Cleanups. + *#* + *#* Revision 1.6 2006/03/13 02:05:54 bernie + *#* Mark slow paths as UNLIKELY. + *#* + *#* Revision 1.5 2006/03/07 22:18:04 bernie + *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute. + *#* + *#* Revision 1.4 2006/02/15 09:10:15 bernie + *#* Implement prop fonts; Fix algo styles. + *#* + *#* Revision 1.3 2006/02/10 12:31:55 bernie + *#* Add multiple font support in bitmaps. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.13 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.12 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.11 2005/01/20 18:46:31 aleph + *#* Fix progmem includes. + *#* + *#* Revision 1.10 2005/01/08 09:20:12 bernie + *#* Really make it work on both architectures. + *#* + *#* Revision 1.9 2004/12/31 16:44:29 bernie + *#* Sanitize for non-Harvard processors. + *#* + *#* Revision 1.8 2004/11/16 21:16:28 bernie + *#* Update to new naming scheme in mware/gfx.c. + *#* + *#* Revision 1.7 2004/09/20 03:28:28 bernie + *#* Fix header. + *#* + *#* Revision 1.6 2004/09/14 20:57:15 bernie + *#* Use debug.h instead of kdebug.h. + *#* + *#* Revision 1.5 2004/09/06 21:51:26 bernie + *#* Extend interface to allow any algorithmic style. + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* 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 +#include +#include +#include + +#include // FIXME: BM_DRAWPIXEL + +#include + + +/** + * ANSI escape sequences flag: true for ESC state on. + * + * \todo Move to Bitmap.flags. + */ +static bool ansi_mode = false; + +/** + * Move (imaginary) cursor to coordinates specified. + */ +void text_setCoord(struct Bitmap *bm, int x, int y) +{ + bm->penX = x; + bm->penY = y; +} + + +/** + * 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 / bm->font->width); + ASSERT(row >= 0); + ASSERT(row < bm->height / bm->font->height); + + text_setCoord(bm, col * bm->font->width, row * bm->font->height); +} + + +/** + * Render char \a c on Bitmap \a bm. + */ +static int text_putglyph(char c, struct Bitmap *bm) +{ + const uint8_t * PROGMEM glyph; /* font is in progmem */ + uint8_t glyph_width, glyph_height, glyph_height_bytes; + unsigned char index = (unsigned char)c; + + /* Check for out of range char and replace with '?' or first char in font. */ + if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index))) + { + kprintf("Illegal char '%c' (0x%02x)\n", index, index); + if (FONT_HAS_GLYPH(bm->font, '?')) + index = '?'; + else + index = bm->font->first; + } + + /* Make character relative to font start */ + index -= bm->font->first; + + glyph_height = bm->font->height; + // FIXME: for vertical fonts only + glyph_height_bytes = (glyph_height + 7) / 8; + + if (bm->font->offset) + { + /* Proportional font */ + glyph_width = bm->font->widths[index]; /* TODO: optimize away */ + glyph = bm->font->glyph + bm->font->offset[index]; + } + else + { + /* + * Fixed-width font: compute the first column of pixels + * of the selected glyph using the character code to index + * the glyph array. + */ + glyph_width = bm->font->width; + + //For horizontal fonts + //glyph = bm->font->glyph + index * (((glyph_width + 7) / 8) * glyph_height); + glyph = bm->font->glyph + index * glyph_height_bytes * glyph_width; + } + + /* Slow path for styled glyphs */ + if (UNLIKELY(bm->styles)) + { + uint8_t styles = bm->styles; + uint8_t prev_dots = 0, italic_prev_dots = 0; + uint8_t dots; + uint8_t row, col, row_bit; + + /* + * To avoid repeating clipping and other expensive computations, + * we cluster calls to gfx_blitRaster() using a small buffer. + */ + #define CONFIG_TEXT_RENDER_OPTIMIZE 1 + #if CONFIG_TEXT_RENDER_OPTIMIZE + #define RENDER_BUF_WIDTH 12 + #define RENDER_BUF_HEIGHT 8 + uint8_t render_buf[RAST_SIZE(RENDER_BUF_WIDTH, RENDER_BUF_HEIGHT)]; + uint8_t render_xpos = 0; + #endif + + /* This style alone could be handled by the fast path too */ + if (bm->styles & STYLEF_CONDENSED) + --glyph_width; + + if (bm->styles & STYLEF_EXPANDED) + glyph_width *= 2; + + for (row = 0, row_bit = 0; row < glyph_height_bytes; ++row, row_bit += 8) + { + /* For each dot column in the glyph... */ + for (col = 0; col < glyph_width; ++col) + { + uint8_t src_col = col; + + /* Expanded style: advances only once every two columns. */ + if (styles & STYLEF_EXPANDED) + src_col /= 2; + + /* Fetch a column of dots from glyph. */ + dots = PGM_READ_CHAR(RAST_ADDR(glyph, src_col, row_bit, glyph_width)); + + /* Italic: get lower 4 dots from previous column */ + if (styles & STYLEF_ITALIC) + { + uint8_t new_dots = dots; + dots = (dots & 0xF0) | italic_prev_dots; + italic_prev_dots = new_dots & 0x0F; + } + + /* Bold: "or" pixels with the previous column */ + if (styles & STYLEF_BOLD) + { + uint8_t new_dots = dots; + dots |= prev_dots; + prev_dots = new_dots; + } + + /* Underlined: turn on base pixel */ + if ((styles & STYLEF_UNDERLINE) + && (row == glyph_height_bytes - 1)) + dots |= (1 << (glyph_height - row_bit - 1)); + + /* Inverted: invert pixels */ + if (styles & STYLEF_INVERT) + dots = ~dots; + + /* Output dots */ + #if CONFIG_TEXT_RENDER_OPTIMIZE + render_buf[render_xpos++] = dots; + if (render_xpos == RENDER_BUF_WIDTH) + { + gfx_blitRaster(bm, bm->penX + col - render_xpos + 1, bm->penY + row_bit, + render_buf, render_xpos, + MIN((uint8_t)RENDER_BUF_HEIGHT, (uint8_t)(glyph_height - row_bit)), + RENDER_BUF_WIDTH); + render_xpos = 0; + } + #else + gfx_blitRaster(bm, bm->penX + col, bm->penY + row_bit, + &dots, 1, MIN((uint8_t)8, glyph_height - row_bit), 1); + #endif + } + + #if CONFIG_TEXT_RENDER_OPTIMIZE + /* Flush out rest of render buffer */ + if (render_xpos != 0) + { + gfx_blitRaster(bm, bm->penX + col - render_xpos, bm->penY + row_bit, + render_buf, render_xpos, + MIN((uint8_t)RENDER_BUF_HEIGHT, (uint8_t)(glyph_height - row_bit)), + RENDER_BUF_WIDTH); + render_xpos = 0; + } + #endif + } + } + else + { + /* No style: fast vanilla copy of glyph to bitmap */ + gfx_blitRaster(bm, bm->penX, bm->penY, glyph, glyph_width, glyph_height, glyph_width); + } + + /* Update current pen position */ + bm->penX += glyph_width; + + 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 (UNLIKELY(ansi_mode)) + { + switch (c) + { + case ANSI_ESC_CLEARSCREEN: + gfx_bitmapClear(bm); + bm->penX = 0; + bm->penY = 0; + text_style(bm, 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 + bm->font->height < bm->height) + { + bm->penY += bm->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); +} + + +void text_clearLine(struct Bitmap *bm, int line) +{ + gfx_rectClear(bm, 0, line * bm->font->height, bm->width, (line + 1) * bm->font->height); +} + + +/** + * Set/clear algorithmic font style bits. + * + * \param bm Pointer to Bitmap to affect. + * \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 text_style(bm, STYLEF_BOLD, STYLEF_BOLD); \endcode + * + * Turn off bold and turn on italic, leave others as they are + * \code text_style(bm, STYLEF_ITALIC, STYLEF_BOLD | STYLEF_ITALIC); \endcode + * + * Query current style without chaning it + * \code style = text_style(bm, 0, 0); \endcode + * + * Reset all styles (plain text) + * \code text_style(bm, 0, STYLE_MASK); \endcode + */ +uint8_t text_style(struct Bitmap *bm, uint8_t flags, uint8_t mask) +{ + uint8_t old = bm->styles; + bm->styles = (bm->styles & ~mask) | flags; + return old; +} diff --git a/bertos/gfx/text.h b/bertos/gfx/text.h new file mode 100644 index 00000000..59f65ea0 --- /dev/null +++ b/bertos/gfx/text.h @@ -0,0 +1,118 @@ +/** + * \file + * + * + * \brief Text graphic routines (interface) + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * \version $Id$ + */ + +#ifndef GFX_TEXT_H +#define GFX_TEXT_H + +#include +#include /* BV() */ +#include /* CPU_HARVARD */ +#include /* coord_t */ + +#include + +/** + * \name Style flags + * \see text_style() + * \{ + */ +#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) /* +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, uint16_t mode, const char * PROGMEM fmt, ...) FORMAT(__printf__, 5, 6); +int text_vwidthf_P(struct Bitmap *bm, const char * PROGMEM fmt, va_list ap); +int text_widthf_P(struct Bitmap *bm, const char * PROGMEM fmt, ...); +#endif /* CPU_HARVARD */ + +#endif /* GFX_TEXT_H */ diff --git a/bertos/gfx/text_format.c b/bertos/gfx/text_format.c new file mode 100644 index 00000000..7c204725 --- /dev/null +++ b/bertos/gfx/text_format.c @@ -0,0 +1,360 @@ +/** + * \file + * + * + * \brief printf-family routines for text output + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.10 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.9 2006/04/27 05:39:24 bernie + *#* Enhance text rendering to arbitrary x,y coords. + *#* + *#* Revision 1.8 2006/03/22 09:50:11 bernie + *#* Don't use C99 stuff. + *#* + *#* Revision 1.7 2006/03/20 17:51:55 bernie + *#* Cleanups. + *#* + *#* Revision 1.6 2006/03/13 02:05:54 bernie + *#* Mark slow paths as UNLIKELY. + *#* + *#* Revision 1.5 2006/03/07 22:18:04 bernie + *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute. + *#* + *#* Revision 1.4 2006/02/10 12:31:33 bernie + *#* Add multiple font support in bitmaps. + *#* + *#* Revision 1.3 2005/11/27 23:31:58 bernie + *#* Reorder includes. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* + *#* Revision 1.1 2005/11/04 18:11:35 bernie + *#* Move graphics stuff from mware/ to gfx/. + *#* + *#* Revision 1.10 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.9 2004/12/31 17:47:45 bernie + *#* Rename UNUSED() to UNUSED_ARG(). + *#* + *#* Revision 1.8 2004/11/16 21:16:56 bernie + *#* Update to new naming scheme in mware/gfx.c. + *#* + *#* Revision 1.7 2004/10/03 19:05:04 bernie + *#* text_widthf(), text_vwidthf(): New functions. + *#* + *#* Revision 1.6 2004/09/14 20:59:04 bernie + *#* text_xprintf(): Support all styles; Pixel-wise text centering. + *#* + *#* Revision 1.5 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.4 2004/08/05 18:46:44 bernie + *#* Documentation improvements. + *#* + *#* Revision 1.3 2004/08/03 15:57:18 aleph + *#* Add include to fix warning for vsprintf() + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* 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 /* _formatted_write() */ +#include +#include + +#include /* vsprintf() */ +#include +#include /* strlen() */ + +/** + * Render string \a str in Bitmap \a bm at current cursor position + * + * \note Text formatting functions are also available with an _P suffix + * accepting the source string from program memory. This feature + * is only available (and useful) on Harvard microprocessors such + * as the AVR. + * + * \see text_putchar() + */ +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; +} + + +/** + * vprintf()-like formatter to render text in a Bitmap. + * + * Perform vprintf()-like formatting on the \a fmt format string using the + * variable-argument list \a ap. + * Render the resulting string in Bitmap \a bm starting at the current + * cursor position. + * + * \see text_puts() text_putchar() text_printf() + */ +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); +} + +/** + * printf()-like formatter to render text in a Bitmap. + * + * Perform printf()-like formatting on the \a fmt format string. + * Render the resulting string in Bitmap \a bm starting at the + * current cursor position. + * + * \see text_puts() text_putchar() text_vprintf() + */ +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; +} + +/** + * Render text with vprintf()-like formatting at a specified pixel position. + * + * \see text_xyprintf() + */ +int PGM_FUNC(text_xyvprintf)(struct Bitmap *bm, + coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, va_list ap) +{ + int len; + uint8_t oldstyle = 0; + + text_setCoord(bm, x, y); + + if (style & STYLEF_MASK) + oldstyle = text_style(bm, style, STYLEF_MASK); + + if (style & (TEXT_CENTER | TEXT_RIGHT)) + { + uint8_t pad = bm->width - PGM_FUNC(text_vwidthf)(bm, fmt, ap); + + if (style & TEXT_CENTER) + pad /= 2; + + if (style & TEXT_FILL) + gfx_rectFillC(bm, 0, y, pad, y + bm->font->height, + (style & STYLEF_INVERT) ? 0xFF : 0x00); + + text_setCoord(bm, pad, y); + } + + len = PGM_FUNC(text_vprintf)(bm, fmt, ap); + + if (style & TEXT_FILL) + gfx_rectFillC(bm, bm->penX, y, bm->width, y + bm->font->height, + (style & STYLEF_INVERT) ? 0xFF : 0x00); + + /* Restore old style */ + if (style & STYLEF_MASK) + text_style(bm, oldstyle, STYLEF_MASK); + + return len; +} + + +/** + * Render text with printf()-like formatting at a specified pixel position. + * + * \param bm Bitmap where to render the text + * \param x [pixels] Initial X coordinate of text. + * \param y [pixels] Coordinate of top border of text. + * \param style Formatting style to use. In addition to any STYLEF_ + * flag, it can be TEXT_NORMAL, TEXT_FILL, TEXT_INVERT or + * TEXT_RIGHT, or a combination of these flags ORed together. + * \param fmt String possibly containing printf() formatting commands. + * + * \see text_puts() text_putchar() text_printf() text_vprintf() + * \see text_moveTo() text_style() + */ +int PGM_FUNC(text_xyprintf)(struct Bitmap *bm, + coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, ...) +{ + int len; + va_list ap; + + va_start(ap, fmt); + len = PGM_FUNC(text_xyvprintf)(bm, x, y, style, fmt, ap); + va_end(ap); + + return len; +} + + +/** + * Render text with printf()-like formatting at a specified row/column position. + * + * \see text_xyprintf() + */ +int PGM_FUNC(text_xprintf)(struct Bitmap *bm, + uint8_t row, uint8_t col, uint16_t style, const char * PGM_ATTR fmt, ...) +{ + int len; + va_list ap; + + va_start(ap, fmt); + len = PGM_FUNC(text_xyvprintf)( + bm, col * bm->font->width, row * bm->font->height, + style, fmt, ap); + va_end(ap); + + return len; +} + + +struct TextWidthData +{ + Bitmap *bitmap; + coord_t width; +}; + +/** + * Compute width in pixels of a character. + * + * Compute the on screen width of a character, taking the + * current style and font into account. + * + * The width is accumulated in the WidthData structure + * passed as second argument. + * + * This is a formatted_write() callback used by text_vwidthf() + * to compute the length of a formatted string. + */ +static int text_charWidth(int c, struct TextWidthData *twd) +{ + unsigned char index = (unsigned char)c; + Bitmap *bm = twd->bitmap; + coord_t glyph_width; + + + if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index))) + { + if (!FONT_HAS_GLYPH(bm->font, '?')) + index = '?'; + else + index = bm->font->first; + } + + /* Make character relative to font start */ + index -= bm->font->first; + + if (bm->font->offset) + /* Proportional font */ + glyph_width = bm->font->widths[index]; /* TODO: optimize away */ + else + /* Fixed width font */ + glyph_width = bm->font->width; + + if (bm->styles & STYLEF_CONDENSED) + --glyph_width; + + if (bm->styles & STYLEF_EXPANDED) + glyph_width *= 2; + + twd->width += glyph_width; + + return c; +} + +/** + * Return the width in pixels of a vprintf()-formatted string. + */ +int PGM_FUNC(text_vwidthf)( + UNUSED_ARG(struct Bitmap *, bm), + const char * PGM_ATTR fmt, + va_list ap) +{ + /* Fixed font with no styles affecting the width? */ + if (!bm->font->offset && !(bm->styles & (STYLEF_CONDENSED | STYLEF_EXPANDED))) + return PGM_FUNC(vsprintf)(NULL, fmt, ap) * bm->font->width; + else + { + struct TextWidthData twd; + twd.bitmap = bm; + twd.width = 0; + _formatted_write(fmt, (void (*)(char, void *))text_charWidth, &twd, ap); + return twd.width; + } +} + + +/** + * Return the width in pixels of a printf()-formatted string. + */ +int PGM_FUNC(text_widthf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...) +{ + int width; + + va_list ap; + va_start(ap, fmt); + width = PGM_FUNC(text_vwidthf)(bm, fmt, ap); + va_end(ap); + + return width; +} diff --git a/bertos/gfx/win.c b/bertos/gfx/win.c new file mode 100644 index 00000000..4925ace6 --- /dev/null +++ b/bertos/gfx/win.c @@ -0,0 +1,232 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Very simple hierarchical windowing system. + * + * All functions in this module are to be intended as methods + * of the Window class. Please see its documentation + * for a module-wise introduction. + * + * \see struct Window + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/08/01 17:26:04 batt + *#* Update docs. + *#* + *#* Revision 1.1 2006/08/01 15:43:01 batt + *#* Add in board_kd current edited channel visualization. + *#* + *#* Revision 1.4 2006/07/19 12:56:26 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2006/02/10 12:25:41 bernie + *#* Add missing header. + *#* + *#* Revision 1.2 2006/01/26 00:36:48 bernie + *#* Const correctness for some new functions. + *#* + *#* Revision 1.1 2006/01/23 23:14:29 bernie + *#* Implement simple, but impressive windowing system. + *#* + *#*/ + +#include "win.h" +#include + +/** + * Map the contents of all child-windows into the bitmap of \a w. + * + * \note Recursively drawing children into their parent + * effectively damages the parent buffer. + */ +void win_compose(Window *w) +{ + Window *child; + + /* + * Walk over all children, in back to front order and tell them + * to compose into us. + */ + REVERSE_FOREACH_NODE(child, &w->children) + { + /* Recursively compose child first. */ + win_compose(child); + + /* Draw child into our bitmap. */ + if (w->bitmap) + gfx_blit(w->bitmap, &child->geom, child->bitmap, 0, 0); + } +} + +/** + * Map window \a w into \a parent. + * + * The new window becomes the topmost window. + * + * \note Opening a window twice is illegal. + * + * \see win_close() + */ +void win_open(Window *w, Window *parent) +{ + ASSERT(!w->parent); + w->parent = parent; + ADDHEAD(&parent->children, &w->link); +} + +/** + * Detach window from its parent. + * + * Closing a window causes it to become orphan of its + * parent. Its content will no longer appear in its + * parent after the next refresh cycle. + * + * \note Closing a window that has not been previously + * opened is illegal. + * + * \see win_open() + */ +void win_close(Window *w) +{ + ASSERT(w->parent); + REMOVE(&w->link); + w->parent = NULL; +} + +/** + * Move window to the topmost position relative to its sibling. + * + * \see win_move(), win_resize(), win_setGeometry() + */ +void win_raise(Window *w) +{ + ASSERT(w->parent); + REMOVE(&w->link); + ADDHEAD(&w->parent->children, &w->link); +} + +/** + * Set window position and size at the same time. + * + * This function is equivalent to subsequent calls to win_move() + * and win_resize() using the coordinates provided by the + * \a new_geom rectangle. + * + * \note The xmax and ymax members of \a new_geom are non-inclusive, + * as usual for the Rect interface. + * + * \see win_move() + * \see win_resize() + */ +void win_setGeometry(Window *w, const Rect *new_geom) +{ + // requires C99? + // memcpy(&w->geom, new_geom, sizeof(w->geom)); + w->geom = *new_geom; +} + +/** + * Move window to specified position. + * + * Move the window top-left corner to the pixel coordinates + * \a left and \a top, which are relative to the parent window. + * + * \note A window can also be moved outside the borders + * of its parent, or at negative coordinates. + * + * \note It is allowed to move an orphan window. + */ +void win_move(Window *w, coord_t left, coord_t top) +{ + Rect r; + + r.xmin = left; + r.ymin = top; + r.xmax = r.xmin + RECT_WIDTH(&w->geom); + r.ymax = r.ymin + RECT_WIDTH(&w->geom); + + win_setGeometry(w, &r); +} + +/** + * Resize the rectangle of a window. + * + * The window shrinks or grows to the specified size. + * + * \note Growing a window beyond the size of its + * backing bitmap results in unspecified behavior. + * + * \note It is allowed to resize an orphan window. + */ +void win_resize(Window *w, coord_t width, coord_t height) +{ + Rect r; + + r.xmin = w->geom.xmin; + r.ymin = w->geom.ymin; + r.xmax = r.xmin + width; + r.ymax = r.ymin + height; + + win_setGeometry(w, &r); +} + +/** + * Initialize a new window structure. + * + * The new window initial position is set to (0,0). + * The size is set to the size of the installed bitmap, + * or (0,0) if there's no backing store. + * + * \arg bm The bitmap to install as backing store + * for drawing into the window, or NULL if + * the window is not drawable. + */ +void win_create(Window *w, Bitmap *bm) +{ + w->parent = NULL; + w->bitmap = bm; + w->geom.xmin = 0; + w->geom.ymin = 0; + if (bm) + { + w->geom.xmax = bm->width; + w->geom.ymax = bm->height; + } + LIST_INIT(&w->children); +} + diff --git a/bertos/gfx/win.h b/bertos/gfx/win.h new file mode 100644 index 00000000..3dafc910 --- /dev/null +++ b/bertos/gfx/win.h @@ -0,0 +1,120 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Very simple hierarchical windowing system. + * + * All functions in this module are to be intended as methods + * of the Window class. Please see its documentation + * for a module-wise introduction. + * + * \see struct Window + */ + +/*#* + *#* $Log$ + *#* Revision 1.3 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.2 2006/01/26 00:36:48 bernie + *#* Const correctness for some new functions. + *#* + *#* Revision 1.1 2006/01/23 23:14:29 bernie + *#* Implement simple, but impressive windowing system. + *#* + *#*/ + +#ifndef GFX_WIN_H +#define GFX_WIN_H + +#include /* Node, List */ +#include /* coord_t */ + + +EXTERN_C_BEGIN + +/** + * Window handle and context structure. + * + * A window is a small rectangular area on the + * screen backed by its own bitmap where you + * can draw. + * + * A window can contain any number of children + * sub-windows that can be depth arranged with + * respect to their siblings. + * + * At any time, a window and all its children + * can be drawn into another bitmap to display + * a complete screen, taking depth and + * overlapping into account. + * + * This rendering model is commonly referred to as + * screen composition, and is quite popular among + * modern windowing systems. + */ +typedef struct Window +{ + Node link; /**< Link us with other siblings into our parent. */ + struct Window *parent; /**< Our parent window. NULL for the root window. */ + + Bitmap *bitmap; /**< Pixel storage for window contents. */ + Rect geom; /**< [px] Window size and position relative to parent. */ + + /** + * List of child windows, arranged by depth (front to back). + * + * Child top/left coordinates are relative to us. + */ + List children; + +} Window; + +/* + * Public function prototypes + */ +void win_compose(Window *w); +void win_open(Window *w, Window *parent); +void win_close(Window *w); +void win_raise(Window *w); +void win_setGeometry(Window *w, const Rect *new_geom); +void win_move(Window *w, coord_t left, coord_t top); +void win_resize(Window *w, coord_t width, coord_t height); +void win_create(Window *w, Bitmap *bm); + +EXTERN_C_END + +#endif /* GFX_WIN_H */ + diff --git a/bertos/gui/levelbar.c b/bertos/gui/levelbar.c new file mode 100644 index 00000000..8b75d15b --- /dev/null +++ b/bertos/gui/levelbar.c @@ -0,0 +1,106 @@ +/** + * \file + * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) + * + * + * \brief Graphics user interface element to display a level bar. + * + * \version $Id$ + * \author Stefano Fedrigo + */ + +#include "levelbar.h" + + +/** + * Initialize the LevelBar widget with the bitmap associated, + * the value range and the coordinates in the bitmap. + * \note The levelbar should be at least 5 pixels wide and high + * for correct borders drawing. No check is done on this. + */ +void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos, + coord_t x1, coord_t y1, coord_t x2, coord_t y2) +{ + lb->bitmap = bmp; + lb->type = type; + lb->min = min; + lb->max = max; + lb->pos = pos; + lb->x1 = x1; + lb->y1 = y1; + lb->x2 = x2; + lb->y2 = y2; +} + + +/** + * Set the level. + */ +void lbar_setLevel(struct LevelBar *lb, int level) +{ + if (level < lb->min) + level = lb->min; + if (level > lb->max) + level = lb->max; + + lb->pos = level; +} + + +/** + * Get current level. + */ +int lbar_getLevel(struct LevelBar *lb) +{ + return lb->pos; +} + + +/** + * Change level with respect to previous value + * (delta can be negative). + */ +void lbar_changeLevel(struct LevelBar *lb, int delta) +{ + lbar_setLevel(lb, lb->pos + delta); +} + + +/** + * Change the top limit. + */ +void lbar_setMax(struct LevelBar *lb, int max) +{ + lb->max = max; +} + + +/** + * Render the LevelBar on the bitmap. + */ +void lbar_draw(struct LevelBar *lb) +{ +#define BORDERW 1 +#define BORDERH 1 + + /* Compute filled bar length in pixels */ + int totlen = (lb->type & LBAR_HORIZONTAL) ? lb->x2 - lb->x1 - BORDERW*4 : lb->y2 - lb->y1 - BORDERH*4; + int range = lb->max - lb->min; + int barlen = ((long)(lb->pos - lb->min) * (long)totlen + range - 1) / range; + + // Draw border + gfx_rectDraw(lb->bitmap, lb->x1, lb->y1, lb->x2, lb->y2); + + // Clear inside + gfx_rectClear(lb->bitmap, lb->x1 + BORDERW, lb->y1 + BORDERH, lb->x2 - BORDERW, lb->y2 - BORDERH); + + // Draw bar + if (lb->type & LBAR_HORIZONTAL) + gfx_rectFill(lb->bitmap, + lb->x1 + BORDERW*2, lb->y1 + BORDERH*2, + lb->x1 + BORDERW*2 + barlen, lb->y2 - BORDERH*2); + else + gfx_rectFill(lb->bitmap, + lb->x1 + BORDERW*2, lb->y2 - BORDERH*2 - barlen, + lb->x2 - BORDERW*2, lb->y2 - BORDERH*2); +} diff --git a/bertos/gui/levelbar.h b/bertos/gui/levelbar.h new file mode 100644 index 00000000..97b1a9a9 --- /dev/null +++ b/bertos/gui/levelbar.h @@ -0,0 +1,41 @@ +/** + * \file + * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) + * + * + * \version $Id$ + * + * \author Stefano Fedrigo + * + * \brief Graphics level bar widget + */ + +#ifndef GUI_LEVELBAR_H +#define GUI_LEVELBAR_H + +#include + + +/** Type of levelbar */ +#define LBAR_HORIZONTAL 1 +#define LBAR_VERTICAL 2 + +typedef struct LevelBar +{ + struct Bitmap *bitmap; + int type; + int pos; ///< Current level + int min; ///< Minimum level + int max; ///< Maximum level + coord_t x1, y1, x2, y2; ///< Position of widget in the bitmap +} LevelBar; + +void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos, + coord_t x1, coord_t y1, coord_t x2, coord_t y2); +void lbar_setLevel(struct LevelBar *lb, int level); +int lbar_getLevel(struct LevelBar *lb); +void lbar_changeLevel(struct LevelBar *lb, int delta); +void lbar_setMax(struct LevelBar *lb, int max); +void lbar_draw(struct LevelBar *lb); + +#endif /* GUI_LEVELBAR_H */ diff --git a/bertos/gui/leveledit.c b/bertos/gui/leveledit.c new file mode 100644 index 00000000..902d7154 --- /dev/null +++ b/bertos/gui/leveledit.c @@ -0,0 +1,330 @@ +/** + * \file + * + * + * \brief Generic editor for (volume/gain/contrast/...) setting. + * + * \version $Id$ + * \author Stefano Fedrigo + */ + +#include "leveledit.h" + +#include /* MAX() */ +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_MENU_MENUBAR +#include +#endif + +// BEGIN project_grl LOCAL +#include +#include +// END project_grl LOCAL + +#define LBAR_HEIGHT 16 + +/** + * Allow user to change level. + */ +void level_edit(struct LevelEdit *lev) +{ +#if CONFIG_MENU_MENUBAR + /* Labels for menubars */ + enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 }; + const_iptr_t labels[] = + { + (const_iptr_t)LABEL_BACK, + (const_iptr_t)LABEL_MINUS, + (const_iptr_t)LABEL_PLUS, + (const_iptr_t)LABEL_EMPTY + }; + struct MenuBar mb; +#endif /* CONFIG_MENU_MENUBAR */ + + struct LevelBar bar1, bar2; + keymask_t keys, old_rpt_mask; + int step, rep_step; + + rep_step = MAX(lev->step, ((lev->max - lev->min) / 200)); + step = lev->step; + + // Allow keys repetition. + old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN); + + text_clear(lev->bitmap); + //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE); + text_puts(lev->title, lev->bitmap); + //text_style(0, STYLEF_UNDERLINE); + + if (lev->type & LEVELEDIT_DOUBLE) + { + int chn = 0; /* edit both channels */ + + /* Levelbars init */ + lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL, + lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23); + lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL, + lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23); + + #if CONFIG_MENU_MENUBAR + labels[3] = (const_iptr_t)ch_labels[chn]; + mbar_init(&mb, lev->bitmap, labels, countof(labels)); + mbar_draw(&mb); + #endif /* CONFIG_MENU_MENUBAR */ + + /* Input loop for double level setting */ + for (;;) + { + #if CONFIG_LEVELEDIT_TIMEOUT != 0 + ticks_t idle_timeout = timer_clock(); + #endif + do + { + if (lev->display_hook) + lev->display_hook(lev); + else + { + text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit); + PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val); + PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val); + + lbar_setLevel(&bar1, *lev->ch1_val); + lbar_setLevel(&bar2, *lev->ch2_val); + lbar_draw(&bar1); + lbar_draw(&bar2); + } + + #if CONFIG_LEVELEDIT_TIMEOUT != 0 + if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT)) + { + /* Accept input implicitly */ + keys = K_OK; + break; + } + #endif + } + while (!(keys = kbd_peek())); + + if (keys & K_CANCEL) + break; + + if (keys & K_OK) + { + chn = (chn + 1) % 3; + + #if CONFIG_MENU_MENUBAR + labels[3] = (const_iptr_t)ch_labels[chn]; + mbar_draw(&mb); + #endif /* CONFIG_MENU_MENUBAR */ + } + + /* Increment step to achieve greater accelerations on larger values */ + if (keys & K_REPEAT) + step = MIN(rep_step, step + 1); + else + step = lev->step; + + if (keys & (K_UP | K_DOWN)) + { + if (keys & K_UP) + { + /* If changing both channels (chn == 0), don't change + * level if one of two is at min or max */ + if (chn != 0 || + (*lev->ch1_val + step <= lev->max + && *lev->ch2_val + step <= lev->max)) + { + /* If chn == 0 change both channels */ + if (chn != 2) + { + *lev->ch1_val += step; + if (*lev->ch1_val > lev->max) + *lev->ch1_val = lev->max; + } + if (chn != 1) + { + *lev->ch2_val += step; + if (*lev->ch2_val > lev->max) + *lev->ch2_val = lev->max; + } + } + } + else + { + if (chn != 0 || + (*lev->ch1_val - step >= lev->min + && *lev->ch2_val - step >= lev->min)) + { + if (chn != 2) + { + *lev->ch1_val -= step; + if (*lev->ch1_val < lev->min) + *lev->ch1_val = lev->min; + } + if (chn != 1) + { + *lev->ch2_val -= step; + if (*lev->ch2_val < lev->min) + *lev->ch2_val = lev->min; + } + } + } + + if (lev->set_hook) + lev->set_hook(); + } + } // end for(;;) + } + else + { + const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d"); + +/* + const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit), + PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit)); + + const coord_t barlen = lev->bitmap->width - 6 - textw; +*/ + const coord_t barlen = lev->bitmap->width; + const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height; + lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL, + lev->min, lev->max, *lev->ch1_val, + 0, barvtop, barlen, barvtop + LBAR_HEIGHT); + + #if CONFIG_MENU_MENUBAR + mbar_init(&mb, lev->bitmap, labels, countof(labels)); + mbar_draw(&mb); + #endif /* CONFIG_MENU_MENUBAR */ + + /* Input loop for single level setting */ + for (;;) + { + #if CONFIG_LEVELEDIT_TIMEOUT != 0 + ticks_t idle_timeout = timer_clock(); + #endif + do + { + if (lev->display_hook) + lev->display_hook(lev); + else + { + if (lev->type != LEVELEDIT_NOBAR) + { + lbar_setLevel(&bar1, *lev->ch1_val); + lbar_draw(&bar1); + } + PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height, + TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit); + } + + #if CONFIG_LEVELEDIT_TIMEOUT != 0 + if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT) + { + /* Accept input implicitly */ + keys = K_CANCEL; + break; + } + #endif + +// BEGIN project_grl LOCAL +#if 1 + //FIXME: must to this only when needed + lcd_blitBitmap(&lcd_bitmap); + } + while (!(keys = GuiMan_KbdPeek())); +#else + } + while (!(keys = kbd_peek())); +#endif +// END project_grl LOCAL + + if (keys & K_CANCEL) + break; + + /* Increment step to achieve greater accelerations on larger values */ + if (keys & K_REPEAT) + step = MIN(rep_step, step + 1); + else + step = lev->step; + + if (keys & K_UP) + { + *lev->ch1_val += step; + if (*lev->ch1_val > lev->max) + *lev->ch1_val = lev->max; + } + + if (keys & K_DOWN) + { + *lev->ch1_val -= step; + if (*lev->ch1_val < lev->min) + *lev->ch1_val = lev->min; + } + + if (lev->set_hook) + lev->set_hook(); + } + } + + kbd_setRepeatMask(old_rpt_mask); +} + +/** + * LevelEdit structure initialization. + * Init data structure and init LevelEdit widgets. + */ +void level_init(struct LevelEdit *lev, + int type, + struct Bitmap *bmp, const char *title, const char *unit, + int min, int max, int step, + int *ch1_val, int *ch2_val, + level_set_callback *set_hook, display_callback *display_hook) +{ + lev->type = type; + lev->bitmap = bmp; + lev->title = title; + lev->unit = unit; + lev->min = min; + lev->max = max; + lev->step = step; + + lev->ch1_val = ch1_val; + lev->ch2_val = ch2_val; + lev->set_hook = set_hook; + lev->display_hook = display_hook; +} diff --git a/bertos/gui/leveledit.h b/bertos/gui/leveledit.h new file mode 100644 index 00000000..b41df146 --- /dev/null +++ b/bertos/gui/leveledit.h @@ -0,0 +1,89 @@ +/** + * \file + * + * + * \brief Generic editor for (volume/gain/contrast/...) setting. + * + * \version $Id$ + * + * \author Stefano Fedrigo + */ +#ifndef GUI_LEVELEDIT_H +#define GUI_LEVELEDIT_H + +//#include + +/* Type for level_init */ +#define LEVELEDIT_NOBAR 0 /**< Edit number only, without bar nor units */ +#define LEVELEDIT_SINGLE 1 /**< Single channel editing */ +#define LEVELEDIT_DOUBLE 2 /**< Double channel editing */ + + + +/* Fwd decl */ +struct Bitmap; +struct LevelEdit; + +/** Type for callback used to set meter levels */ +typedef void level_set_callback(void); + +/** Type for callback used to customize display of units */ +typedef void display_callback(struct LevelEdit *); + +/** + * State of a level meter + */ +typedef struct LevelEdit { + int type; /* + * + * --> + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief General pourpose menu handling functions + */ + +/*#* + *#* $Log$ + *#* Revision 1.8 2006/09/13 13:58:32 bernie + *#* Add RenderHook support. + *#* + *#* Revision 1.7 2006/08/01 12:22:46 bernie + *#* Mention DevLib license. + *#* + *#* Revision 1.6 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.5 2006/06/03 13:58:01 bernie + *#* Fix recursive timeout and add exit status information. + *#* + *#* Revision 1.4 2006/06/02 12:26:18 bernie + *#* Draw graphical checkmarks. + *#* + *#* Revision 1.3 2006/05/28 15:03:31 bernie + *#* Avoid unnecessary rendering. + *#* + *#* Revision 1.2 2006/05/25 23:34:38 bernie + *#* Implement menu timeouts. + *#* + *#* Revision 1.1 2006/05/15 07:20:54 bernie + *#* Move menu to gui/. + *#* + *#* Revision 1.7 2006/04/27 05:39:24 bernie + *#* Enhance text rendering to arbitrary x,y coords. + *#* + *#* Revision 1.6 2006/04/11 00:07:32 bernie + *#* Implemenent MF_SAVESEL flag. + *#* + *#* Revision 1.5 2006/03/22 09:49:51 bernie + *#* Simplifications from project_grl. + *#* + *#* Revision 1.4 2006/03/20 17:48:35 bernie + *#* Implement support for ROM menus. + *#* + *#* Revision 1.3 2006/02/20 14:34:32 bernie + *#* Include appconfig.h before using its definitions. + *#* + *#* Revision 1.2 2006/02/15 09:10:51 bernie + *#* Make title bold; Fix height when we have no menubar. + *#*/ + +#include "menu.h" + +#include +#include +#include +#include +#include +#include +#include +#include /* strcpy() */ + +#if CPU_HARVARD +#include /* strncpy_P() */ +#endif + +#if CONFIG_MENU_SMOOTH +#include +#endif + +#if (CONFIG_MENU_TIMEOUT != 0) +#include +#endif + +#if CONFIG_MENU_MENUBAR +#include "menubar.h" +#endif + +#if defined(CONFIG_LOCALE) && (CONFIG_LOCALE == 1) +#include "msg.h" +#else +#define PTRMSG(x) ((const char *)x) +#endif + + +/* Temporary fake defines for ABORT stuff... */ +#define abort_top 0 +#define PUSH_ABORT false +#define POP_ABORT do {} while(0) +#define DO_ABORT do {} while(0) + + +/** + * Return the total number of items in in a menu. + */ +static int menu_count(const struct Menu *menu) +{ + int cnt = 0; + + for (cnt = 0; /*NOP*/; ++cnt) + { + const MenuItem *item = &menu->items[cnt]; +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif + if (!(item->label || item->hook)) + break; + } + + return cnt; +} + +#if CONFIG_MENU_MENUBAR + +/** + * Update the menu bar according to the selected item and redraw it. + */ +static void menu_update_menubar( + const struct Menu *menu, + struct MenuBar *mb, + int selected) +{ + int item_flags; +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[selected].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[selected].flags); + } + else +#endif + item_flags = menu->items[selected].flags; + + const_iptr_t newlabel = (const_iptr_t)LABEL_OK; + + if (item_flags & MIF_DISABLED) + newlabel = (const_iptr_t)LABEL_EMPTY; + else if (item_flags & MIF_TOGGLE) + newlabel = (const_iptr_t)LABEL_SEL; + else if (item_flags & MIF_CHECKIT) + { + newlabel = (item_flags & MIF_CHECKED) ? + (const_iptr_t)LABEL_EMPTY : (const_iptr_t)LABEL_SEL; + } + + mb->labels[3] = newlabel; + mbar_draw(mb); +} +#endif /* CONFIG_MENU_MENUBAR */ + + +static void menu_defaultRenderHook(struct Bitmap *bm, int ypos, bool selected, const struct MenuItem *item) +{ + if (item->flags & MIF_CHECKIT) + { + gfx_rectClear(bm, 0, ypos, + bm->font->height, ypos + bm->font->height); + + if (item->flags & MIF_TOGGLE) + gfx_rectDraw(bm, 2, ypos + 2, + bm->font->height - 2, ypos + bm->font->height - 2); + if (item->flags & MIF_CHECKED) + { + gfx_line(bm, + 3, ypos + 3, + bm->font->height - 3, ypos + bm->font->height - 3); + gfx_line(bm, + bm->font->height - 3, ypos + 3, + 3, ypos + bm->font->height - 3); + } + } + +#if CPU_HARVARD + ((item->flags & MIF_RAMLABEL) ? text_xyprintf : text_xyprintf_P) +#else + text_xyprintf +#endif + ( + bm, (item->flags & MIF_CHECKIT) ? bm->font->height : 0, ypos, + selected ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL, + PTRMSG(item->label) + ); +} + +/** + * Show a menu on the display. + */ +static void menu_layout( + const struct Menu *menu, + int first_item, + int selected, + bool redraw) +{ + coord_t ypos; + int i; + const char * PROGMEM title = PTRMSG(menu->title); + Bitmap *bm = menu->bitmap; + + ypos = bm->cr.ymin; + +#if 0 + if (redraw) + { + /* Clear screen */ + text_clear(menu->bitmap); + } +#endif + + if (title) + { + if (redraw) + text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title); + ypos += bm->font->height; + } + +#if CONFIG_MENU_SMOOTH + static coord_t yoffset = 0; + static int old_first_item = 0; + static int speed; + coord_t old_ymin = bm->cr.ymin; + + /* Clip drawing inside menu items area */ + gfx_setClipRect(bm, + bm->cr.xmin, bm->cr.ymin + ypos, + bm->cr.xmax, bm->cr.ymax); + + if (old_first_item != first_item) + { + /* Speed proportional to distance */ + speed = ABS(old_first_item - first_item) * 3; + + if (old_first_item > first_item) + { + yoffset += speed; + if (yoffset > bm->font->height) + { + yoffset = 0; + --old_first_item; + } + } + else + { + yoffset -= speed; + if (yoffset < -bm->font->height) + { + yoffset = 0; + ++old_first_item; + } + } + first_item = MIN(old_first_item, menu_count(menu)); + + ypos += yoffset; + redraw = true; + } +#endif /* CONFIG_MENU_SMOOTH */ + + if (redraw) for (i = first_item; /**/; ++i) + { + const MenuItem *item = &menu->items[i]; +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif /* CPU_HARVARD */ + + /* Check for end of room */ + if (ypos > bm->cr.ymax) + break; + + /* Check for end of menu */ + if (!(item->label || item->hook)) + break; + + /* Only print visible items */ + if (!(item->flags & MIF_HIDDEN)) + { + /* Check if a special render function is supplied, otherwise use defaults */ + RenderHook renderhook = (item->flags & MIF_RENDERHOOK) ? (RenderHook)item->label : menu_defaultRenderHook; + + /* Render menuitem */ + renderhook(menu->bitmap, ypos++, (i == selected), item); + + ypos += bm->font->height; + } + } + +#if CONFIG_MENU_SMOOTH + if (redraw) + { + /* Clear rest of area */ + gfx_rectClear(bm, bm->cr.xmin, ypos, bm->cr.xmax, bm->cr.ymax); + + lcd_blitBitmap(&lcd_bitmap); + } + + /* Restore old cliprect */ + gfx_setClipRect(bm, + bm->cr.xmin, old_ymin, + bm->cr.xmax, bm->cr.ymax); + +#endif /* CONFIG_MENU_SMOOTH */ +} + + +/** + * Handle menu item selection + */ +static iptr_t menu_doselect(const struct Menu *menu, struct MenuItem *item) +{ + iptr_t result = 0; + + /* Exclude other items */ + int mask, i; + for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i) + { + if (mask & 1) + menu->items[i].flags &= ~MIF_CHECKED; + } + + if (item->flags & MIF_DISABLED) + return MENU_DISABLED; + + /* Handle checkable items */ + if (item->flags & MIF_TOGGLE) + item->flags ^= MIF_CHECKED; + else if (item->flags & MIF_CHECKIT) + item->flags |= MIF_CHECKED; + + /* Handle items with callback hooks */ + if (item->hook) + { + /* Push a jmp buffer to abort the operation with the STOP/CANCEL key */ + if (!PUSH_ABORT) + { + result = item->hook(item->userdata); + POP_ABORT; + } + } + else + result = item->userdata; + + return result; +} + + +/** + * Return the next visible item (rolls back to the first item) + */ +static int menu_next_visible_item(const struct Menu *menu, int index) +{ + int total = menu_count(menu); + int item_flags; + + do + { + if (++index >= total) + index = 0; + +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[index].flags); + } + else +#endif + item_flags = menu->items[index].flags; + } + while (item_flags & MIF_HIDDEN); + + return index; +} + + +/** + * Return the previous visible item (rolls back to the last item) + */ +static int menu_prev_visible_item(const struct Menu *menu, int index) +{ + int total = menu_count(menu); + int item_flags; + + do + { + if (--index < 0) + index = total - 1; + +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[index].flags); + } + else +#endif + item_flags = menu->items[index].flags; + } + while (item_flags & MIF_HIDDEN); + + return index; +} + + +/** + * Handle a menu and invoke hook functions for the selected menu items. + */ +iptr_t menu_handle(const struct Menu *menu) +{ + uint8_t items_per_page; + uint8_t first_item = 0; + uint8_t selected; + iptr_t result = 0; + bool redraw = true; + +#if (CONFIG_MENU_TIMEOUT != 0) + ticks_t now, menu_idle_time = timer_clock(); +#endif + +#if CONFIG_MENU_MENUBAR + struct MenuBar mb; + const_iptr_t labels[] = + { + (const_iptr_t)LABEL_BACK, + (const_iptr_t)LABEL_UPARROW, + (const_iptr_t)LABEL_DOWNARROW, + (const_iptr_t)0 + }; + + /* + * Initialize menu bar + */ + if (menu->flags & MF_TOPLEVEL) + labels[0] = (const_iptr_t)LABEL_EMPTY; + + mbar_init(&mb, menu->bitmap, labels, countof(labels)); +#endif /* CONFIG_MENU_MENUBAR */ + + + items_per_page = + (menu->bitmap->height / menu->bitmap->font->height) +#if CONFIG_MENU_MENUBAR + - 1 /* menu bar labels */ +#endif + - (menu->title ? 1 : 0); + + /* Selected item should be a visible entry */ + //first_item = selected = menu_next_visible_item(menu, menu->selected - 1); + selected = menu->selected; + first_item = 0; + + for(;;) + { + keymask_t key; + + /* + * Keep selected item visible + */ + while (selected < first_item) + first_item = menu_prev_visible_item(menu, first_item); + while (selected >= first_item + items_per_page) + first_item = menu_next_visible_item(menu, first_item); + + menu_layout(menu, first_item, selected, redraw); + redraw = false; + + #if CONFIG_MENU_MENUBAR + menu_update_menubar(menu, &mb, selected); + #endif + + #if CONFIG_MENU_SMOOTH || (CONFIG_MENU_TIMEOUT != 0) + key = kbd_peek(); + #else + key = kbd_get(); + #endif + + #if (CONFIG_MENU_TIMEOUT != 0) + /* Reset idle timer on key press. */ + now = timer_clock(); + if (key) + menu_idle_time = now; + #endif + + if (key & K_OK) + { + struct MenuItem *item = &(menu->items[selected]); +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif + result = menu_doselect(menu, item); + redraw = true; + + /* Return immediately */ + if (!(menu->flags & MF_STICKY)) + break; + + #if (CONFIG_MENU_TIMEOUT != 0) + /* Chain timeout */ + if ((result == MENU_TIMEOUT) && !(menu->flags & MF_TOPLEVEL)) + break; + + /* Reset timeout */ + menu_idle_time = timer_clock(); + #endif + } + else if (key & K_UP) + { + selected = menu_prev_visible_item(menu, selected); + redraw = true; + } + else if (key & K_DOWN) + { + selected = menu_next_visible_item(menu, selected); + redraw = true; + } + else if (!(menu->flags & MF_TOPLEVEL)) + { + if (key & K_CANCEL) + { + result = MENU_CANCEL; + break; + } + + #if CONFIG_MENU_TIMEOUT != 0 + if (now - menu_idle_time > ms_to_ticks(CONFIG_MENU_TIMEOUT)) + { + result = MENU_TIMEOUT; + break; + } + #endif + } + } + + /* Store currently selected item before leaving. */ + if (menu->flags & MF_SAVESEL) + CONST_CAST(struct Menu *, menu)->selected = selected; + + return result; +} + + +/** + * Set flags on a menuitem. + * + * \param menu Menu owner of the item to change. + * \param idx Index of the menu item. + * \param flags Bit mask of the flags to set. + * + * \return Old flags. + */ +int menu_setFlags(struct Menu *menu, int idx, int flags) +{ + ASSERT(idx < menu_count(menu)); + ASSERT(!(menu->flags & MF_ROMITEMS)); + + int old = menu->items[idx].flags; + menu->items[idx].flags |= flags; + return old; +} + + +/** + * Clear flags on a menuitem. + * + * \param menu Menu owner of the item to change. + * \param idx Index of the menu item. + * \param flags Bit mask of the flags to clear. + * + * \return Old flags. + */ +int menu_clearFlags(struct Menu *menu, int idx, int flags) +{ + ASSERT(idx < menu_count(menu)); + ASSERT(!(menu->flags & MF_ROMITEMS)); + + int old = menu->items[idx].flags; + menu->items[idx].flags &= ~flags; + return old; +} diff --git a/bertos/gui/menu.h b/bertos/gui/menu.h new file mode 100644 index 00000000..31b33f62 --- /dev/null +++ b/bertos/gui/menu.h @@ -0,0 +1,185 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief Common menu handling API + */ + +/*#* + *#* $Log$ + *#* Revision 1.5 2007/09/19 16:23:27 batt + *#* Fix doxygen warnings. + *#* + *#* Revision 1.4 2006/09/13 13:58:33 bernie + *#* Add RenderHook support. + *#* + *#* Revision 1.3 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.2 2006/06/03 13:58:02 bernie + *#* Fix recursive timeout and add exit status information. + *#* + *#* Revision 1.1 2006/05/15 07:20:54 bernie + *#* Move menu to gui/. + *#* + *#* Revision 1.4 2006/04/11 00:07:32 bernie + *#* Implemenent MF_SAVESEL flag. + *#* + *#* Revision 1.3 2006/03/22 09:49:51 bernie + *#* Simplifications from project_grl. + *#* + *#* Revision 1.2 2006/03/20 17:48:35 bernie + *#* Implement support for ROM menus. + *#* + *#* Revision 1.1 2006/02/10 12:29:36 bernie + *#* Add menu system. + *#* + *#* Revision 1.20 2005/11/16 18:10:19 bernie + *#* Move top-level headers to cfg/ as in DevLib. + *#* + *#* Revision 1.19 2005/02/11 19:11:38 aleph + *#* Move menu_displaymsg() in new displaymsg module + *#* + *#* Revision 1.18 2005/01/13 16:56:36 aleph + *#* Fix progmem includes. + *#* + *#* Revision 1.17 2004/12/14 12:52:45 aleph + *#* Add exclude menu flags + *#* + *#* Revision 1.16 2004/10/01 14:04:59 customer_pw + *#* Add accessor functions for menu flags + *#* + *#* Revision 1.15 2004/09/09 08:31:36 customer_pw + *#* Add disabled item type + *#* + *#* Revision 1.14 2004/08/29 21:46:12 bernie + *#* CVSSILENT: Mark CVS log blocks. + *#* + *#* Revision 1.13 2004/08/25 15:35:23 customer_pw + *#* IPTR -> iptr_t conversion. + *#* + *#* Revision 1.12 2004/08/25 13:23:45 bernie + *#* IPTR -> iptr_t conversion. + *#*/ +#ifndef MWARE_MENU_H +#define MWARE_MENU_H + +#include + +/* Fwd decl */ +struct Bitmap; + +/** Menu callback function */ +typedef iptr_t (*MenuHook)(iptr_t userdata); + +/** + * Menu item description. + */ +typedef struct MenuItem +{ + const_iptr_t label; /**< Item label (ID or ptr to string, 0 to disable) */ + int flags; /**< See MIF_#? definitions below */ + MenuHook hook; /**< Callback function (NULL to terminate item list) */ + iptr_t userdata; /**< User data to be passed back to the hook */ +} MenuItem; + +/** Render hook callback function prototype */ +typedef void (*RenderHook)(struct Bitmap *bitmap, int ypos, bool selected, const struct MenuItem *item); + +/** + * \name Flags for MenuItem.flags. + * \{ + */ +#define MIF_EXCLUDE_MASK 0x00FF /**< Mask for mutual exclusion map (shared with priority). */ +#define MIF_PRI_MASK 0x00FF /**< Mask for priority value (shared with mutual exclusion). */ +#define MIF_PRI(x) ((x) & MIF_PRI_MASK) /**< Set menu item priority. */ +#define MIF_EXCLUDE_0 BV(0) /**< Exclude item 0 when this item is checked */ +#define MIF_EXCLUDE_1 BV(1) /**< Exclude item 1 when this item is checked */ +#define MIF_EXCLUDE_2 BV(2) /**< Exclude item 2 when this item is checked */ +#define MIF_EXCLUDE_3 BV(3) /**< Exclude item 3 when this item is checked */ +#define MIF_EXCLUDE_4 BV(4) /**< Exclude item 4 when this item is checked */ +#define MIF_EXCLUDE_5 BV(5) /**< Exclude item 5 when this item is checked */ +#define MIF_EXCLUDE_6 BV(6) /**< Exclude item 6 when this item is checked */ +#define MIF_EXCLUDE_7 BV(7) /**< Exclude item 7 when this item is checked */ +#define MIF_CHECKED BV(8) /**< Item is currently checked */ +#define MIF_CHECKIT BV(9) /**< Automatically check this item when selected */ +#define MIF_TOGGLE BV(10) /**< Toggle MIF_CHECKED when item is selected */ +#define MIF_HIDDEN BV(11) /**< This menu item is not visible */ +#define MIF_DISABLED BV(12) /**< This menu item is not visible */ +#define MIF_RAMLABEL BV(13) /**< Item label is stored in RAM, not in program memory */ +#define MIF_RENDERHOOK BV(14) /**< Menu render function is passed in label field */ +/* \} */ + +/** + * Menu description. + */ +typedef struct Menu +{ + MenuItem *items; /**< Array of items (end with a NULL hook) */ + const_iptr_t title; /**< Menu title (ID or ptr to string, 0 to disable) */ + int flags; /**< See MF_#? definitions below */ + struct Bitmap *bitmap; /**< Bitmap where the menu is rendered */ + int selected; /**< Initial selection (written to if MF_SAVESEL is set). */ +} Menu; + +/** + * \name Flags for Menu.flags. + * \{ + */ +#define MF_STICKY BV(0) /**< Stay in the menu when the items called return */ +#define MF_TOPLEVEL BV(1) /**< Top-level menu (do not display "back" label) */ +#define MF_ROMITEMS BV(2) /**< Menu items are stored in ROM (default is RAM) */ +#define MF_SAVESEL BV(3) /**< Remember the selected item across invocations. */ +/* \} */ + +/** + * \name Special result codes for menu_handle(). + * \{ + */ +#define MENU_OK ((iptr_t)0) +#define MENU_CANCEL ((iptr_t)-1) +#define MENU_TIMEOUT ((iptr_t)-2) +#define MENU_ABORT ((iptr_t)-3) +#define MENU_DISABLED ((iptr_t)-4) +/* \} */ + +/* Function prototypes */ +iptr_t menu_handle(const struct Menu *menu); +int menu_setFlags(struct Menu *menu, int idx, int flags); +int menu_clearFlags(struct Menu *menu, int idx, int flags); + +#endif /* MWARE_MENU_H */ diff --git a/bertos/hw/hw_buzzer.h b/bertos/hw/hw_buzzer.h new file mode 100644 index 00000000..d4ec5f74 --- /dev/null +++ b/bertos/hw/hw_buzzer.h @@ -0,0 +1,60 @@ +/** + * \file + * + * + * \brief Buzzer hardware-specific definitions + * + * \version $Id$ + * + * \author Francesco Sacchi + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2006/02/10 12:31:03 bernie + *#* Add templates for hw definitions. + *#* + *#*/ + +#ifndef HW_BUZZER_H +#define HW_BUZZER_H + +#define BUZZER_BIT BV(1) +#define IS_BUZZER_ON 0 +#define BUZZER_HW_INIT do { } while (0) +#define BUZZER_ON do { } while (0) +#define BUZZER_OFF do { } while (0) + +#endif /* HW_BUZZER_H */ diff --git a/bertos/hw/hw_kbd.h b/bertos/hw/hw_kbd.h new file mode 100644 index 00000000..7e82cb05 --- /dev/null +++ b/bertos/hw/hw_kbd.h @@ -0,0 +1,81 @@ +/** + * \file + * + * + * \brief Keyboard hardware-specific definitions + * + * \version $Id$ + * + * \author Francesco Sacchi + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2006/03/22 09:51:27 bernie + *#* Wrap C++ stuff. + *#* + *#* Revision 1.2 2006/02/15 09:13:42 bernie + *#* Add keyboard emulator. + *#* + *#* Revision 1.1 2006/02/10 12:31:03 bernie + *#* Add templates for hw definitions. + *#* + *#*/ + +#ifndef HW_KBD_H +#define HW_KBD_H + +#include "kbd_map.h" +#include + +#define K_RPT_MASK (K_UP | K_DOWN | K_OK | K_CANCEL) + +#define KBD_HW_INIT \ + do { \ + } while (0) + +EXTERN_C int emul_kbdReadCols(void); + +/** + * Read the keyboard ports and return the mask of + * depressed keys. + */ +INLINE keymask_t kbd_readkeys(void) +{ + return (keymask_t)emul_kbdReadCols(); +} + +#endif /* HW_KBD_H */ diff --git a/bertos/hw/hw_lcd.h b/bertos/hw/hw_lcd.h new file mode 100644 index 00000000..b7cf5f89 --- /dev/null +++ b/bertos/hw/hw_lcd.h @@ -0,0 +1,162 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief LCD low-level hardware macros + */ + +#ifndef HW_LCD_H +#define HW_LCD_H + +#include +//#include + +#include +#include +#include + +#include /* BV() */ +#include + +#include +#include +#include + +/** + * \name LCD I/O pins/ports + * @{ + */ +#define LCD_RS BV(PG3) +#define LCD_RW BV(PG0) +#define LCD_E BV(PG2) +#define LCD_DB0 BV(PA0) +#define LCD_DB1 BV(PA1) +#define LCD_DB2 BV(PA2) +#define LCD_DB3 BV(PA3) +#define LCD_DB4 BV(PA4) +#define LCD_DB5 BV(PA5) +#define LCD_DB6 BV(PA6) +#define LCD_DB7 BV(PA7) +/*@}*/ + +/** + * \name DB high nibble (DB[4-7]) + * @{ + */ +#define LCD_PORT PORTG +#define LCD_DB_PORT PORTA +#define LCD_PIN PING +#define LCD_DB_PIN PINA +#define LCD_DDR DDRG +#define LCD_DB_DDR DDRA + +#if CONFIG_LCD_4BIT + #define LCD_MASK (LCD_DB7 | LCD_DB6 | LCD_DB5 | LCD_DB4) + #define LCD_SHIFT 4 +#else + #define LCD_MASK (uint8_t)0xff + #define LCD_SHIFT 0 +#endif +/*@}*/ + +/** + * \name LCD bus control macros + * @{ + */ +#define LCD_CLR_RS (LCD_PORT &= ~LCD_RS) +#define LCD_SET_RS (LCD_PORT |= LCD_RS) +#define LCD_CLR_RD (LCD_PORT &= ~LCD_RW) +#define LCD_SET_RD (LCD_PORT |= LCD_RW) +#define LCD_CLR_E (LCD_PORT &= ~LCD_E) +#define LCD_SET_E (LCD_PORT |= LCD_E) + +#if CONFIG_LCD_4BIT + #define LCD_WRITE_H(x) (LCD_DB_PORT = (LCD_DB_PORT & ~LCD_MASK) | (((x) >> (4 - LCD_SHIFT)) & LCD_MASK)) + #define LCD_WRITE_L(x) (LCD_DB_PORT = (LCD_DB_PORT & ~LCD_MASK) | (((x) << LCD_SHIFT) & LCD_MASK)) + #define LCD_READ_H ((LCD_DB_PIN & LCD_MASK) >> (4 - LCD_SHIFT)) + #define LCD_READ_L ((LCD_DB_PIN & LCD_MASK) >> LCD_SHIFT) +#else + #define LCD_WRITE(x) (LCD_DB_PORT = (x)) + #define LCD_READ (LCD_DB_PIN) +#endif +/*@}*/ + +/** Set data bus direction to output (write to display) */ +#define LCD_DB_OUT (LCD_DB_DDR |= LCD_MASK) + +/** Set data bus direction to input (read from display) */ +#define LCD_DB_IN (LCD_DB_DDR &= ~LCD_MASK) + +/** Delay for write (Enable pulse width, 220ns) */ +#define LCD_DELAY_WRITE \ + do { \ + NOP; \ + NOP; \ + NOP; \ + NOP; \ + NOP; \ + } while (0) + +/** Delay for read (Data ouput delay time, 120ns) */ +#define LCD_DELAY_READ \ + do { \ + NOP; \ + NOP; \ + NOP; \ + NOP; \ + } while (0) + + +INLINE void lcd_bus_init(void) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + LCD_PORT = (LCD_PORT & ~(LCD_E | LCD_RW)) | LCD_RS; + LCD_DDR |= LCD_RS | LCD_RW | LCD_E; + + /* + * Data bus is in output state most of the time: + * LCD r/w functions assume it is left in output state + */ + LCD_DB_OUT; + + + IRQ_RESTORE(flags); +} + +#endif /* HW_LCD_H */ diff --git a/bertos/hw/hw_mcp41.c b/bertos/hw/hw_mcp41.c new file mode 100644 index 00000000..88cd4ea0 --- /dev/null +++ b/bertos/hw/hw_mcp41.c @@ -0,0 +1,55 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief MCP41 hardware-specific definitions + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#include + +#include +#include + +#include + + +const uint16_t mcp41_ports[MCP41_CNT] = { + _SFR_IO_ADDR(PORTB), /** Led pot */ + _SFR_IO_ADDR(PORTB), /** Photometer pot */ + }; +const uint8_t mcp41_pins [MCP41_CNT] = { + BV(PB7), + BV(PB6), + }; diff --git a/bertos/hw/hw_mcp41.h b/bertos/hw/hw_mcp41.h new file mode 100644 index 00000000..8dd6297e --- /dev/null +++ b/bertos/hw/hw_mcp41.h @@ -0,0 +1,71 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief MCP41 hardware-specific definitions + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#ifndef HW_MCP41_H +#define HW_MCP41_H + +#include +#include +#include +#include + +extern const uint16_t mcp41_ports[MCP41_CNT]; +extern const uint8_t mcp41_pins[MCP41_CNT]; + +/** + * Set MCP41 port associated with \a dev to output. + */ +INLINE void SET_MCP41_DDR(Mcp41Dev dev) +{ + /* DDR port is 1 address before PORT */ + ATOMIC(_SFR_IO8(mcp41_ports[dev] - 1) |= mcp41_pins[dev]); +} + +INLINE void MCP41_ON(Mcp41Dev i) +{ + ATOMIC(_SFR_IO8(mcp41_ports[i]) &= ~mcp41_pins[i]); +} + +INLINE void MCP41_OFF(Mcp41Dev i) +{ + ATOMIC(_SFR_IO8(mcp41_ports[i]) |= mcp41_pins[i]); +} + + +#endif /* HW_MCP41_H */ diff --git a/bertos/hw/hw_tc520.h b/bertos/hw/hw_tc520.h new file mode 100644 index 00000000..34501ca5 --- /dev/null +++ b/bertos/hw/hw_tc520.h @@ -0,0 +1,76 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 hardware-specific definitions + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#ifndef HW_TC520_H +#define HW_TC520_H + +#include +#include + +#define CE_PIN PE6 +#define DV_PIN PE5 +#define LOAD_PIN PE3 +#define READ_PIN PE4 + +#define TC520_DDR DDRE +#define TC520_PORT PORTE +#define TC520_PIN PINE + +#define DV_HIGH() (TC520_PIN & BV(DV_PIN)) +#define DV_LOW() (!DV_HIGH()) + +#define CE_HIGH() (TC520_PORT |= BV(CE_PIN)) +#define CE_LOW() (TC520_PORT &= ~BV(CE_PIN)) + +#define LOAD_HIGH() (TC520_PORT |= BV(LOAD_PIN)) +#define LOAD_LOW() (TC520_PORT &= ~BV(LOAD_PIN)) + +#define READ_HIGH() (TC520_PORT |= BV(READ_PIN)) +#define READ_LOW() (TC520_PORT &= ~BV(READ_PIN)) + +#define TC520_HW_INIT \ +do\ +{\ + TC520_PORT |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ + TC520_DDR |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ + TC520_DDR &= ~BV(DV_PIN);\ +}\ +while(0) + +#endif /* HW_TC520_H */ diff --git a/bertos/hw/kbd_map.h b/bertos/hw/kbd_map.h new file mode 100644 index 00000000..f54bbc02 --- /dev/null +++ b/bertos/hw/kbd_map.h @@ -0,0 +1,77 @@ +/** + * \file + * + * + * \brief Keyboard map definitions. + * + * \version $Id$ + * + * \author Francesco Sacchi + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2006/02/10 12:31:03 bernie + *#* Add templates for hw definitions. + *#* + *#*/ + +#ifndef HW_KBD_MAP_H +#define HW_KBD_MAP_H + +#include + + +/** + * Type for keyboard mask. + */ +typedef uint16_t keymask_t; + +/** + * \name Keycodes. + */ +/*@{*/ +#define K_UP BV(0) +#define K_DOWN BV(1) +#define K_OK BV(2) +#define K_CANCEL BV(3) + +#define K_REPEAT BV(14) /**< This is a repeated keyevent. */ +#define K_TIMEOUT BV(15) /**< Fake key event for timeouts. */ +/*@}*/ + + +#endif /* HW_KBD_MAP_H */ diff --git a/bertos/hw/mcp41_map.h b/bertos/hw/mcp41_map.h new file mode 100644 index 00000000..5e083128 --- /dev/null +++ b/bertos/hw/mcp41_map.h @@ -0,0 +1,55 @@ +/** + * \file + * + * + * \brief MCP41 digital potentiometer map definitions. + * + * \version $Id$ + * + * \author Francesco Sacchi + */ + +#ifndef MCP41_MAP_H +#define MCP41_MAP_H + +/** \name Enum for mcp41 pot evices. + * \{ + */ +typedef enum Mcp41Dev +{ + MCP41_LED, + MCP41_PHOTO_GAIN, + + MCP41_CNT, +} Mcp41Dev; +/* \} */ + +#endif /* MCP41_MAP_H */ diff --git a/bertos/icons/Makefile b/bertos/icons/Makefile new file mode 100644 index 00000000..50469549 --- /dev/null +++ b/bertos/icons/Makefile @@ -0,0 +1,45 @@ +# +# $Id: Makefile 18234 2007-10-08 13:39:48Z rasky $ +# Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) +# All rights reserved. +# +# Author: Stefano Fedrigo +# +# $Log$ +# Revision 1.2 2006/09/20 14:18:01 marco +# Use only icons neede by demo. +# +# Revision 1.1 2006/09/19 17:48:00 bernie +# Add temporary logo. +# +# + +# Set to 1 for debug builds +DEBUG = 1 + +RASTERS = logo.raster + +FLIPIMAGE = flipimage +flipimage_SRC = flipimage.cpp +flipimage_OBJ = $(flipimage_SRC:%.cpp=%.o) + +.PHONY: all +all: $(RASTERS) + +# Link rule +$(FLIPIMAGE): $(flipimage_OBJ) + $(CXX) $^ $(flipimage_LIBS) $(LDFLAGS) -o $@ + +.PHONY: clean +clean: + rm -f $(TRG) $(flipimage_OBJ) + rm -f $(RASTERS) + +.PHONY: rasters +rasters: $(FLIPIMAGE) $(RASTERS) + +%.raster: %.png $(FLIPIMAGE) + convert $< txt:- | ./flipimage >$@ + +# Include dependencies +-include *.d diff --git a/bertos/icons/flipimage.cpp b/bertos/icons/flipimage.cpp new file mode 100644 index 00000000..f28af7da --- /dev/null +++ b/bertos/icons/flipimage.cpp @@ -0,0 +1,120 @@ +/** + * \file + * + * + * \version $Id$ + * \author Stefano Fedrigo + * + * \brief Conversion tool from image TXT format to LCD bitmap + */ + +/* + * $Log$ + * Revision 1.1 2006/09/19 17:48:00 bernie + * Add temporary logo. + * + * Revision 1.3 2004/09/24 17:25:32 powersoft + * Fix for new version of ImageMagick. + * + * Revision 1.2 2004/03/13 22:52:54 aleph + * documentation fixes + * + * Revision 1.1 2004/01/26 15:31:17 aleph + * Add boot images and tools for importing them + * + */ + +#include +#include +#include + +#define RASTER_WIDTH 82 +#define RASTER_HEIGHT 64 + +// Minimum color level to consider a pixel on +#define COLOR_THRESHOLD 128 + + +using namespace std; + + +int main(void) +{ + char buf[64]; + int n; + unsigned char mask; + unsigned char line[RASTER_WIDTH]; + + for (int l = 0; l < RASTER_HEIGHT/8; l++) + { + mask = 1; + memset(line, 0, sizeof(line)); + + do + { + for (int x = 0; x < RASTER_WIDTH; x++) + { + if (!cin.getline(buf, sizeof(buf))) + goto print_line; + + istringstream ss(buf); + string s; + char c; + + ss + >> s // skip glob coord spec + >> c // skip open paren + >> n; // this is the red level + + //DEBUG + //cout << "s='" << s << "' n='" << n << "'" << endl; + + if (n < COLOR_THRESHOLD) + line[x] |= mask; + } + } + while (mask <<= 1); + +print_line: + cout << "\n\t"; + for (int x = 0; x < RASTER_WIDTH; x++) + { + printf("0x%02X", line[x]); + if (x % 8 == 7) + cout << ",\n\t"; + else + cout << ", "; + } + cout << endl; + } + + return 0; +} diff --git a/bertos/icons/logo.c b/bertos/icons/logo.c new file mode 100644 index 00000000..651f07bd --- /dev/null +++ b/bertos/icons/logo.c @@ -0,0 +1,116 @@ + +#include "logo.h" +#include +#include + +/** + * BeRTOS logo + */ +const PROGMEM uint8_t bertos_logo_raster[] = { + + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + 0x00, 0xF8, 0xF8, 0xF8, 0x78, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x78, 0x70, 0xF0, 0xF0, 0xE0, 0x80, 0x00, + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x70, 0x70, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x70, 0xF0, 0xE0, 0xE0, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xF1, 0x7F, 0x3F, 0x1F, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x18, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x07, 0x1F, 0xFF, 0xFE, 0xFC, + 0x00, 0x00, 0x07, 0x1F, 0x9F, 0xBC, 0xB8, 0xB8, + 0x30, 0x30, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0xB0, 0xB0, 0xB8, 0xB8, 0xBC, 0x9E, 0x1F, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, + 0x80, 0x00, + + 0x32, 0x3F, 0x3F, 0x3F, 0x3C, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x3C, 0x1C, 0x1F, 0x1F, 0x0F, 0x03, + 0x00, 0x00, 0x00, 0x3F, 0x0D, 0x04, 0x04, 0x0C, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x31, + 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, + 0x24, 0x25, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + +}; + +EXTERN_CONST struct Image bertos_logo = +{ + /* .raster = */ bertos_logo_raster, + /* .width = */ 82, + /* .height = */ 64, + /* .stride = */ 82 +}; + diff --git a/bertos/icons/logo.h b/bertos/icons/logo.h new file mode 100644 index 00000000..e0bbc636 --- /dev/null +++ b/bertos/icons/logo.h @@ -0,0 +1,3 @@ +#include + +extern const struct Image bertos_logo; diff --git a/bertos/icons/logo.png b/bertos/icons/logo.png new file mode 100755 index 00000000..aecad002 Binary files /dev/null and b/bertos/icons/logo.png differ diff --git a/bertos/kern/kfile.c b/bertos/kern/kfile.c new file mode 100644 index 00000000..1ec32664 --- /dev/null +++ b/bertos/kern/kfile.c @@ -0,0 +1,221 @@ +/** + * \file + * + * + * \brief Virtual KFile I/O interface. + * This module implements some generic I/O interfaces for kfile. + * + * \version $Id$ + * \author Francesco Sacchi + * \author Daniele Basile + * + */ + + +#include "kfile.h" +#include + +#include +#include +#include + +/* + * Sanity check for config parameters required by this module. + */ +#if !defined(CONFIG_KFILE_GETS) || ((CONFIG_KFILE_GETS != 0) && CONFIG_KFILE_GETS != 1) + #error CONFIG_KFILE_GETS must be set to either 0 or 1 in appconfig.h +#endif +#if !defined(CONFIG_PRINTF) + #error CONFIG_PRINTF missing in appconfig.h +#endif + + +/** + * Generic putc() implementation using \a fd->write. + */ +int kfile_putc(int _c, struct KFile *fd) +{ + unsigned char c = (unsigned char)_c; + + if (kfile_write(fd, &c, sizeof(c)) == sizeof(c)) + return (int)((unsigned char)_c); + else + return EOF; +} + +/** + * Generic getc() implementation using \a fd->read. + */ +int kfile_getc(struct KFile *fd) +{ + unsigned char c; + + if (kfile_read(fd, &c, sizeof(c)) == sizeof(c)) + return (int)((unsigned char)c); + else + return EOF; +} + +#if CONFIG_PRINTF +/** + * Formatted write. + */ +int kfile_printf(struct KFile *fd, const char *format, ...) +{ + va_list ap; + int len; + + va_start(ap, format); + len = _formatted_write(format, (void (*)(char, void *))kfile_putc, fd, ap); + va_end(ap); + + return len; +} +#endif /* CONFIG_PRINTF */ + +/** + * Write a string to kfile \a fd. + * \return 0 if OK, EOF in case of error. + */ +int kfile_print(struct KFile *fd, const char *s) +{ + while (*s) + { + if (kfile_putc(*s++, fd) == EOF) + return EOF; + } + return 0; +} + +#if CONFIG_KFILE_GETS +/** + * Read a line long at most as size and put it + * in buf. + * \return number of chars read or EOF in case + * of error. + */ +int kfile_gets(struct KFile *fd, char *buf, int size) +{ + return kfile_gets_echo(fd, buf, size, false); +} + + +/** + * Read a line long at most as size and put it + * in buf, with optional echo. + * + * \return number of chars read, or EOF in case + * of error. + */ +int kfile_gets_echo(struct KFile *fd, char *buf, int size, bool echo) +{ + int i = 0; + int c; + + for (;;) + { + if ((c = kfile_getc(fd)) == EOF) + { + buf[i] = '\0'; + return -1; + } + + /* FIXME */ + if (c == '\r' || c == '\n' || i >= size-1) + { + buf[i] = '\0'; + if (echo) + kfile_print(fd, "\r\n"); + break; + } + buf[i++] = c; + if (echo) + kfile_putc(c, fd); + } + + return i; +} +#endif /* !CONFIG_KFILE_GETS */ + + +/** + * Move \a fd file seek position of \a offset bytes from \a whence. + * + * This is a generic implementation of seek function, you can redefine + * it in your local module if needed. + */ +kfile_off_t kfile_genericSeek(struct KFile *fd, kfile_off_t offset, KSeekMode whence) +{ + uint32_t seek_pos; + + switch (whence) + { + + case KSM_SEEK_SET: + seek_pos = 0; + break; + case KSM_SEEK_END: + seek_pos = fd->size; + break; + case KSM_SEEK_CUR: + seek_pos = fd->seek_pos; + break; + default: + ASSERT(0); + return EOF; + break; + } + + /* Bound check */ + if (seek_pos + offset > fd->size) + { + ASSERT(0); + return EOF; + } + + fd->seek_pos = seek_pos + offset; + + return fd->seek_pos; +} + +/** + * Reopen file \a fd. + * This is a generic implementation that only flush file + * and reset seek_pos to 0. + */ +struct KFile * kfile_genericReopen(struct KFile *fd) +{ + kfile_flush(fd); + kfile_seek(fd, 0, KSM_SEEK_SET); + return fd; +} + + diff --git a/bertos/kern/kfile.h b/bertos/kern/kfile.h new file mode 100644 index 00000000..4bb7a238 --- /dev/null +++ b/bertos/kern/kfile.h @@ -0,0 +1,266 @@ +/** + * \file + * + * + * \brief Virtual KFile I/O interface. + * KFile is a generic interface for file I/O. + * It uses an object-oriented model to supply + * a generic interface for drivers to communicate. + * This module contains only definitions, the instance structure + * and an API. + * Each KFile user should implement at least some methods. + * E.G. + * If you have a serial driver and want to comply to KFile interface, + * you have to declare your context structure: + * + * \code + * typedef struct KFileSerial + * { + * KFile fd; + * Serial *ser; + * } KFileSerial; + * \endcode + * + * You should also supply a macro for casting KFile to KFileSerial: + * + * \code + * INLINE KFileSerial * KFILESERIAL(KFile *fd) + * { + * ASSERT(fd->_type == KFT_SERIAL); + * return (KFileSerial *)fd; + * } + * \endcode + * + * Then you can implement as much interface functions as you like + * and leave the others to NULL. + * ser_close implementation example: + * + * \code + * static int ser_kfile_close(struct KFile *fd) + * { + * KFileSerial *fds = KFILESERIAL(fd); + * ser_close(fds->ser); + * return 0; + * } + * \endcode + * KFILESERIAL macro helps to ensure that obj passed is really a Serial. + * + * KFile interface do not supply the open function: this is deliberate, + * because in embedded systems each device has its own init parameters. + * For the same reason specific file settings (like baudrate for Serial, for example) + * are demanded to specific driver implementation. + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + * \author Daniele Basile + */ + +#ifndef KERN_KFILE_H +#define KERN_KFILE_H + +#include +#include +#include + +/* fwd decl */ +struct KFile; + +typedef int32_t kfile_off_t; ///< KFile offset type, used by kfile_seek function. + +/** + * Costants for repositioning read/write file offset. + * These are needed because on some embedded platforms + * ANSI I/O library may not be present. + */ +typedef enum KSeekMode +{ + KSM_SEEK_SET, ///< Seek from file beginning. + KSM_SEEK_CUR, ///< Seek from file current position. + KSM_SEEK_END, ///< Seek from file end. +} KSeekMode; + +/** + * Prototypes for KFile access functions. + * I/O file functions must be ANSI compliant. + * \note A KFile user can choose which function subset to implement, + * but has to set to NULL unimplemented features. + * \{ + */ + +/** + * Read from file. + * \return the number of bytes read. + */ +typedef size_t (*ReadFunc_t) (struct KFile *fd, void *buf, size_t size); + +/** + * Write to file. + * \return the number of bytes written. + */ +typedef size_t (*WriteFunc_t) (struct KFile *fd, const void *buf, size_t size); + +/** + * Seek into file (if seekable). + * \return the new file offset or EOF on errors. + */ +typedef kfile_off_t (*SeekFunc_t) (struct KFile *fd, kfile_off_t offset, KSeekMode whence); + +/** + * Close and reopen file \a fd. + * The reopening is done with the former file parameters and access modes. + */ +typedef struct KFile * (*ReOpenFunc_t) (struct KFile *fd); + +/** + * Close file. + * \return 0 on success, EOF on errors. + */ +typedef int (*CloseFunc_t) (struct KFile *fd); + +/** + * Flush file I/O. + * \return 0 on success, EOF on errors. + */ +typedef int (*FlushFunc_t) (struct KFile *fd); + +/** + * Get file error mask. + * \return 0 on success or file error code, device specific. + */ +typedef int (*ErrorFunc_t) (struct KFile *fd); + +/** + * Clear errors. + */ +typedef void (*ClearErrFunc_t) (struct KFile *fd); +/* \} */ + +/** + * Context data for callback functions which operate on + * pseudo files. + * \note If you change interface, remember to add corresponding access function. + */ +typedef struct KFile +{ + ReadFunc_t read; + WriteFunc_t write; + ReOpenFunc_t reopen; + CloseFunc_t close; + SeekFunc_t seek; + FlushFunc_t flush; + ErrorFunc_t error; + ClearErrFunc_t clearerr; + DB(id_t _type); ///< Used to keep trace, at runtime, of obj type. + + /* NOTE: these must _NOT_ be size_t on 16bit CPUs! */ + uint32_t seek_pos; + uint32_t size; +} KFile; + +/** + * Generic implementation of kfile_seek. + */ +kfile_off_t kfile_genericSeek(struct KFile *fd, kfile_off_t offset, KSeekMode whence); + +/** + * Generic implementation of kfile_reopen. + */ +struct KFile * kfile_genericReopen(struct KFile *fd); + +int kfile_putc(int c, struct KFile *fd); ///< Generic putc implementation using kfile_write. +int kfile_getc(struct KFile *fd); ///< Generic getc implementation using kfile_read. +int kfile_printf(struct KFile *fd, const char *format, ...); +int kfile_print(struct KFile *fd, const char *s); +int kfile_gets(struct KFile *fd, char *buf, int size); +int kfile_gets_echo(struct KFile *fd, char *buf, int size, bool echo); + +/** + * Interface functions for KFile access. + * \note Remember to change following functions if KFile interface changes. + * \{ + */ +INLINE size_t kfile_read(struct KFile *fd, void *buf, size_t size) +{ + ASSERT(fd->read); + return fd->read(fd, buf, size); +} + +INLINE size_t kfile_write(struct KFile *fd, const void *buf, size_t size) +{ + ASSERT(fd->write); + return fd->write(fd, buf, size); +} + +INLINE KFile * kfile_reopen(struct KFile *fd) +{ + ASSERT(fd->reopen); + return fd->reopen(fd); +} + +INLINE int kfile_close(struct KFile *fd) +{ + ASSERT(fd->close); + return fd->close(fd); +} + +INLINE kfile_off_t kfile_seek(struct KFile *fd, kfile_off_t offset, KSeekMode whence) +{ + ASSERT(fd->seek); + return fd->seek(fd, offset, whence); +} + +INLINE int kfile_flush(struct KFile *fd) +{ + ASSERT(fd->flush); + return fd->flush(fd); +} + +INLINE int kfile_error(struct KFile *fd) +{ + ASSERT(fd->error); + return fd->error(fd); +} + +INLINE void kfile_clearerr(struct KFile *fd) +{ + ASSERT(fd->clearerr); + fd->clearerr(fd); +} +/* \} */ + +/** + * Kfile test function. + */ +bool kfile_test(KFile *fd, uint8_t *test_buf, uint8_t *save_buf, size_t size); + +#endif /* KERN_KFILE_H */ diff --git a/bertos/kern/kfile_test.c b/bertos/kern/kfile_test.c new file mode 100644 index 00000000..76e78092 --- /dev/null +++ b/bertos/kern/kfile_test.c @@ -0,0 +1,248 @@ +/** + * \file + * + * + * \brief Test suite for virtual KFile I/O interface. + * This module implements a test for some generic I/O interfaces for kfile. + * + * \version $Id$ + * \author Francesco Sacchi + * \author Daniele Basile + * + */ + + +#include "kfile.h" +#include + +#include +#include +#include + +/** + * KFile read/write subtest. + * Try to write/read in the same \a f file location \a size bytes. + * \return true if all is ok, false otherwise + * \note Restore file position at exit (if no error) + * \note Test buffer \a buf must be filled with + * the following statement: + *
+ * buf[i] = i & 0xff
+ * 
+ */ +static bool kfile_rwTest(KFile *f, uint8_t *buf, size_t size) +{ + /* + * Write test buffer + */ + if (kfile_write(f, buf, size) != size) + return false; + + kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR); + + /* + * Reset test buffer + */ + memset(buf, 0, size); + + /* + * Read file in test buffer + */ + if (kfile_read(f, buf, size) != size) + return false; + kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR); + + /* + * Check test result + */ + for (size_t i = 0; i < size; i++) + if (buf[i] != (i & 0xff)) + return false; + + return true; +} + +/** + * KFile read/write test. + * This function write and read \a test_buf long \a size + * on \a fd handler. + * \a save_buf can be NULL or a buffer where to save previous file content. + */ +bool kfile_test(KFile *fd, uint8_t *test_buf, uint8_t *save_buf, size_t size) +{ + /* + * Part of test buf size that you would write. + * This var is used in test 3 to check kfile_write + * when writing beyond filesize limit. + */ + kfile_off_t len = size / 2; + + + /* Fill test buffer */ + for (size_t i = 0; i < size; i++) + test_buf[i] = (i & 0xff); + + /* + * If necessary, user can save content, + * for later restore. + */ + if (save_buf) + { + kfile_read(fd, save_buf, size); + kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); + } + + /* TEST 1 BEGIN. */ + kprintf("Test 1: write from pos 0 to [%lu]\n", size); + + /* + * Seek to addr 0. + */ + if (kfile_seek(fd, 0, KSM_SEEK_SET) != 0) + goto kfile_test_end; + + /* + * Test read/write to address 0..size + */ + if (!kfile_rwTest(fd, test_buf, size)) + goto kfile_test_end; + + kprintf("Test 1: ok!\n"); + + /* + * Restore previous read content. + */ + if (save_buf) + { + kfile_seek(fd, 0, KSM_SEEK_SET); + + if (kfile_write(fd, save_buf, size) != size) + goto kfile_test_end; + + kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); + } + /* TEST 1 END. */ + + /* TEST 2 BEGIN. */ + kprintf("Test 2: write from pos [%lu] to [%lu]\n", fd->size/2 , fd->size/2 + size); + + /* + * Go to half test size. + */ + kfile_seek(fd, (fd->size / 2), KSM_SEEK_SET); + + /* + * If necessary, user can save content + * for later restore. + */ + if (save_buf) + { + kfile_read(fd, save_buf, size); + kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR); + kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); + } + + /* + * Test read/write to address filesize/2 ... filesize/2 + size + */ + if (!kfile_rwTest(fd, test_buf, size)) + goto kfile_test_end; + + kprintf("Test 2: ok!\n"); + + /* + * Restore previous content. + */ + if (save_buf) + { + kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR); + + if (kfile_write(fd, save_buf, size) != size) + goto kfile_test_end; + + kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); + } + + /* TEST 2 END. */ + + /* TEST 3 BEGIN. */ + kprintf("Test 3: write outside of fd->size limit [%lu]\n", fd->size); + kprintf("This test should FAIL!, you must see an assertion fail message.\n"); + + /* + * Go to the Flash end + */ + kfile_seek(fd, -len, KSM_SEEK_END); + + /* + * If necessary, user can save content, + * for later restore. + */ + if (save_buf) + { + kfile_read(fd, save_buf, len); + kfile_seek(fd, -len, KSM_SEEK_CUR); + kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + len); + } + + /* + * Test read/write to address (filesize - size) ... filesize + */ + if (kfile_rwTest(fd, test_buf, size)) + goto kfile_test_end; + + kprintf("Test 3: ok!\n"); + + /* + * Restore previous read content + */ + if (save_buf) + { + kfile_seek(fd, -len, KSM_SEEK_END); + + if (kfile_write(fd, save_buf, len) != len) + goto kfile_test_end; + + kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + len); + } + + /* TEST 3 END. */ + + kfile_close(fd); + return true; + +kfile_test_end: + kfile_close(fd); + return false; +} + + + diff --git a/bertos/kern/monitor.c b/bertos/kern/monitor.c new file mode 100644 index 00000000..96b563e1 --- /dev/null +++ b/bertos/kern/monitor.c @@ -0,0 +1,174 @@ +/** + * \file + * + * + * \brief Monitor to check for stack overflows + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + + +#include "monitor.h" + +#if CONFIG_KERN_MONITOR + +#include "proc_p.h" +#include +#include +#include +#include +#include + + +static List MonitorProcs; + + +void monitor_init(void) +{ + LIST_INIT(&MonitorProcs); +} + + +void monitor_add(Process* proc, const char* name, cpustack_t* stack_base, size_t stack_size) +{ + proc->monitor.name = name; + proc->monitor.stack_base = stack_base; + proc->monitor.stack_size = stack_size; + + ADDTAIL(&MonitorProcs, &proc->monitor.link); +} + + +void monitor_remove(Process* proc) +{ + REMOVE(&proc->monitor.link); +} + +void monitor_rename(Process *proc, const char* name) +{ + proc->monitor.name = name; +} + +/* TODO: use containerof() */ +#define MONITOR_NODE_TO_PROCESS(node) \ + (struct Process *)((intptr_t)(node) - offsetof(struct Process, monitor.link)) + +size_t monitor_checkStack(cpustack_t* stack_base, size_t stack_size) +{ + cpustack_t* beg; + cpustack_t* cur; + cpustack_t* end; + size_t sp_free; + + beg = stack_base; + end = stack_base + stack_size / sizeof(cpustack_t) - 1; + + if (CPU_STACK_GROWS_UPWARD) + { + cur = beg; + beg = end; + end = cur; + } + + cur = beg; + while (cur != end) + { + if (*cur != CONFIG_KERN_STACKFILLCODE) + break; + + if (CPU_STACK_GROWS_UPWARD) + cur--; + else + cur++; + } + + sp_free = ABS(cur - beg) * sizeof(cpustack_t); + return sp_free; +} + + +void monitor_report(void) +{ + struct Process* p; + int i; + + if (LIST_EMPTY(&MonitorProcs)) + { + kputs("No stacks registered in the monitor\n"); + return; + } + + kprintf("%-24s%-8s%-8s%-8s%-8s\n", "Process name", "TCB", "SPbase", "SPsize", "SPfree"); + for (i=0;i<56;i++) + kputchar('-'); + kputchar('\n'); + + for (p = MONITOR_NODE_TO_PROCESS(LIST_HEAD(&MonitorProcs)); + p->monitor.link.succ; + p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ)) + { + size_t free = monitor_checkStack(p->monitor.stack_base, p->monitor.stack_size); + kprintf("%-24s%-8p%-8p%-8lu%-8lu\n", + p->monitor.name, p, p->monitor.stack_base, p->monitor.stack_size, free); + } +} + + +static void NORETURN monitor(void) +{ + struct Process *p; + + while (1) + { + for (p = MONITOR_NODE_TO_PROCESS(LIST_HEAD(&MonitorProcs)); + p->monitor.link.succ; + p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ)) + { + size_t free = monitor_checkStack(p->monitor.stack_base, p->monitor.stack_size); + + if (free < 0x20) + kprintf("MONITOR: WARNING: Free stack for process '%s' is only %u chars\n", + p->monitor.name, (unsigned int)free); + + timer_delay(500); + } + } +} + + +void monitor_start(size_t stacksize, cpustack_t *stack) +{ + proc_new(monitor, NULL, stacksize, stack); +} + +#endif /* CONFIG_KERN_MONITOR */ diff --git a/bertos/kern/monitor.h b/bertos/kern/monitor.h new file mode 100644 index 00000000..95bbb6db --- /dev/null +++ b/bertos/kern/monitor.h @@ -0,0 +1,77 @@ +/** + * \file + * + * + * \brief Monitor to check for stack overflows + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +#ifndef KERN_MONITOR_H +#define KERN_MONITOR_H + +#include +#include + +#if CONFIG_KERN_MONITOR + +/** + * Start the kernel monitor. It is a special process which checks every second the stacks of the + * running processes trying to detect stack overflows. + * + * \param stacksize Size of stack in chars + * \param stack Pointer to the stack that will be used by the monitor + * + * \note The stack is provided by the caller so that there is no wasted space if the monitor + * is not used. + */ +void monitor_start(size_t stacksize, cpustack_t *stack); + + +/** + * Manually check if a given stack has overflown. This is used to check for stacks + * of processes handled externally form the kernel, or for other stacks (for instance + * the interrupt supervisor stack). + * + * \note For this function to work, the stack must have been filled at startup with + * CONFIG_KERN_STACKFILLCODE. + */ +size_t monitor_checkStack(cpustack_t *stack_base, size_t stack_size); + + +/** Print a report of the stack status through kdebug */ +void monitor_report(void); + + +#endif /* CONFIG_KERN_MONITOR */ +#endif /* KERN_MONITOR_H */ diff --git a/bertos/kern/msg.h b/bertos/kern/msg.h new file mode 100644 index 00000000..e4ee21f9 --- /dev/null +++ b/bertos/kern/msg.h @@ -0,0 +1,286 @@ +/** + * \file + * + * + * + * This module implements a common system for executing + * a user defined action calling a hook function. + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Simple inter-process messaging system + * + * Handle queues of messages associated an action. + * + * A message port is an abstraction used to exchange information + * asynchronously between processes or other entities such as + * interrupts and call-back functions. + * + * This form of IPC is higher-level than bare signals and + * semaphores, because it sets a policy for exchanging + * structured data with well-defined synchronization and + * ownership semantics. + * + * Before using it, a message port must be initialized by + * calling msg_initPort(), which associates the port with + * an Event object, which can be setup to signal a process + * or invoke a call-back hook. + * + * A process or interrupt routine can deliver messages to any + * message port by calling msg_put(). By sending a message, + * the sender temporarly or permanently transfers ownership + * of its associated data to the receiver. + * + * Queuing a message to a port automatically triggers the + * associated Event to notify the receiver. When the + * receiver wakes up, it usually invokes msg_get() to pick + * the next message from the port. + * + * Message ports can hold any number of pending messages, + * and receivers usually process them in FIFO order. + * Other scheduling policies are possible, but not implemented + * in this API. + * + * After the receiver has done processing a message, it replies + * it back to the sender with msg_reply(), which transfer + * ownership back to the original sender. Replies are delivered + * to a reply port, which is nothing more than another MsgPort + * structure designated by the sender. + * + * Returning messages to senders is not mandatory, but it provides + * a convenient way to provide some kind of result and simplify + * the resource allocation scheme at the same time. + * + * When using signals to receive messages in a process, you + * call sig_wait() in an event-loop to wake up when messages + * are delivered to any of your ports. When your process + * wakes up with the port signal active, multiple messages + * may already have queued up at the message port, and the + * process must process them all before returning to sleep. + * Signals don't keep a nesting count. + * + * A simple message loop works like this: + * + * \code + * // Our message port. + * static MsgPort test_port; + * + * // A test message with two parameters and a result. + * typedef struct + * { + * Msg msg; + * + * int x, y; + * int result; + * } TestMsg; + * + * + * // A process that sends two messages and waits for replies. + * static void sender_proc(void) + * { + * MsgPort test_reply_port; + * TestMsg msg1; + * TestMsg msg2; + * Msg *reply; + * + * msg_initPort(&reply_port, + * event_createSignal(proc_current(), SIGF_SINGLE); + * + * // Fill-in first message and send it out. + * msg1.x = 3; + * msg1.y = 2; + * msg1.msg.replyPort = &test_reply_port; + * msg_put(&test_port, &msg1); + * + * // Fill-in second message and send it out too. + * msg2.x = 5; + * msg2.y = 4; + * msg2.msg.replyPort = &test_reply_port; + * msg_put(&test_port, &msg1); + * + * // Wait for a reply... + * sig_wait(SIG_SINGLE); + * + * reply = (TestMsg *)msg_get(&test_reply_port); + * ASSERT(reply != NULL); + * ASSERT(reply->result == 5); + * + * // Get reply to second message. + * while (!(reply = (TestMsg *)msg_get(&test_reply_port)) + * { + * // Not yet, be patient and wait some more. + * sig_wait(SIG_SINGLE); + * } + * + * ASSERT(reply->result == 9); + * } + * + * + * // Receive messages and do something boring with them. + * static void receiver_proc(void) + * { + * msg_initPort(&test_port, + * event_createSignal(proc_current(), SIGF_EXAMPLE); + * + * proc_new(sender_proc, (iptr_t)&test_port, + * sender_stack, sizeof(sender_stack); + * + * for (;;) + * { + * sigmask_t sigs = sig_wait(SIGF_EXAMPLE | more_signals); + * + * if (sigs & SIGF_EXAMPLE) + * { + * TestMsg *emsg; + * while (emsg = (TestMsg *)msg_get(&test_port) + * { + * // Do something with the message + * emsg->result = emsg->x + emsg->y; + * msg_reply((Msg *)msg); + * } + * } + * } + * } + * \endcode + */ + + */ + +#ifndef KERN_MSG_H +#define KERN_MSG_H + +#include "event.h" +#include + + +typedef struct MsgPort +{ + List queue; /**< Messages queued at this port. */ + Event event; /**< Event to trigger when a message arrives. */ +} MsgPort; + + +typedef struct Msg +{ + Node link; /**< Link into message port queue. */ + MsgPort *replyPort; /**< Port to which the msg is to be replied. */ + /* User data may follow */ +} Msg; + + +/** + * Lock a message port. + * + * This is required before reading or manipulating + * any field of the MsgPort structure. + * + * \note Ports may be locked multiple times and each + * call to msg_lockPort() must be paired with + * a corresponding call to msg_unlockPort(). + * + * \todo Add a configurable policy for locking against + * interrupts and locking with semaphorse. + * + * \see msg_unlockPort() + */ +INLINE void msg_lockPort(MsgPort *port) +{ + proc_forbid(); +} + +/** + * Unlock a message port. + * + * \see msg_lockPort() + */ +INLINE void msg_unlockPort(MsgPort *port) +{ + proc_permit(); +} + + +/** Initialize a message port */ +INLINE void msg_initPort(MsgPort *port, Event event) +{ + LIST_INIT(&port->queue); + port->event = event; +} + +/** Queue \a msg into \a port, triggering the associated event */ +INLINE void msg_put(MsgPort *port, Msg *msg) +{ + msg_portLock(port); + ADDTAIL(&port->queue, &msg->link); + msg_portUnlock(port); + + event_do(&port->event); +} + +/** + * Get the first message from the queue of \a port. + * + * \return Pointer to the message or NULL if the port was empty. + */ +INLINE Msg *msg_get(MsgPort *port) +{ + Msg *msg; + + msg_portLock(port); + msg = (Msg *)REMHEAD(&port->queue); + msg_portUnlock(port); + + return msg; +} + +/** Peek the first message in the queue of \a port, or NULL if the port is empty. */ +INLINE Msg *msg_peek(MsgPort *port) +{ + Msg *msg; + + msg_portLock(port); + msg = (Msg *)port->queue.head; + if (ISLISTEMPTY(&port->queue)) + msg = NULL; + msg_portUnlock(port); + + return msg; +} + +/** Send back (reply) \a msg to its sender. */ +INLINE void msg_reply(Msg *msg) +{ + msg_put(msg->replyPort, msg); +} + +#endif /* KERN_MSG_H */ diff --git a/bertos/kern/proc.c b/bertos/kern/proc.c new file mode 100644 index 00000000..a9e95624 --- /dev/null +++ b/bertos/kern/proc.c @@ -0,0 +1,416 @@ +/** + * \file + * + * + * \brief Simple realtime multitasking scheduler. + * Context switching is only done cooperatively. + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + + +#include "proc_p.h" +#include "proc.h" +//#include "hw.h" +#include +#include +#include +#include +#include +#include +#include /* ARCH_EMUL */ +#include /* ABS() */ + +#include /* memset() */ + +/** + * CPU dependent context switching routines. + * + * \note This function *MUST* preserve also the status of the interrupts. + */ +EXTERN_C void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp); +EXTERN_C int asm_switch_version(void); + +/* + * The scheduer tracks ready and waiting processes + * by enqueuing them in these lists. A pointer to the currently + * running process is stored in the CurrentProcess pointer. + * + * NOTE: these variables are protected by DI/EI locking + */ +REGISTER Process *CurrentProcess; +REGISTER List ProcReadyList; + + +#if CONFIG_KERN_PREEMPTIVE +/* + * The time sharing scheduler forces a task switch when + * the current process has consumed its quantum. + */ +uint16_t Quantum; +#endif + + +/* In Win32 we must emulate stack on the real process stack */ +#if (ARCH & ARCH_EMUL) +extern List StackFreeList; +#endif + +/** The main process (the one that executes main()). */ +struct Process MainProcess; + + +static void proc_init_struct(Process *proc) +{ + /* Avoid warning for unused argument. */ + (void)proc; + +#if CONFIG_KERN_SIGNALS + proc->sig_recv = 0; +#endif + +#if CONFIG_KERN_PREEMPTIVE + proc->forbid_cnt = 0; +#endif + +#if CONFIG_KERN_HEAP + proc->flags = 0; +#endif +} + +MOD_DEFINE(proc); + +void proc_init(void) +{ + LIST_INIT(&ProcReadyList); + +#if CONFIG_KERN_MONITOR + monitor_init(); +#endif + + /* We "promote" the current context into a real process. The only thing we have + * to do is create a PCB and make it current. We don't need to setup the stack + * pointer because it will be written the first time we switch to another process. + */ + proc_init_struct(&MainProcess); + CurrentProcess = &MainProcess; + + /* Make sure the assembly routine is up-to-date with us */ + ASSERT(asm_switch_version() == 1); + MOD_INIT(proc); +} + + +/** + * Create a new process, starting at the provided entry point. + * + * \return Process structure of new created process + * if successful, NULL otherwise. + */ +struct Process *proc_new_with_name(UNUSED(const char *, name), void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack_base) +{ + Process *proc; + size_t i; + size_t proc_size_words = ROUND2(sizeof(Process), sizeof(cpustack_t)) / sizeof(cpustack_t); +#if CONFIG_KERN_HEAP + bool free_stack = false; +#endif + +#if (ARCH & ARCH_EMUL) + /* Ignore stack provided by caller and use the large enough default instead. */ + stack_base = (cpustack_t *)LIST_HEAD(&StackFreeList); + REMOVE(LIST_HEAD(&StackFreeList)); + stacksize = CONFIG_PROC_DEFSTACKSIZE; +#elif CONFIG_KERN_HEAP + /* Did the caller provide a stack for us? */ + if (!stack_base) + { + /* Did the caller specify the desired stack size? */ + if (!stacksize) + stacksize = CONFIG_PROC_DEFSTACKSIZE + sizeof(Process); + + /* Allocate stack dinamically */ + if (!(stack_base = heap_alloc(stacksize))) + return NULL; + + free_stack = true; + } +#else + /* Stack must have been provided by the user */ + ASSERT(stack_base); + ASSERT(stacksize); +#endif + +#if CONFIG_KERN_MONITOR + /* Fill-in the stack with a special marker to help debugging */ + memset(stack_base, CONFIG_KERN_STACKFILLCODE, stacksize / sizeof(cpustack_t)); +#endif + + /* Initialize the process control block */ + if (CPU_STACK_GROWS_UPWARD) + { + proc = (Process*)stack_base; + proc->stack = stack_base + proc_size_words; + if (CPU_SP_ON_EMPTY_SLOT) + proc->stack++; + } + else + { + proc = (Process*)(stack_base + stacksize / sizeof(cpustack_t) - proc_size_words); + proc->stack = (cpustack_t*)proc; + if (CPU_SP_ON_EMPTY_SLOT) + proc->stack--; + } + + proc_init_struct(proc); + proc->user_data = data; + +#if CONFIG_KERN_HEAP + proc->stack_base = stack_base; + proc->stack_size = stack_size; + if (free_stack) + proc->flags |= PF_FREESTACK; +#endif + + /* Initialize process stack frame */ + CPU_PUSH_CALL_CONTEXT(proc->stack, proc_exit); + CPU_PUSH_CALL_CONTEXT(proc->stack, entry); + + /* Push a clean set of CPU registers for asm_switch_context() */ + for (i = 0; i < CPU_SAVED_REGS_CNT; i++) + CPU_PUSH_WORD(proc->stack, CPU_REG_INIT_VALUE(i)); + + /* Add to ready list */ + ATOMIC(SCHED_ENQUEUE(proc)); + +#if CONFIG_KERN_MONITOR + monitor_add(proc, name, stack_base, stacksize); +#endif + + return proc; +} + +/** Rename a process */ +void proc_rename(struct Process *proc, const char *name) +{ +#if CONFIG_KERN_MONITOR + monitor_rename(proc, name); +#else + (void)proc; (void)name; +#endif +} + + +/** + * System scheduler: pass CPU control to the next process in + * the ready queue. + * + * Saving and restoring the context on the stack is done + * by a CPU-dependent support routine which must usually be + * written in assembly. + */ +void proc_schedule(void) +{ + struct Process *old_process; + cpuflags_t flags; + + /* Remember old process to save its context later */ + old_process = CurrentProcess; + +#ifdef IRQ_RUNNING + /* Scheduling in interrupts is a nono. */ + ASSERT(!IRQ_RUNNING()); +#endif + + /* Poll on the ready queue for the first ready process */ + IRQ_SAVE_DISABLE(flags); + while (!(CurrentProcess = (struct Process *)list_remHead(&ProcReadyList))) + { + /* + * Make sure we physically reenable interrupts here, no matter what + * the current task status is. This is important because if we + * are idle-spinning, we must allow interrupts, otherwise no + * process will ever wake up. + * + * During idle-spinning, can occur an interrupt, it may be able to + * modify \p ProcReadyList. To ensure that compiler reload this + * variable every while cycle we call CPU_MEMORY_BARRIER. + * The memory barrier ensure that all variables used in this context + * are reloaded. + * \todo If there was a way to write sig_wait() so that it does not + * disable interrupts while waiting, there would not be any + * reason to do this. + */ + IRQ_ENABLE; + CPU_IDLE; + MEMORY_BARRIER; + IRQ_DISABLE; + } + IRQ_RESTORE(flags); + + /* + * Optimization: don't switch contexts when the active + * process has not changed. + */ + if (CurrentProcess != old_process) + { + cpustack_t *dummy; + +#if CONFIG_KERN_PREEMPTIVE + /* Reset quantum for this process */ + Quantum = CONFIG_KERN_QUANTUM; +#endif + + /* Save context of old process and switch to new process. If there is no + * old process, we save the old stack pointer into a dummy variable that + * we ignore. In fact, this happens only when the old process has just + * exited. + * TODO: Instead of physically clearing the process at exit time, a zombie + * list should be created. + */ + asm_switch_context(&CurrentProcess->stack, old_process ? &old_process->stack : &dummy); + } + + /* This RET resumes the execution on the new process */ +} + + +/** + * Terminate the current process + */ +void proc_exit(void) +{ +#if CONFIG_KERN_MONITOR + monitor_remove(CurrentProcess); +#endif + +#if CONFIG_KERN_HEAP + /* + * The following code is BROKEN. + * We are freeing our own stack before entering proc_schedule() + * BAJO: A correct fix would be to rearrange the scheduler with + * an additional parameter which frees the old stack/process + * after a context switch. + */ + if (CurrentProcess->flags & PF_FREESTACK) + heap_free(CurrentProcess->stack_base, CurrentProcess->stack_size); + heap_free(CurrentProcess); +#endif + +#if (ARCH & ARCH_EMUL) +#warning This is wrong + /* Reinsert process stack in free list */ + ADDHEAD(&StackFreeList, (Node *)(CurrentProcess->stack + - (CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)))); + + /* + * NOTE: At this point the first two words of what used + * to be our stack contain a list node. From now on, we + * rely on the compiler not reading/writing the stack. + */ +#endif /* ARCH_EMUL */ + + CurrentProcess = NULL; + proc_schedule(); + /* not reached */ +} + + +/** + * Co-operative context switch + */ +void proc_switch(void) +{ + cpuflags_t flags; + + IRQ_SAVE_DISABLE(flags); + SCHED_ENQUEUE(CurrentProcess); + IRQ_RESTORE(flags); + + proc_schedule(); +} + + +/** + * Get the pointer to the current process + */ +struct Process *proc_current(void) +{ + return CurrentProcess; +} + +/** + * Get the pointer to the user data of the current process + */ +iptr_t proc_current_user_data(void) +{ + return CurrentProcess->user_data; +} + + +#if CONFIG_KERN_PREEMPTIVE + +/** + * Disable preemptive task switching. + * + * The scheduler maintains a per-process nesting counter. Task switching is + * effectively re-enabled only when the number of calls to proc_permit() + * matches the number of calls to proc_forbid(). + * + * Calling functions that could sleep while task switching is disabled + * is dangerous, although supported. Preemptive task switching is + * resumed while the process is sleeping and disabled again as soon as + * it wakes up again. + * + * \sa proc_permit() + */ +void proc_forbid(void) +{ + /* No need to protect against interrupts here. */ + ++CurrentProcess->forbid_cnt; +} + +/** + * Re-enable preemptive task switching. + * + * \sa proc_forbid() + */ +void proc_permit(void) +{ + /* No need to protect against interrupts here. */ + --CurrentProcess->forbid_cnt; +} + +#endif /* CONFIG_KERN_PREEMPTIVE */ diff --git a/bertos/kern/proc.h b/bertos/kern/proc.h new file mode 100644 index 00000000..cec57487 --- /dev/null +++ b/bertos/kern/proc.h @@ -0,0 +1,85 @@ +/** + * \file + * + * + * \brief Process scheduler (public interface). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ +#ifndef KERN_PROC_H +#define KERN_PROC_H + +#include +#include +#include + +/* Fwd decl */ +struct Process; + +/* Task scheduling services */ +void proc_init(void); +struct Process *proc_new_with_name(const char* name, void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack); + +#if !CONFIG_KERN_MONITOR + #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack)) +#else + #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack)) +#endif + +void proc_exit(void); +void proc_switch(void); +void proc_test(void); +struct Process *proc_current(void); +iptr_t proc_current_user_data(void); +void proc_rename(struct Process *proc, const char* name); + +#if CONFIG_KERN_PREEMPTIVE + void proc_forbid(void); + void proc_permit(void); +#else + INLINE void proc_forbid(void) { /* nop */ } + INLINE void proc_permit(void) { /* nop */ } +#endif + +/** + * Execute a block of \a CODE atomically with respect to task scheduling. + */ +#define PROC_ATOMIC(CODE) \ + do { \ + proc_forbid(); \ + CODE; \ + proc_permit(); \ + } while(0) + +#endif /* KERN_PROC_H */ diff --git a/bertos/kern/proc_p.h b/bertos/kern/proc_p.h new file mode 100644 index 00000000..8fbb0ed0 --- /dev/null +++ b/bertos/kern/proc_p.h @@ -0,0 +1,120 @@ +/** + * \file + * + * + * \brief Internal scheduler structures and definitions for processes. + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#ifndef KERN_PROC_P_H +#define KERN_PROC_P_H + +#include +#include /* for cpu_stack_t */ +#include +#include +#include + +typedef struct Process +{ + Node link; /**< Link Process into scheduler lists */ + cpustack_t *stack; /**< Per-process SP */ + iptr_t user_data; /**< Custom data passed to the process */ + +#if CONFIG_KERN_SIGNALS + sigmask_t sig_wait; /**< Signals the process is waiting for */ + sigmask_t sig_recv; /**< Received signals */ +#endif + +#if CONFIG_KERN_PREEMPTIVE + int forbid_cnt; /**< Nesting count for proc_forbid()/proc_permit(). */ +#endif + +#if CONFIG_KERN_HEAP + uint16_t flags; /**< Flags */ + cpustack_t *stack_base; /**< Base of process stack */ + size_t stack_size; /**< Size of process stack */ +#endif + +#if CONFIG_KERN_MONITOR + struct ProcMonitor + { + Node link; + const char *name; + cpustack_t *stack_base; + size_t stack_size; + } monitor; +#endif + +} Process; + + +/** + * \name Flags for Process.flags. + * \{ + */ +#define PF_FREESTACK BV(0) /**< Free the stack when process dies */ +/*\}*/ + + +/** Track running processes. */ +extern REGISTER Process *CurrentProcess; + +/** Track ready processes. */ +extern REGISTER List ProcReadyList; + + +/** Enqueue a task in the ready list. */ +#define SCHED_ENQUEUE(proc) ADDTAIL(&ProcReadyList, &(proc)->link) + +/** Schedule to another process *without* adding the current to the ready list. */ +void proc_schedule(void); + +#if CONFIG_KERN_MONITOR + /** Initialize the monitor */ + void monitor_init(void); + + /** Register a process into the monitor */ + void monitor_add(Process *proc, const char *name, cpustack_t *stack, size_t stacksize); + + /** Unregister a process from the monitor */ + void monitor_remove(Process *proc); + + /** Rename a process */ + void monitor_rename(Process *proc, const char* name); +#endif /* CONFIG_KERN_MONITOR */ + +#endif /* KERN_PROC_P_H */ + diff --git a/bertos/kern/proc_test.c b/bertos/kern/proc_test.c new file mode 100644 index 00000000..4c2f3126 --- /dev/null +++ b/bertos/kern/proc_test.c @@ -0,0 +1,58 @@ + +#include +#include + +/** + * Proc scheduling test subthread 1 + */ +static void NORETURN proc_test_thread1(void) +{ + for (;;) + { + kputs(">task 1\n"); + timer_delay(50); + proc_switch(); + } +} + +/** + * Proc scheduling test subthread 2 + */ +static void NORETURN proc_test_thread2(void) +{ + for (;;) + { + kputs(">task 2\n"); + timer_delay(75); + proc_switch(); + } +} + +static cpustack_t proc_test_stack1[CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)]; +static cpustack_t proc_test_stack2[CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)]; + +/** + * Proc scheduling test + */ +void NORETURN proc_test(void) +{ + proc_new(proc_test_thread1, NULL, sizeof(proc_test_stack1), proc_test_stack1); + proc_new(proc_test_thread2, NULL, sizeof(proc_test_stack2), proc_test_stack2); + kputs("Created tasks\n"); + + kputs("stack1:\n"); +// #warning FIXME + kdump(proc_test_stack1+sizeof(proc_test_stack1)-64, 64); + kputs("stack2:\n"); +// #warning FIXME + kdump(proc_test_stack2+sizeof(proc_test_stack1)-64, 64); + + for (;;) + { + kputs(">main task\n"); + timer_delay(93); + proc_switch(); + } + + ASSERT(false); +} diff --git a/bertos/kern/sem.c b/bertos/kern/sem.c new file mode 100644 index 00000000..0f31fa06 --- /dev/null +++ b/bertos/kern/sem.c @@ -0,0 +1,186 @@ +/** + * \file + * + * + * \brief Semaphore based synchronization services. + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#include "sem.h" +#include +#include +#include +#include + +INLINE void sem_verify(struct Semaphore *s) +{ + (void)s; + ASSERT(s); + LIST_ASSERT_VALID(&s->wait_queue); + ASSERT(s->nest_count >= 0); + ASSERT(s->nest_count < 128); // heuristic max +} + + +/** + * \brief Initialize a Semaphore structure. + */ +void sem_init(struct Semaphore *s) +{ + LIST_INIT(&s->wait_queue); + s->owner = NULL; + s->nest_count = 0; +} + + +/** + * \brief Attempt to lock a semaphore without waiting. + * + * \return true in case of success, false if the semaphore + * was already locked by someone else. + * + * \note each call to sem_attempt() must be matched by a + * call to sem_release(). + * + * \see sem_obtain() sem_release() + */ +bool sem_attempt(struct Semaphore *s) +{ + bool result = false; + + proc_forbid(); + sem_verify(s); + if ((!s->owner) || (s->owner == CurrentProcess)) + { + s->owner = CurrentProcess; + s->nest_count++; + result = true; + } + proc_permit(); + + return result; +} + + +/** + * \brief Lock a semaphore. + * + * If the semaphore is already owned by another process, the caller + * process will be enqueued into the waiting list and sleep until + * the semaphore is available. + * + * \note Each call to sem_obtain() must be matched by a + * call to sem_release(). + * + * \note This routine is optimized for highest speed in + * the most common case: the semaphore is free or locked + * by the calling process itself. Rearranging this code + * is probably a bad idea. + * + * \sa sem_release() sem_attempt() + */ +void sem_obtain(struct Semaphore *s) +{ + proc_forbid(); + sem_verify(s); + + /* Is the semaphore already locked by another process? */ + if (UNLIKELY(s->owner && (s->owner != CurrentProcess))) + { + /* Append calling process to the wait queue */ + ADDTAIL(&s->wait_queue, (Node *)CurrentProcess); + + /* + * We will wake up only when the current owner calls + * sem_release(). Then, the semaphore will already + * be locked for us. + */ + proc_permit(); + proc_schedule(); + } + else + { + ASSERT(LIST_EMPTY(&s->wait_queue)); + + /* The semaphore was free: lock it */ + s->owner = CurrentProcess; + s->nest_count++; + proc_permit(); + } +} + + +/** + * \brief Release a lock on a previously locked semaphore. + * + * If the nesting count of the semaphore reaches zero, + * the next process waiting for it will be awaken. + * + * \note This routine is optimized for highest speed in + * the most common case: the semaphore has been locked just + * once and nobody else was waiting for it. Rearranging + * this code is probably a bad idea. + * + * \sa sem_obtain() sem_attempt() + */ +void sem_release(struct Semaphore *s) +{ + proc_forbid(); + sem_verify(s); + + ASSERT(s->owner == CurrentProcess); + + /* + * Decrement nesting count and check if the semaphore + * has been fully unlocked. + */ + if (--s->nest_count == 0) + { + Process *proc; + + /* Disown semaphore */ + s->owner = NULL; + + /* Give semaphore to the first applicant, if any */ + if (UNLIKELY((proc = (Process *)list_remHead(&s->wait_queue)))) + { + s->nest_count = 1; + s->owner = proc; + SCHED_ENQUEUE(proc); + } + } + + proc_permit(); +} diff --git a/bertos/kern/sem.h b/bertos/kern/sem.h new file mode 100644 index 00000000..a80c914f --- /dev/null +++ b/bertos/kern/sem.h @@ -0,0 +1,70 @@ +/** + * \file + * + * + * \brief Mutually exclusive semaphores. + * Shared locking not supported in this implementation. + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + + +#ifndef KERN_SEM_H +#define KERN_SEM_H + +#include +#include + +/* Fwd decl */ +struct Process; + + +typedef struct Semaphore +{ + struct Process *owner; + List wait_queue; + int nest_count; +} Semaphore; + +/** + * \name Process synchronization services + * \{ + */ +void sem_init(struct Semaphore *s); +bool sem_attempt(struct Semaphore *s); +void sem_obtain(struct Semaphore *s); +void sem_release(struct Semaphore *s); +/* \} */ + +#endif /* KERN_SEM_H */ diff --git a/bertos/kern/signal.c b/bertos/kern/signal.c new file mode 100644 index 00000000..5abd7062 --- /dev/null +++ b/bertos/kern/signal.c @@ -0,0 +1,218 @@ +/** + * \file + * + * + * \brief IPC signals implementation. + * + * Signals are a low-level IPC primitive. A process receives a signal + * when some external event has happened. Like interrupt requests, + * signals do not carry any additional information. If processing a + * specific event requires additional data, the process must obtain it + * through some other mechanism. + * + * Despite the name, one shouldn't confuse these signals with POSIX + * signals. POSIX signals are usually executed synchronously, like + * software interrupts. + * + * Signals are very low overhead. Using them exclusively to wait + * for multiple asynchronous events results in very simple dispatch + * logic with low processor and resource usage. + * + * The "event" module is a higher-level interface that can optionally + * deliver signals to processes. Messages provide even higher-level + * IPC services built on signals. Semaphore arbitration is also + * implemented using signals. + * + * In this implementation, each process has a limited set of signal + * bits (usually 32) and can wait for multiple signals at the same + * time using sig_wait(). Signals can also be polled using sig_check(), + * but a process spinning on its signals usually defeats their purpose + * of providing a multitasking-friendly infrastructure for event-driven + * applications. + * + * Signals are like flags: they are either active or inactive. After an + * external event has delivered a particular signal, it remains raised until + * the process acknowledges it using either sig_wait() or sig_check(). + * Counting signals is not a reliable way to count how many times a + * particular event has occurred, because the same signal may be + * delivered twice before the process can notice. + * + * Any execution context, including an interrupt handler, can deliver + * a signal to a process using sig_signal(). Multiple independent signals + * may be delivered at once with a single invocation of sig_signal(), + * although this is rarely useful. + * + * \section signal_allocation Signal Allocation + * + * There's no hardcoded mapping of specific events to signal bits. + * The meaning of a particular signal bit is defined by an agreement + * between the delivering entity and the receiving process. + * For instance, a terminal driver may be designed to deliver + * a signal bit called SIG_INT when it reads the CTRL-C sequence + * from the keyboard, and a process may react to it by quitting. + * + * \section sig_single SIG_SINGLE + * + * The SIG_SINGLE bit is reserved as a convenient shortcut in those + * simple scenarios where a process needs to wait on just one event + * synchronously. By using SIG_SINGLE, there's no need to allocate + * a specific signal from the free pool. The constraints for safely + * accessing SIG_SINGLE are: + * - The process MUST sig_wait() exclusively on SIG_SINGLE + * - SIG_SIGNAL MUST NOT be left pending after use (sig_wait() will reset + * it automatically) + * - Do not sleep between starting the asynchronous task that will fire + * SIG_SINGLE, and the call to sig_wait(). + * - Do not call system functions that may implicitly sleep, such as + * timer_delayTickes(). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#include "signal.h" + +#include +#include +#include +#include + + +#if CONFIG_KERN_SIGNALS + +/** + * Check if any of the signals in \a sigs has occurred and clear them. + * \return the signals that have occurred. + */ +sigmask_t sig_check(sigmask_t sigs) +{ + sigmask_t result; + cpuflags_t flags; + + IRQ_SAVE_DISABLE(flags); + result = CurrentProcess->sig_recv & sigs; + CurrentProcess->sig_recv &= ~sigs; + IRQ_RESTORE(flags); + + return result; +} + + +/** + * Sleep until any of the signals in \a sigs occurs. + * \return the signal(s) that have awoken the process. + */ +sigmask_t sig_wait(sigmask_t sigs) +{ + sigmask_t result; + cpuflags_t flags; + + IRQ_SAVE_DISABLE(flags); + + /* Loop until we get at least one of the signals */ + while (!(result = CurrentProcess->sig_recv & sigs)) + { + /* go to sleep and proc_schedule() another process */ + CurrentProcess->sig_wait = sigs; + proc_schedule(); + + /* When we come back here, a signal must be arrived */ + ASSERT(!CurrentProcess->sig_wait); + ASSERT(CurrentProcess->sig_recv); + } + + /* Signals found: clear them and return */ + CurrentProcess->sig_recv &= ~sigs; + + IRQ_RESTORE(flags); + return result; +} + +/** + * Sleep until any of the signals in \a sigs or \a timeout ticks elapse. + * If the timeout elapse a SIG_TIMEOUT is added to the received signal(s). + * \return the signal(s) that have awoken the process. + * \note Caller must check return value to check which signal awoke the process. + */ +sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout) +{ + Timer t; + sigmask_t res; + cpuflags_t flags; + + ASSERT(!sig_check(SIG_TIMEOUT)); + ASSERT(!(sigs & SIG_TIMEOUT)); + /* IRQ are needed to run timer */ + ASSERT(IRQ_ENABLED()); + + timer_set_event_signal(&t, proc_current(), SIG_TIMEOUT); + timer_setDelay(&t, timeout); + timer_add(&t); + res = sig_wait(SIG_TIMEOUT | sigs); + + IRQ_SAVE_DISABLE(flags); + /* Remove timer if sigs occur before timer signal */ + if (!(res & SIG_TIMEOUT) && !sig_check(SIG_TIMEOUT)) + timer_abort(&t); + IRQ_RESTORE(flags); + return res; +} + + +/** + * Send the signals \a sigs to the process \a proc. + * The process will be awoken if it was waiting for any of them. + * + * \note This call is interrupt safe. + */ +void sig_signal(Process *proc, sigmask_t sigs) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + /* Set the signals */ + proc->sig_recv |= sigs; + + /* Check if process needs to be awoken */ + if (proc->sig_recv & proc->sig_wait) + { + /* Wake up process and enqueue in ready list */ + proc->sig_wait = 0; + SCHED_ENQUEUE(proc); + } + + IRQ_RESTORE(flags); +} + +#endif /* CONFIG_KERN_SIGNALS */ + diff --git a/bertos/kern/signal.h b/bertos/kern/signal.h new file mode 100644 index 00000000..af3aed6b --- /dev/null +++ b/bertos/kern/signal.h @@ -0,0 +1,72 @@ +/** + * \file + * + * + * \brief Signal module (public interface). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + + +#ifndef KERN_SIGNAL_H +#define KERN_SIGNAL_H + +#include + + +/* Fwd decl */ +struct Process; + +/* Inter-process Communication services */ +sigmask_t sig_check(sigmask_t sigs); +void sig_signal(struct Process *proc, sigmask_t sig); +sigmask_t sig_wait(sigmask_t sigs); +sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout); + + +/** + * \name Signal definitions + * \{ + */ +#define SIG_USER0 BV(0) /**< Free for user usage */ +#define SIG_USER1 BV(1) /**< Free for user usage */ +#define SIG_USER2 BV(2) /**< Free for user usage */ +#define SIG_USER3 BV(3) /**< Free for user usage */ +#define SIG_TIMEOUT BV(4) /**< Reserved for timeout use */ +#define SIG_SYSTEM5 BV(5) /**< Reserved for system use */ +#define SIG_SYSTEM6 BV(6) /**< Reserved for system use */ +#define SIG_SINGLE BV(7) /**< Used to wait for a single event */ +/*\}*/ + +#endif /* KERN_SIGNAL_H */ diff --git a/bertos/kern/switch.S b/bertos/kern/switch.S new file mode 100644 index 00000000..93d9b7c7 --- /dev/null +++ b/bertos/kern/switch.S @@ -0,0 +1,8 @@ +#if defined(__i386__) + #include "switch_i386.s" +#elif defined(__x86_64__) + #include "switch_x86_64.s" +#else + #error Unknown CPU +#endif + diff --git a/bertos/kern/switch_arm.S b/bertos/kern/switch_arm.S new file mode 100644 index 00000000..531b18a5 --- /dev/null +++ b/bertos/kern/switch_arm.S @@ -0,0 +1,67 @@ +/** + * \file + * + * + * \brief ARM context switch + * + * \version $Id: proc.c 18271 2007-10-11 14:51:31Z batt $ + * + * \author Stefano Fedrigo + * \author Francesco Sacchi + */ + + +/* + * NOTE: At each change of this function affecting proc.c + * (i.e. arguments, data stored in the stack) bump up version + * number in asm_switch_version(). + */ + +/* void asm_switch_context(void **new_sp, void **save_sp) */ +.globl asm_switch_context +asm_switch_context: + mrs r2, cpsr /* Save status. */ + stmfd sp!, {r2, r4-r11, lr} /* Save registers. */ + + str sp, [r1] /* Save old stack pointer. */ + ldr sp, [r0] /* Load new stack pointer */ + + ldmfd sp!, {r2, r4-r11, lr} /* Load new registers. */ + msr cpsr, r2 /* restore flags reg. */ + + mov pc, lr + + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + mov r0, #1 + mov pc, lr diff --git a/bertos/kern/switch_avr.S b/bertos/kern/switch_avr.S new file mode 100644 index 00000000..93892919 --- /dev/null +++ b/bertos/kern/switch_avr.S @@ -0,0 +1,135 @@ +/*! + * \file + * + * + * \brief AVR context switch + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#include + +/* + * NOTE: At each change of this function affecting proc.c + * (i.e. arguments, data stored in the stack) bump up version + * number in asm_switch_version(). + */ + +/* void asm_switch_context(void **new_sp, void **save_sp) */ +.globl asm_switch_context +asm_switch_context: + +; r0 is the TEMP REG and can be used freely. +; r1 is the ZERO REG and must always contain 0. +; +; Stack frame is 19 byte, remember to update +; CPU_SAVED_REGS_CNT if you change pushed regs. + + in r0,SREG-__SFR_OFFSET + push r0 +; push r1 ;zero-reg + push r2 + push r3 + push r4 + push r5 + push r6 + push r7 + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + push r16 + push r17 +; push r18 ;caller-save +; push r19 ;caller-save +; push r20 ;caller-save +; push r21 ;caller-save +; push r22 ;caller-save +; push r23 ;caller-save +; push r24 ;caller-save +; push r25 ;caller-save +; push r26 ;caller-save +; push r27 ;caller-save + push r28 + push r29 +; push r30 ;caller-save +; push r31 ;caller-save + +; First parameter (new_sp) is in r24:r25, second (save_sp) in r22:r23 + + in r18,SPL-__SFR_OFFSET ; r18:r19 = SP + in r19,SPH-__SFR_OFFSET + movw r26,r22 ; X = save_sp + st X+,r18 ; *save_sp = SP + st X,r19 + movw r26,r24 ; X = new_sp + ld r18,X+ + ld r19,X + +; Set new stack pointer. +; AVR is an 8 bit processor so +; care must be taken when updating +; SP that is a 16 bit reg. +; Two instructions are required to update SP +; so an IRQ can sneak in between them. +; So IRQ *MUST* be disabled and then restored. + cli ; Disable interrupt + out SPL-__SFR_OFFSET,r18 ; SP = *new_sp + out SPH-__SFR_OFFSET,r19 + out SREG-__SFR_OFFSET,r0 ; Restore previous IRQ state + +; pop r31 ;caller-save +; pop r30 ;caller-save + pop r29 + pop r28 +; pop r27 ;caller-save +; pop r26 ;caller-save +; pop r25 ;caller-save +; pop r24 ;caller-save +; pop r23 ;caller-save +; pop r22 ;caller-save +; pop r21 ;caller-save +; pop r20 ;caller-save +; pop r19 ;caller-save +; pop r18 ;caller-save + pop r17 + pop r16 + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop r7 + pop r6 + pop r5 + pop r4 + pop r3 + pop r2 +; pop r1 ;zero-reg + pop r0 + out SREG-__SFR_OFFSET,r0 + + ret + + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + ldi r24,lo8(1) + ldi r25,hi8(1) + ret + diff --git a/bertos/kern/switch_dsp56k.c b/bertos/kern/switch_dsp56k.c new file mode 100644 index 00000000..41a12056 --- /dev/null +++ b/bertos/kern/switch_dsp56k.c @@ -0,0 +1,135 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Giovanni Bajo + * + * \brief DSP5680x task switching support + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2006/02/24 01:17:05 bernie + *#* Update for new emulator. + *#* + *#* Revision 1.5 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.4 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.3 2004/07/30 14:24:16 rasky + *#* Task switching con salvataggio perfetto stato di interrupt (SR) + *#* Kernel monitor per dump informazioni su stack dei processi + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 17:27:00 bernie + *#* Import kern/ subdirectory. + *#* + *#*/ + +void asm_switch_context(void ** new_sp/*R2*/, void ** save_sp/*R3*/); +asm void asm_switch_context(void ** new_sp, void ** save_sp) +{ + lea (SP)+ + + ; From the manual: + ; The compiler uses page 0 address locations X: 0x0030 - 0x003F as register + ; variables. Frequently accessed local variables are assigned to the page 0 + ; registers instead of to stack locations so that load and store instructions + ; are shortened. Addresses X: 0x0030 - 0x0037 (page 0 registers MR0-MR7) are + ; volatile registers and can be overwritten. The remaining registers (page 0 + ; registers MR8-MR15) are treated as non-volatile and, if used by a routine, + ; must be saved on entry and restored on exit. + ; + ; So, register 0x30-0x37 are caller-save, while 0x38-0x3F are callee-save. + move x:<$38,y1 + move y1,x:(SP)+ + move x:<$39,y1 + move y1,x:(SP)+ + move x:<$3A,y1 + move y1,x:(SP)+ + move x:<$3B,y1 + move y1,x:(SP)+ + move x:<$3C,y1 + move y1,x:(SP)+ + move x:<$3D,y1 + move y1,x:(SP)+ + move x:<$3E,y1 + move y1,x:(SP)+ + move x:<$3F,y1 + move y1,x:(SP) + + ; + ; Switch stacks + nop + move SP, x:(R3) + nop + move x:(R2), SP + nop + + ; + ; restore all saved registers + ; + pop y1 + move y1,x:<$3F + pop y1 + move y1,x:<$3E + pop y1 + move y1,x:<$3D + pop y1 + move y1,x:<$3C + pop y1 + move y1,x:<$3B + pop y1 + move y1,x:<$3A + pop y1 + move y1,x:<$39 + pop y1 + move y1,x:<$38 + + ; SR is already pushed on the stack (normal call context). Use RTI to restore + ; it, so that interrupt status is preserved across the tasks. + rti +} + +int asm_switch_version(void); +int asm_switch_version(void) +{ + return 1; +} diff --git a/bertos/kern/switch_i196.s32 b/bertos/kern/switch_i196.s32 new file mode 100644 index 00000000..a2f3c70d --- /dev/null +++ b/bertos/kern/switch_i196.s32 @@ -0,0 +1,92 @@ +;* Copyright 2004 Develer S.r.l. (http://www.develer.com/) +;* Copyright 1999,2000,2001 Bernardo Innocenti +;* This file is part of DevLib - See devlib/README for information. +;* +;* \version $Id$ +;* +;* \author Bernardo Innocenti +;* + +;* $Log$ +;* Revision 1.2 2004/06/06 16:14:12 bernie +;* Add DevLib license information. +;* +;* Revision 1.1 2004/05/23 17:27:00 bernie +;* Import kern/ subdirectory. +;* +;* + +!!!!!! THIS FILE HAS NOT BEEN REVISED FOR THE NEW SCHEDULER API !!!!!! + + + + NAME AsmSwitch + RSEG CODE + + EXTERN ?LR + EXTERN ?GR + PUBLIC AsmSwitchContext + PUBLIC AsmReplaceContext + + +;* Perform low-level process context switching +;* +;* void AsmSwitchContext(cpustack_t *new_sp, cpustack_t **save_sp) +;* GR+0 SP+2 +;* +;* Replace current context with new process +;* +;* void AsmReplaceContext(cpustack_t *new_sp, cpustack_t **dummy) +;* GR+0 SP+2 +;* + +AsmSwitchContext: + +; pop 2nd parameter from the stack + ld ?GR+2,2[SP] + +; save all registers + push ?LR+0 + push ?LR+2 + push ?LR+4 + push ?LR+6 + push ?LR+8 + push ?LR+10 + push ?LR+12 + push ?LR+14 + push ?LR+16 + push ?LR+18 + push ?LR+20 + push ?LR+22 + push ?LR+24 + push ?LR+26 + push ?LR+28 + push ?LR+30 + st SP,[?GR+2] ; save old stack pointer + ; fall-thru + +AsmReplaceContext: + ld SP,?GR+0 ; load new stack pointer + +; restore all registers + pop ?LR+30 + pop ?LR+28 + pop ?LR+26 + pop ?LR+24 + pop ?LR+22 + pop ?LR+20 + pop ?LR+18 + pop ?LR+16 + pop ?LR+14 + pop ?LR+12 + pop ?LR+10 + pop ?LR+8 + pop ?LR+6 + pop ?LR+4 + pop ?LR+2 + pop ?LR+0 + +; restore execution in new context + ret + + END diff --git a/bertos/kern/switch_i386.s b/bertos/kern/switch_i386.s new file mode 100644 index 00000000..6931d45c --- /dev/null +++ b/bertos/kern/switch_i386.s @@ -0,0 +1,44 @@ +/*! + * \file + * + * + * \brief i386 context switch + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +/* void asm_switch_context(void ** new_sp, void ** save_sp) */ +.globl asm_switch_context +asm_switch_context: + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + pushl %ebp + movl 0x24(%esp),%ebp /* ebp = save_sp */ + movl %esp,(%ebp) /* *save_sp = esp */ + movl 0x20(%esp),%ebp /* ebp = new_sp */ + movl (%ebp),%esp /* esp = *new_sp */ + popl %ebp + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %eax + ret + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + mov $1,%eax + ret + diff --git a/bertos/kern/switch_win32.s b/bertos/kern/switch_win32.s new file mode 100644 index 00000000..5891ae90 --- /dev/null +++ b/bertos/kern/switch_win32.s @@ -0,0 +1,58 @@ +/*! + * \file + * + * + * \brief i386 context switch for WIN32 + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +!!!!!! THIS FILE HAS NOT BEEN REVISED FOR THE NEW SCHEDULER API !!!!!! + +__declspec(naked) void AsmSwitchContext(void * new_sp, void ** save_sp) +{ + __asm + { + push eax + push ebx + push ecx + push edx + push esi + push edi + push ebp + mov ebp,dword ptr [esp+24h] ; ebp <- save_sp + mov dword ptr [ebp],esp ; *save_sp = esp + mov esp,dword ptr [esp+20h] ; new_sp + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + ret + } +} + +__declspec(naked) void AsmReplaceContext(void * new_sp, void ** dummy) +{ + __asm + { + mov esp,dword ptr [esp + 4] ; new_sp + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + ret + } +} + diff --git a/bertos/kern/switch_x86_64.s b/bertos/kern/switch_x86_64.s new file mode 100644 index 00000000..5fb4da65 --- /dev/null +++ b/bertos/kern/switch_x86_64.s @@ -0,0 +1,71 @@ +/*! + * \file + * + * + * \brief i386 context switch + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +/* + * $Log$ + * Revision 1.4 2006/09/20 14:02:49 marco + * C-style comment. + * + * Revision 1.3 2006/02/24 01:35:40 bernie + * Update for new emulator. + * + * Revision 1.2 2006/02/24 01:17:05 bernie + * Update for new emulator. + * + * Revision 1.1 2005/11/27 03:06:15 bernie + * Add x86_64 task switching (to be updated to new-style scheduler). + * + * Revision 1.1 2005/11/14 21:06:38 bernie + * Add x86_64 support. + * + * Revision 1.2 2004/06/06 16:14:12 bernie + * Add DevLib license information. + * + * Revision 1.1 2004/05/23 17:27:00 bernie + * Import kern/ subdirectory. + * + */ + +/* I know it's ugly... */ +/* .intel_syntax */ + +/* void AsmSwitchContext(void **new_sp, void **save_sp) */ +/* %rdi %rsi */ +.globl asm_switch_context +asm_switch_context: + pushq %rax + pushq %rbx + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rdi + pushq %rbp + movq %rsp,(%rsi) /* *save_sp = rsp */ + movq (%rdi),%rsp /* rsp = *new_sp */ + popq %rbp + popq %rdi + popq %rsi + popq %rdx + popq %rcx + popq %rbx + popq %rax + ret + +/* int asm_switch_version(void) */ +.globl asm_switch_version +asm_switch_version: + mov $1,%rax + ret + diff --git a/bertos/mware/blanker.c b/bertos/mware/blanker.c new file mode 100644 index 00000000..5cf5247e --- /dev/null +++ b/bertos/mware/blanker.c @@ -0,0 +1,222 @@ +/** + * \file + * + * + * \brief Display Blanker (implementation). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#include "blanker.h" +#include +#include + +/* Time without input events before starting blanker */ +#define BLK_BLANKTIMEOUT (15 * 1000) /* ms */ + +// TODO: move to blanker_hw.h +#include +#define BLK_LCDON power_LcdOn() +#define BLK_LCDOFF power_LcdOff() + + +/** Keyboard event handler to listen for key presses in blanker. */ +static KbdHandler blk_KbdHandler; + +/** Time since last key event. */ +static ticks_t blk_lastevent; + +/** Display blanking function is enabled. */ +static bool blk_enabled; + +/** Display blanker is engaged right now. */ +static bool blk_active; + + +static bool blk_on(void) +{ + if (!blk_active) + { + blk_active = true; + BLK_LCDOFF; + } + return true; +} + + +static void blk_off(void) +{ + if (blk_active) + { + blk_active = false; + BLK_LCDON; + } +} + + +void blk_retrigger(void) +{ + blk_lastevent = timer_clock(); + blk_off(); +} + +#if 0 +/** + * Matrix-like screen saver effect + */ +static void blk_hack(void) +{ + static signed char blk_colstart[LCD_COLS]; + UBYTE row, col; + + + if (rand()%3 == 0) + { + /* Modify one column */ + col = rand() % LCD_COLS; + blk_colstart[col] += rand() % 12 - 5; + } + + for (col = 0; col < LCD_COLS; ++col) + { + if (blk_colstart[col] > 0) + { + --blk_colstart[col]; + + /* Scroll down */ + for(row = LCD_ROWS-1; row; --row) + { + lcd_SetAddr(blk_layer, LCD_POS(col,row)); + lcd_PutChar(blk_layer->Buf[LCD_POS(col,row-1)], blk_layer); + } + + /* Add new kanji */ + lcd_SetAddr(blk_layer, LCD_POS(col,0)); + lcd_PutChar((char)(rand() % 127 + 128), blk_layer); + } + else if (blk_colstart[col] < 0) + { + ++blk_colstart[col]; + + /* Clear tail */ + for(row = 0; row < LCD_ROWS; ++row) + { + if (blk_layer->Buf[LCD_POS(col,row)] != ' ') + { + lcd_SetAddr(blk_layer, LCD_POS(col,row)); + lcd_PutChar(' ', blk_layer); + break; + } + } + } + } +} +#endif + + +static keymask_t blk_handlerFunc(keymask_t key) +{ + /* key used to turn off blanker */ + static keymask_t offkey; + + ticks_t now = timer_clock(); + + /* If key pressed */ + if (key != 0) + { + blk_lastevent = now; + if (blk_active) + { + blk_off(); + + /* remember and eat key event */ + offkey = key; + key = 0; + } + else if (key == offkey) + { + /* keep eating the key until released */ + key = 0; + } + + /* pass key through */ + return key; + } + + /* reset off key */ + offkey = 0; + + /* Blank timeout reached? */ + if (now - blk_lastevent > ms_to_ticks(BLK_BLANKTIMEOUT)) + { + /* Enable blanker unless already done */ + if (!blk_active && !blk_on()) + return 0; + +#if 0 + /* Do some nice visual effect */ + blk_hack(); +#endif /* _DEBUG */ + } + + return 0; +} + + +void blk_enable(void) +{ + if (!blk_enabled) + { + blk_active = false; + blk_lastevent = timer_clock(); + + /* Add display blanker handler */ + blk_KbdHandler.hook = blk_handlerFunc; + blk_KbdHandler.pri = 100; /* high priority */ + blk_KbdHandler.flags = KHF_RAWKEYS; + kbd_addHandler(&blk_KbdHandler); + + blk_enabled = true; + } +} + + +void blk_disable(void) +{ + if (blk_enabled) + { + kbd_remHandler(&blk_KbdHandler); + blk_off(); + blk_enabled = false; + } +} diff --git a/bertos/mware/blanker.h b/bertos/mware/blanker.h new file mode 100644 index 00000000..bdcdc679 --- /dev/null +++ b/bertos/mware/blanker.h @@ -0,0 +1,46 @@ +/** + * \file + * + * + * \brief Display Blanker (implementation). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ +#ifndef MWARE_BLANKER_H +#define MWARE_BLANKER_H + +extern void blk_enable(void); +extern void blk_disable(void); +extern void blk_retrigger(void); + +#endif /* MWARE_BLANKER_H */ diff --git a/bertos/mware/byteorder.h b/bertos/mware/byteorder.h new file mode 100644 index 00000000..0ed874bb --- /dev/null +++ b/bertos/mware/byteorder.h @@ -0,0 +1,269 @@ +/** + * \file + * + * + * \brief Functions to convert integers to/from host byte-order. + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +#ifndef MWARE_BYTEORDER_H +#define MWARE_BYTEORDER_H + +#include +#include + +/** + * Swap upper and lower bytes in a 16-bit value. + */ +INLINE uint16_t swab16(uint16_t x) +{ + return ((x & (uint16_t)0x00FFU) << 8) + | ((x & (uint16_t)0xFF00U) >> 8); +} + +/** + * Reverse bytes in a 32-bit value (e.g.: 0x12345678 -> 0x78563412). + */ +INLINE uint32_t swab32(uint32_t x) +{ + return ((x & (uint32_t)0x000000FFUL) << 24) + | ((x & (uint32_t)0x0000FF00UL) << 8) + | ((x & (uint32_t)0x00FF0000UL) >> 8) + | ((x & (uint32_t)0xFF000000UL) >> 24); +} + +/** + * Reverse bytes in a 64-bit value. + */ +INLINE uint64_t swab64(uint64_t x) +{ + return (uint64_t)swab32(x >> 32) + | ((uint64_t)swab32(x & 0xFFFFFFFFUL) << 32); +} + +/** + * Reverse bytes in a float value. + */ +INLINE float swab_float(float x) +{ + /* Avoid breaking strict aliasing rules. */ + char *cx = (char *)(&x); + STATIC_ASSERT(sizeof(float) == 4); + #define BYTEORDER_SWAP(a, b) ((a) ^= (b) ^= (a) ^= (b)) + BYTEORDER_SWAP(cx[0], cx[3]); + BYTEORDER_SWAP(cx[1], cx[2]); + #undef BYTEORDER_SWAP + return x; +} + +INLINE uint16_t cpu_to_be16(uint16_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab16(x) : x; +} + +INLINE uint16_t cpu_to_le16(uint16_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab16(x) : x; +} + +INLINE uint32_t cpu_to_be32(uint32_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab32(x) : x; +} + +INLINE uint32_t cpu_to_le32(uint32_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab32(x) : x; +} + +INLINE uint64_t cpu_to_be64(uint64_t x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab64(x) : x; +} + +INLINE uint64_t cpu_to_le64(uint64_t x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab64(x) : x; +} + +INLINE float cpu_to_be_float(float x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab_float(x) : x; +} + +INLINE float cpu_to_le_float(float x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab_float(x) : x; +} + +INLINE uint16_t be16_to_cpu(uint16_t x) +{ + return cpu_to_be16(x); +} + +INLINE uint16_t le16_to_cpu(uint16_t x) +{ + return cpu_to_le16(x); +} + +INLINE uint32_t be32_to_cpu(uint32_t x) +{ + return cpu_to_be32(x); +} + +INLINE uint32_t le32_to_cpu(uint32_t x) +{ + return cpu_to_le32(x); +} + +INLINE uint64_t be64_to_cpu(uint64_t x) +{ + return cpu_to_be64(x); +} + +INLINE uint64_t le64_to_cpu(uint64_t x) +{ + return cpu_to_le64(x); +} + +INLINE float be_float_to_cpu(float x) +{ + return cpu_to_be_float(x); +} + +INLINE float le_float_to_cpu(float x) +{ + return cpu_to_le_float(x); +} + +INLINE uint16_t host_to_net16(uint16_t x) +{ + return cpu_to_be16(x); +} + +INLINE uint16_t net_to_host16(uint16_t x) +{ + return be16_to_cpu(x); +} + +INLINE uint32_t host_to_net32(uint32_t x) +{ + return cpu_to_be32(x); +} + +INLINE uint32_t net_to_host32(uint32_t x) +{ + return be32_to_cpu(x); +} + +INLINE uint64_t host_to_net64(uint64_t x) +{ + return cpu_to_be64(x); +} + +INLINE uint64_t net_to_host64(uint64_t x) +{ + return be64_to_cpu(x); +} + +INLINE float host_to_net_float(float x) +{ + return cpu_to_be_float(x); +} + +INLINE float net_to_host_float(float x) +{ + return be_float_to_cpu(x); +} + +#ifdef __cplusplus + +/// Type generic byte swapping. +template +INLINE T swab(T x); + +template<> INLINE uint16_t swab(uint16_t x) { return swab16(x); } +template<> INLINE uint32_t swab(uint32_t x) { return swab32(x); } +template<> INLINE uint64_t swab(uint64_t x) { return swab64(x); } +template<> INLINE int16_t swab(int16_t x) { return static_cast(swab16(static_cast(x))); } +template<> INLINE int32_t swab(int32_t x) { return static_cast(swab32(static_cast(x))); } +template<> INLINE int64_t swab(int64_t x) { return static_cast(swab64(static_cast(x))); } +template<> INLINE float swab(float x) { return swab_float(x); } + +/// Type generic conversion from CPU byte order to big-endian byte order. +template +INLINE T cpu_to_be(T x) +{ + return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab(x) : x; +} + +/// Type generic conversion from CPU byte-order to little-endian. +template +INLINE T cpu_to_le(T x) +{ + return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab(x) : x; +} + +/// Type generic conversion from big endian byte-order to CPU byte order. +template +INLINE T be_to_cpu(T x) +{ + return cpu_to_be(x); +} + +/// Type generic conversion from little-endian byte order to CPU byte order. +template +INLINE T le_to_cpu(T x) +{ + return cpu_to_le(x); +} + +/// Type generic conversion from network byte order to host byte order. +template +INLINE T net_to_host(T x) +{ + return be_to_cpu(x); +} + +/// Type generic conversion from host byte order to network byte order. +template +INLINE T host_to_net(T x) +{ + return net_to_host(x); +} + +#endif /* __cplusplus */ + +#endif /* MWARE_BYTEORDER_H */ diff --git a/bertos/mware/cmd_hunk.h b/bertos/mware/cmd_hunk.h new file mode 100644 index 00000000..a3dfff79 --- /dev/null +++ b/bertos/mware/cmd_hunk.h @@ -0,0 +1,180 @@ +/** + * \file + * + * This module permits to create hunks for the functions that must be executed through + * RPC commands. For instance, given this code: + * + * \code + * ResultCode cmd_add(long a, long b, long* result); + * DECLARE_COMMAND_HUNK(add, (long)(long)(NIL), (long)(NIL)); + * // ^ parameters ^ return values + * \endcode + * + * The macro is expanded to: + * + * \code + * ResultCode cmd_add_hunk(params argv[], params results[]) + * { + * return cmd_add(argv[0].l, argv[1].l, &results[0].l); + * } + * + * const struct CmdTemplate cmd_add_template = + * { + * "add", "dd", "d", cmd_add_hunk + * }; + * \endcode + * + * which is all the boilerplate needed to make the function ready for the RPC. + * The implementation uses the Boost Preprocessor Library (part of the Boost + * library, available at http://www.boost.org). The version we developed the + * code with is 1.31. + * + * \version $Id$ + * + * \author Giovanni Bajo + * + * \brief Preprocessor magic to create hunks for the commands executed from the parser + * + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2006/06/01 12:27:39 marco + *#* Added utilities for protocols + *#* + *#* Revision 1.8 2005/01/12 20:06:31 rasky + *#* enum ResultCode è ora un typedef + *#* + *#* Revision 1.7 2004/12/14 15:10:53 user1 + *#* Bernardo e Francesco: Assegnazione di un codice di ritorno ai processi + *#* + *#* Revision 1.6 2004/12/02 17:43:15 rasky + *#* Aggiunta la possibilità di settare le flag dei comandi con la nuova macro DECLARE_CMD_HUNK_FLAGS (altrimenti, il default è zero) + *#* + *#* Revision 1.5 2004/10/16 13:20:15 rasky + *#* Aggiunto supporto per alias di uno stesso comando + *#* + *#* Revision 1.4 2004/08/25 14:17:10 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.3 2004/07/31 22:00:07 rasky + *#* Fixata una dipendenza + *#* + *#* Revision 1.2 2004/07/31 14:32:58 rasky + *#* args e results possono overlapparsi sempre grazie ai thunk generati: eliminati i due array separati per risparmiare memoria + *#* + *#* Revision 1.1 2004/05/22 16:29:16 rasky + *#* Generazione degli hunk dei comandi RPC tramite preprocessore + *#* + *#*/ + +#ifndef CMD_HUNK_H +#define CMD_HUNK_H + +#include "parser.h" + +// Bring in the Boost Preprocess Library +#include + +#define HUNK_INDEX_FOR_NIL 0 +#define HUNK_INDEX_FOR_string 1 +#define HUNK_INDEX_FOR_long 2 +#define HUNK_ARRAY_LETTERS (3, (NIL, s, l)) +#define HUNK_ARRAY_STRINGS (3, ("", "s", "d")) + +// Transform int->l, float->f, etc. +#define HUNK_TYPE_LETTER(s, _, type) \ + BOOST_PP_CAT(HUNK_INDEX_FOR_, type) \ + /**/ + +#define HUNK_TRANSFORMER(_, array, elem) \ + BOOST_PP_ARRAY_ELEM(elem, array) \ + /**/ + +#define HUNK_SEQ_TRANS_ARRAY(seq, array) \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TRANSFORMER, array, seq) \ + /**/ + +#define HUNK_PARAM(_, n, seq) \ + args_results[n+1]. BOOST_PP_SEQ_ELEM(n, seq) \ + /**/ + +#define HUNK_RESULT(_, n, seq) \ + &args_results[n]. BOOST_PP_SEQ_ELEM(n, seq) \ + /**/ + +#define HUNK_IDENTITY(_, dummy, x) x +#define CMD_HUNK_TEMPLATE(func) cmd_##func###_template + +#define DECLARE_CMD_HUNK_2(func, name, param_types, result_types, flags) \ + static ResultCode cmd_##name##_hunk(parms args_results[]) \ + { \ + return cmd_##func( \ + BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)), HUNK_PARAM, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_LETTERS)) \ + BOOST_PP_COMMA_IF(BOOST_PP_AND(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)), BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)))) \ + BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)), HUNK_RESULT, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_LETTERS)) \ + ); \ + } \ + const struct CmdTemplate CMD_HUNK_TEMPLATE(name) = { \ + #name, \ + BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_STRINGS)), \ + BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_STRINGS)), \ + cmd_##name##_hunk, \ + flags \ + } \ + /**/ + +#define DECLARE_CMD_HUNK(func, param_types, result_types) \ + DECLARE_CMD_HUNK_2(func, func, \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ + 0) \ + /**/ + +#define DECLARE_CMD_HUNK_NAME(func, name, param_types, result_types) \ + DECLARE_CMD_HUNK_2(func, name, \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ + 0) \ + /**/ + +#define DECLARE_CMD_HUNK_FLAGS(func, param_types, result_types, flags) \ + DECLARE_CMD_HUNK_2(func, func, \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ + BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ + flags) \ + /**/ + +#endif diff --git a/bertos/mware/event.c b/bertos/mware/event.c new file mode 100644 index 00000000..a0419fbf --- /dev/null +++ b/bertos/mware/event.c @@ -0,0 +1,57 @@ +/** + * \file + * + * + * \brief Events handling implementation + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + + +#include "event.h" + +void event_hook_ignore(UNUSED_ARG(Event *, e)) +{ +} + +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS +void event_hook_signal(Event *e) +{ + sig_signal((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit); +} +#endif + +void event_hook_softint(Event *e) +{ + e->Ev.Int.func(e->Ev.Int.user_data); +} diff --git a/bertos/mware/event.h b/bertos/mware/event.h new file mode 100644 index 00000000..4270e946 --- /dev/null +++ b/bertos/mware/event.h @@ -0,0 +1,140 @@ +/** + * \file + * + * + * \brief Events handling + * + * This module implements a common system for executing + * a user defined action calling a hook function. + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#ifndef KERN_EVENT_H +#define KERN_EVENT_H + +#include +#include + +#if CONFIG_KERNEL + #include + #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS + #include + #endif + + /* Forward decl */ + struct Process; +#endif + + +/// User defined callback type +typedef void (*Hook)(void *); + +typedef struct Event +{ + void (*action)(struct Event *); + union + { +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS + struct + { + struct Process *sig_proc; /* Process to be signalled */ + sigbit_t sig_bit; /* Signal to send */ + } Sig; +#endif + struct + { + Hook func; /* Pointer to softint hook */ + void *user_data; /* Data to be passed back to user hook */ + } Int; + } Ev; +} Event; + +void event_hook_ignore(Event *event); +void event_hook_signal(Event *event); +void event_hook_softint(Event *event); + +/** Initialize the event \a e as a no-op */ +#define event_initNone(e) \ + ((e)->action = event_hook_ignore) + +/** Same as event_initNone(), but returns the initialized event */ +INLINE Event event_createNone(void); +INLINE Event event_createNone(void) +{ + Event e; + e.action = event_hook_ignore; + return e; +} + +/** Initialize the event \a e with a software interrupt (call function \a f, with parameter \a u) */ +#define event_initSoftInt(e,f,u) \ + ((e)->action = event_hook_softint,(e)->Ev.Int.func = (f), (e)->Ev.Int.user_data = (u)) + +/** Same as event_initSoftInt(), but returns the initialized event */ +INLINE Event event_createSoftInt(Hook func, void *user_data) +{ + Event e; + e.action = event_hook_softint; + e.Ev.Int.func = func; + e.Ev.Int.user_data = user_data; + return e; +} + + +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS + +/** Initialize the event \a e with a signal (send signal \a s to process \a p) */ +#define event_initSignal(e,p,s) \ + ((e)->action = event_hook_signal,(e)->Ev.Sig.sig_proc = (p), (e)->Ev.Sig.sig_bit = (s)) + +/** Same as event_initSignal(), but returns the initialized event */ +INLINE Event event_createSignal(struct Process *proc, sigbit_t bit) +{ + Event e; + e.action = event_hook_signal; + e.Ev.Sig.sig_proc = proc; + e.Ev.Sig.sig_bit = bit; + return e; +} + +#endif + +/** Trigger an event */ +INLINE void event_do(struct Event *e) +{ + e->action(e); +} + +#endif /* KERN_EVENT_H */ diff --git a/bertos/mware/except.h b/bertos/mware/except.h new file mode 100644 index 00000000..b78435de --- /dev/null +++ b/bertos/mware/except.h @@ -0,0 +1,125 @@ +/** + * \file + * + * + * \brief C++-like structured exception handling for C programs + * + * \version $Id$ + * \author Bernardo Innocenti + */ +#ifndef MWARE_EXCEPT_H +#define MWARE_EXCEPT_H + +#include + +#include + +#define EXCEPT_CONTEXTS 8 + +/** + * A stack of jump buffers used to record try sites + * so they can be reached from throw sites. + * + * The stack contains return points for each nested + * context. jmp_buf's are pushed into the stack at + * try points and popped out when the try block ends + * normally or when an exception is thrown. + */ +extern jmp_buf except_stack[EXCEPT_CONTEXTS]; +extern int except_top; + +#define PUSH_EXCEPT (ASSERT(except_top < EXCEPT_CONTEXTS), setjmp(except_stack[except_top++])) +#define POP_EXCEPT (ASSERT(except_top > 0), --except_top) +#define DO_EXCEPT (ASSERT(except_top > 0), longjmp(except_stack[--except_top], true)) + +/** + * Jump buffer to use when throwing an exception or aborting an operation + * + * User code can throw exceptions like this: + * + * \code + * void a_function_throwing_exceptions(void) + * { + * if (some_error_condition) + * THROW; + * } + * \endcode + * + * Catching exceptions (brackets are optional): + * + * \code + * EXCEPT_DEFINE; + * + * void a_function_catching_an_exception(void) + * { + * TRY + * { + * printf("Entered try block\n"); + * a_function_throwing_exceptions(); + * printf("Survived execution of critical code\n"); + * } + * CATCH + * { + * printf("Exception caught!\n"); + * } + * CATCH_END + * } + * \endcode + * + * Simple syntax when you don't need to do anything when catching an excaption: + * + * \code + * TRY + * printf("Entered try block\n"); + * a_function_throwing_exceptions(); + * printf("Survived execution of critical code\n"); + * TRY_END + * \endcode + * + * You also need to declare the exception stack once in + * your global declarations: + * \code + * EXCEPT_DEFINE; + * \endcode + */ +#define TRY if (PUSH_EXCEPT) { { +#define TRY_END } POP_EXCEPT; } +#define CATCH } POP_EXCEPT; } else { +#define CATCH_END } +#define THROW DO_EXCEPT + + +#define EXCEPT_DEFINE \ + jmp_buf except_stack[EXCEPT_CONTEXTS]; \ + int except_top; + +#endif /* MWARE_EXCEPT_H */ diff --git a/bertos/mware/fifobuf.h b/bertos/mware/fifobuf.h new file mode 100644 index 00000000..cb634ee3 --- /dev/null +++ b/bertos/mware/fifobuf.h @@ -0,0 +1,353 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief General pourpose FIFO buffer implemented with a ring buffer + * + * \li \c begin points to the first buffer element; + * \li \c end points to the last buffer element (unlike the STL convention); + * \li \c head points to the element to be extracted next; + * \li \c tail points to the location following the last insertion; + * \li when any of the pointers advances beyond \c end, it is reset + * back to \c begin. + * + * \code + * + * +-----------------------------------+ + * | empty | valid data | empty | + * +-----------------------------------+ + * ^ ^ ^ ^ + * begin head tail end + * + * \endcode + * + * The buffer is EMPTY when \c head and \c tail point to the same location: + * \code head == tail \endcode + * + * The buffer is FULL when \c tail points to the location immediately + * after \c head: + * \code tail == head - 1 \endcode + * + * The buffer is also FULL when \c tail points to the last buffer + * location and head points to the first one: + * \code head == begin && tail == end \endcode + */ + +#ifndef MWARE_FIFO_H +#define MWARE_FIFO_H + +#include +#include +#include + +typedef struct FIFOBuffer +{ + unsigned char * volatile head; + unsigned char * volatile tail; + unsigned char *begin; + unsigned char *end; +} FIFOBuffer; + + +#define ASSERT_VALID_FIFO(fifo) \ + ATOMIC( \ + ASSERT((fifo)->head >= (fifo)->begin); \ + ASSERT((fifo)->head <= (fifo)->end); \ + ASSERT((fifo)->tail >= (fifo)->begin); \ + ASSERT((fifo)->tail <= (fifo)->end); \ + ) + + +/** + * 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 + * (which the AVR and other 8-bit processors can't do). + * + * \sa fifo_isempty_locked + */ +INLINE bool fifo_isempty(const FIFOBuffer *fb) +{ + //ASSERT_VALID_FIFO(fb); + return 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. + */ +INLINE bool fifo_isfull(const FIFOBuffer *fb) +{ + //ASSERT_VALID_FIFO(fb); + return + ((fb->head == fb->begin) && (fb->tail == fb->end)) + || (fb->tail == fb->head - 1); +} + + +/** + * Push a character on 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, unless the CPU can't update + * a pointer atomically (which the AVR and other 8-bit + * processors can't do). + * + * \sa fifo_push_locked + */ +INLINE void fifo_push(FIFOBuffer *fb, unsigned char c) +{ +#ifdef __MWERKS__ +#pragma interrupt called +#endif + //ASSERT_VALID_FIFO(fb); + + /* Write at tail position */ + *(fb->tail) = c; + + if (UNLIKELY(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. + */ +INLINE unsigned char fifo_pop(FIFOBuffer *fb) +{ +#ifdef __MWERKS__ +#pragma interrupt called +#endif + //ASSERT_VALID_FIFO(fb); + + if (UNLIKELY(fb->head == fb->end)) + { + /* wrap head around */ + fb->head = fb->begin; + return *(fb->end); + } + else + /* move head forward */ + return *(fb->head++); +} + + +/** + * Make the fifo empty, discarding all its current contents. + */ +INLINE void fifo_flush(FIFOBuffer *fb) +{ + //ASSERT_VALID_FIFO(fb); + fb->head = fb->tail; +} + + +#if CPU_REG_BITS >= CPU_BITS_PER_PTR + + /* + * 16/32bit CPUs that can update a pointer with a single write + * operation, no need to disable interrupts. + */ + #define fifo_isempty_locked(fb) fifo_isempty((fb)) + #define fifo_push_locked(fb, c) fifo_push((fb), (c)) + #define fifo_pop_locked(fb) fifo_pop((fb)) + #define fifo_flush_locked(fb) fifo_flush((fb)) + +#else /* CPU_REG_BITS < CPU_BITS_PER_PTR */ + + /** + * Similar to fifo_isempty(), but with stronger guarantees for + * concurrent access between user and interrupt code. + * + * \note This is actually only needed for 8-bit processors. + * + * \sa fifo_isempty() + */ + INLINE bool fifo_isempty_locked(const FIFOBuffer *fb) + { + bool result; + ATOMIC(result = fifo_isempty(fb)); + return result; + } + + + /** + * Similar to fifo_push(), but with stronger guarantees for + * concurrent access between user and interrupt code. + * + * \note This is actually only needed for 8-bit processors. + * + * \sa fifo_push() + */ + INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c) + { + ATOMIC(fifo_push(fb, c)); + } + + /* Probably not really needed, but hard to prove. */ + INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb) + { + unsigned char c; + ATOMIC(c = fifo_pop(fb)); + return c; + } + + /** + * Similar to fifo_flush(), but with stronger guarantees for + * concurrent access between user and interrupt code. + * + * \note This is actually only needed for 8-bit processors. + * + * \sa fifo_flush() + */ + INLINE void fifo_flush_locked(FIFOBuffer *fb) + { + ATOMIC(fifo_flush(fb)); + } + +#endif /* CPU_REG_BITS < BITS_PER_PTR */ + + +/** + * Thread safe version of fifo_isfull() + */ +INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb) +{ + bool result; + ATOMIC(result = fifo_isfull(_fb)); + return result; +} + + +/** + * FIFO Initialization. + */ +INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size) +{ + /* FIFO buffers have a known bug with 1-byte buffers. */ + ASSERT(size > 1); + + fb->head = fb->tail = fb->begin = buf; + fb->end = buf + size - 1; +} + + +#if 0 + +/* + * UNTESTED: if uncommented, to be moved in fifobuf.c + */ +void fifo_pushblock(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 + +#endif /* MWARE_FIFO_H */ + diff --git a/bertos/mware/formatwr.c b/bertos/mware/formatwr.c new file mode 100644 index 00000000..6353e1f1 --- /dev/null +++ b/bertos/mware/formatwr.c @@ -0,0 +1,945 @@ +/** + * \file + * + * + * \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 + * channels 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: + * + * \code + * -D CONFIG_PRINTF=PRINTF_FULL Full ANSI printf formatter + * -D CONFIG_PRINTF=PRINTF_NOFLOAT Exclude support for floats + * -D CONFIG_PRINTF=PRINTF_REDUCED Simplified formatter (see below) + * -D CONFIG_PRINTF=PRINTF_NOMODIFIERS Exclude 'l' and 'h' modifiers in reduced version + * -D CONFIG_PRINTF=PRINTF_DISABLED No formatter at all + * \endcode + * + * Code size on AVR4 with GCC 3.4.1 (-O2): + * PRINTF_FULL 2912byte (0xB60) + * PRINTF_NOFLOAT 1684byte (0x694) + * PRINTF_REDUCED 924byte (0x39C) + * PRINTF_NOMODIFIERS 416byte (0x1A0) + * + * Code/data size in words on DSP56K with CodeWarrior 6.0: + * PRINTF_FULL 1493/45 + * PRINTF_NOFLOAT 795/45 + * PRINTF_REDUCED 482/0 + * PRINTF_NOMODIFIERS 301/0 + * + * 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. + */ + + +#include "formatwr.h" +#include +#include +#include /* ASSERT */ +#include /* CONFIG_ macros */ + +#ifndef CONFIG_PRINTF_N_FORMATTER + /** Disable the arcane %n formatter. */ + #define CONFIG_PRINTF_N_FORMATTER 0 +#endif + +#ifndef CONFIG_PRINTF_OCTAL_FORMATTER + /** Disable the %o formatter. */ + #define CONFIG_PRINTF_OCTAL_FORMATTER 0 +#endif + +/* True if we must keep a count of the number of characters we print. */ +#define CONFIG_PRINTF_COUNT_CHARS (CONFIG_PRINTF_RETURN_COUNT || CONFIG_PRINTF_N_FORMATTER) + +#if CONFIG_PRINTF + +#if CONFIG_PRINTF > PRINTF_NOFLOAT + #include + + /* Maximum precision for floating point values */ + typedef long double max_float_t; + + /*bernie: save some memory, who cares about floats with lots of decimals? */ + #define FRMWRI_BUFSIZE 134 + #warning 134 is too much, the code must be fixed to have a lower precision limit +#else + /* + * Conservative estimate. Should be (probably) 12 (which is the size necessary + * to represent (2^32-1) in octal plus the sign bit. + */ + #define FRMWRI_BUFSIZE 16 +#endif + +/* Probably useful for fancy microcontrollers such as the PIC, nobody knows. */ +#ifndef MEM_ATTRIBUTE +#define MEM_ATTRIBUTE +#endif + +#if CONFIG_PRINTF > PRINTF_NOMODIFIERS + #define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier)) +#else + #define IS_SHORT (sizeof(int) == 2) +#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ + + +#if CONFIG_PRINTF > PRINTF_NOFLOAT + +static char *float_conversion(MEM_ATTRIBUTE max_float_t value, + MEM_ATTRIBUTE short nr_of_digits, + MEM_ATTRIBUTE char *buf, + MEM_ATTRIBUTE char format_flag, + MEM_ATTRIBUTE char g_flag, + MEM_ATTRIBUTE bool 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 = true; + } + + /* %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 -= (max_float_t)(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 /* CONFIG_PRINTF > PRINTF_NOFLOAT */ + +/** + * 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) +{ +#if CONFIG_PRINTF > PRINTF_REDUCED + MEM_ATTRIBUTE static char bad_conversion[] = "???"; + MEM_ATTRIBUTE static char null_pointer[] = ""; + + MEM_ATTRIBUTE int precision; + MEM_ATTRIBUTE int n; +#if CONFIG_PRINTF_COUNT_CHARS + MEM_ATTRIBUTE int nr_of_chars; +#endif + MEM_ATTRIBUTE int field_width; + MEM_ATTRIBUTE char format_flag; + enum PLUS_SPACE_FLAGS { + PSF_NONE, PSF_PLUS, PSF_MINUS + }; + enum DIV_FACTOR { + DIV_DEC, DIV_HEX, +#if CONFIG_PRINTF_OCTAL_FORMATTER + DIV_OCT, +#endif + }; + MEM_ATTRIBUTE struct { + enum PLUS_SPACE_FLAGS plus_space_flag : 2; +#if CONFIG_PRINTF_OCTAL_FORMATTER + enum DIV_FACTOR div_factor : 2; +#else + enum DIV_FACTOR div_factor : 1; +#endif + bool left_adjust : 1; + bool l_L_modifier : 1; + bool h_modifier : 1; + bool alternate_flag : 1; + bool nonzero_value : 1; + bool zeropad : 1; +#if CPU_HARVARD + bool progmem : 1; +#endif + } flags; + MEM_ATTRIBUTE unsigned long ulong; + +#if CONFIG_PRINTF > PRINTF_NOFLOAT + MEM_ATTRIBUTE max_float_t fvalue; +#endif + + MEM_ATTRIBUTE char *buf_pointer; + MEM_ATTRIBUTE char *ptr; + MEM_ATTRIBUTE const char *hex; + MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE]; + +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars = 0; +#endif + for (;;) /* Until full format string read */ + { + while ((format_flag = PGM_READ_CHAR(format++)) != '%') /* Until '%' or '\0' */ + { + if (!format_flag) +#if CONFIG_PRINTF_RETURN_COUNT + return (nr_of_chars); +#else + return 0; +#endif + put_one_char(format_flag, secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + if (PGM_READ_CHAR(format) == '%') /* %% prints as % */ + { + format++; + put_one_char('%', secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + continue; + } + + flags.left_adjust = false; + flags.alternate_flag = false; + flags.plus_space_flag = PSF_NONE; + flags.zeropad = false; +#if CPU_HARVARD + flags.progmem = false; +#endif + ptr = buf_pointer = &buf[0]; + hex = HEX_tab; + + /* check for leading '-', '+', ' ','#' or '0' flags */ + for (;;) + { + switch (PGM_READ_CHAR(format)) + { + case ' ': + if (flags.plus_space_flag) + goto NEXT_FLAG; + case '+': + flags.plus_space_flag = PSF_PLUS; + goto NEXT_FLAG; + case '-': + flags.left_adjust = true; + goto NEXT_FLAG; + case '#': + flags.alternate_flag = true; + goto NEXT_FLAG; + case '0': + flags.zeropad = true; + 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; + flags.left_adjust = true; + } + 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 (flags.left_adjust) + flags.zeropad = false; + + /* 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. + */ + + flags.l_L_modifier = false; + flags.h_modifier = false; + + /* Optional 'l','L','z' or 'h' modifier? */ + switch (PGM_READ_CHAR(format)) + { + case 'l': + case 'L': + case 'z': + flags.l_L_modifier = true; + format++; + break; + case 'h': + flags.h_modifier = true; + 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 CONFIG_PRINTF_N_FORMATTER + case 'n': + if (sizeof(short) != sizeof(int)) + { + if (sizeof(int) != sizeof(long)) + { + if (h_modifier) + *va_arg(ap, short *) = nr_of_chars; + else if (flags.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 (flags.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; + + /* Custom formatter for strings in program memory. */ + case 'S': +#if CPU_HARVARD + flags.progmem = true; +#endif + /* Fall trough */ + + case 's': + if ( !(buf_pointer = va_arg(ap, char *)) ) + buf_pointer = null_pointer; + if (precision < 0) + precision = 10000; + + /* + * Move `ptr' to the last character of the + * string that will be actually printed. + */ + ptr = buf_pointer; +#if CPU_HARVARD + if (flags.progmem) + { + for (n=0; pgm_read_char(ptr) && n < precision; n++) + ++ptr; + } + else +#endif + for (n=0; *ptr && n < precision; n++) + ++ptr; + break; + +#if CONFIG_PRINTF_OCTAL_FORMATTER + case 'o': + if (flags.alternate_flag && !precision) + precision++; +#endif + case 'x': + hex = hex_tab; + 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 (flags.l_L_modifier) + ulong = va_arg(ap, unsigned long); + else if (flags.h_modifier) + ulong = (unsigned long)(unsigned short)va_arg(ap, unsigned int); + else + ulong = va_arg(ap, unsigned int); + + flags.div_factor = +#if CONFIG_PRINTF_OCTAL_FORMATTER + (format_flag == 'o') ? DIV_OCT : +#endif + (format_flag == 'u') ? DIV_DEC : DIV_HEX; + flags.plus_space_flag = PSF_NONE; + goto INTEGRAL_CONVERSION; + + case 'd': + case 'i': + if (flags.l_L_modifier) + ulong = (unsigned long)(long)va_arg(ap, long); + else + ulong = (unsigned long)(long)va_arg(ap, int); + + /* Extract sign */ + if ((signed long)ulong < 0) + { + flags.plus_space_flag = PSF_MINUS; + ulong = (unsigned long)(-((signed long)ulong)); + } + + flags.div_factor = DIV_DEC; + + /* Now convert to digits */ +INTEGRAL_CONVERSION: + ptr = buf_pointer = &buf[FRMWRI_BUFSIZE - 1]; + flags.nonzero_value = (ulong != 0); + + /* No char if zero and zero precision */ + if (precision != 0 || flags.nonzero_value) + { + switch (flags.div_factor) + { + case DIV_DEC: + do + *--buf_pointer = hex[ulong % 10]; + while (ulong /= 10); + break; + + case DIV_HEX: + do + *--buf_pointer = hex[ulong % 16]; + while (ulong /= 16); + break; +#if CONFIG_PRINTF_OCTAL_FORMATTER + case DIV_OCT: + do + *--buf_pointer = hex[ulong % 8]; + while (ulong /= 8); + break; +#endif + } + } + + /* "precision" takes precedence */ + if (precision < 0) + if (flags.zeropad) + precision = field_width - (flags.plus_space_flag != PSF_NONE); + while (precision > (int)(ptr - buf_pointer)) + *--buf_pointer = '0'; + + if (flags.alternate_flag && flags.nonzero_value) + { + if (format_flag == 'x' || format_flag == 'X') + { + *--buf_pointer = format_flag; + *--buf_pointer = '0'; + } +#if CONFIG_PRINTF_OCTAL_FORMATTER + else if ((format_flag == 'o') && (*buf_pointer != '0')) + { + *--buf_pointer = '0'; + } +#endif + } + ASSERT(buf_pointer >= buf); + break; + +#if CONFIG_PRINTF > PRINTF_NOFLOAT + 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(max_float_t)) + { + fvalue = flags.l_L_modifier ? + va_arg(ap,max_float_t) : va_arg(ap,double); + } + else + fvalue = va_arg(ap,max_float_t); + + if (fvalue < 0) + { + flags.plus_space_flag = PSF_MINUS; + fvalue = -fvalue; + } + ptr = float_conversion (fvalue, + (short)precision, + buf_pointer += field_width, + format_flag, + (char)n, + flags.alternate_flag); + if (flags.zeropad) + { + precision = field_width - (flags.plus_space_flag != PSF_NONE); + while (precision > ptr - buf_pointer) + *--buf_pointer = '0'; + } + break; + +#endif /* CONFIG_PRINTF <= PRINTF_NOFLOAT */ + + case '\0': /* Really bad place to find NUL in */ + format--; + + default: + /* Undefined conversion! */ + ptr = buf_pointer = bad_conversion; + ptr += sizeof(bad_conversion) - 1; + 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 - (flags.plus_space_flag != PSF_NONE); + } + + /* emit any leading pad characters */ + if (!flags.left_adjust) + while (--n >= 0) + { + put_one_char(' ', secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + + /* emit flag characters (if any) */ + if (flags.plus_space_flag) + { + put_one_char(flags.plus_space_flag == PSF_PLUS ? '+' : '-', secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + +#if CPU_HARVARD + if (flags.progmem) + { + while (--precision >= 0) + { + put_one_char(pgm_read_char(buf_pointer++), secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + } + else +#endif /* CPU_HARVARD */ + { + /* emit the string itself */ + while (--precision >= 0) + { + put_one_char(*buf_pointer++, secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + } + + /* emit trailing space characters */ + if (flags.left_adjust) + while (--n >= 0) + { + put_one_char(' ', secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; +#endif + } + } + +#else /* PRINTF_REDUCED starts here */ + +#if CONFIG_PRINTF > PRINTF_NOMODIFIERS + bool l_modifier, h_modifier; + unsigned long u_val, div_val; +#else + unsigned int u_val, div_val; +#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ + + 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++; + } + +#if CONFIG_PRINTF > PRINTF_NOMODIFIERS + /*=================================*/ + /* Optional 'l' or 'h' modifiers ? */ + /*=================================*/ + l_modifier = h_modifier = false; + switch (PGM_READ_CHAR(format)) + { + case 'l': + l_modifier = true; + format++; + break; + + case 'h': + h_modifier = true; + format++; + break; + } +#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ + + 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: +#if CONFIG_PRINTF > PRINTF_NOMODIFIERS + 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 /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ + u_val = va_arg(ap,int); +#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ + 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 /* CONFIG_PRINTF > PRINTF_REDUCED */ +} + +#endif /* CONFIG_PRINTF */ diff --git a/bertos/mware/formatwr.h b/bertos/mware/formatwr.h new file mode 100644 index 00000000..5854bd4a --- /dev/null +++ b/bertos/mware/formatwr.h @@ -0,0 +1,78 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief Basic "printf", "sprintf" and "fprintf" formatter. + */ + +#ifndef MWARE_FORMATWR_H +#define MWARE_FORMATWR_H + +#include /* va_list */ +#include +#include /* CPU_HARVARD */ + +/** + * \name _formatted_write() configuration + * \{ + */ +#define PRINTF_DISABLED 0 +#define PRINTF_NOMODIFIERS 1 +#define PRINTF_REDUCED 2 +#define PRINTF_NOFLOAT 3 +#define PRINTF_FULL 4 +/* \} */ + +#ifndef CONFIG_PRINTF_RETURN_COUNT + /** Enable/disable _formatted_write return value */ + #define CONFIG_PRINTF_RETURN_COUNT 1 +#endif + +int +_formatted_write( + const char *format, + void put_char_func(char c, void *user_data), + void *user_data, + va_list ap); + +#if CPU_HARVARD + #include + int _formatted_write_P( + const char * PROGMEM format, + void put_char_func(char c, void *user_data), + void *user_data, + va_list ap); +#endif /* CPU_HARVARD */ + +#endif /* MWARE_FORMATWR_H */ + diff --git a/bertos/mware/hashtable.c b/bertos/mware/hashtable.c new file mode 100644 index 00000000..d3797339 --- /dev/null +++ b/bertos/mware/hashtable.c @@ -0,0 +1,391 @@ +/** + * \file + * + * + * \brief Portable hash table implementation + * + * Some rationales of our choices in implementation: + * + * \li For embedded systems, it is vital to allocate the table in static memory. To do + * so, it is necessary to expose the \c HashNode and \c HashTable structures in the header file. + * Nevertheless, they should be used as opaque types (that is, the users should not + * access the structure fields directly). + * + * \li To statically allocate the structures, a macro is provided. With this macro, we + * are hiding completely \c HashNode to the user (who only manipulates \c HashTable). Without + * the macro, the user would have had to define both the \c HashNode and the \c HashTable + * manually, and pass both of them to \c ht_init() (which would have created the link between + * the two). Instead, the link is created with a literal initialization. + * + * \li The hash table is created as power of two to remove the divisions from the code. + * Of course, hash functions work at their best when the table size is a prime number. + * When calculating the modulus to convert the hash value to an index, the actual operation + * becomes a bitwise AND: this is fast, but truncates the value losing bits. Thus, the higher + * bits are first "merged" with the lower bits through some XOR operations (see the last line of + * \c calc_hash()). + * + * \li To minimize the memory occupation, there is no flag to set for the empty node. An + * empty node is recognized by its data pointer set to NULL. It is then invalid to store + * NULL as data pointer in the table. + * + * \li The visiting interface through iterators is implemented with pass-by-value semantic. + * While this is overkill for medium-to-stupid compilers, it is the best designed from an + * user point of view. Moreover, being totally inlined (defined completely in the header), + * even a stupid compiler should be able to perform basic optimizations on it. + * We thought about using a pass-by-pointer semantic but it was much more awful to use, and + * the compiler is then forced to spill everything to the stack (unless it is *very* smart). + * + * \li The current implementation allows to either store the key internally (that is, copy + * the key within the hash table) or keep it external (that is, a hook is used to extract + * the key from the data in the node). The former is more memory-hungry of course, as it + * allocated static space to store the key copies. The overhead to keep both methods at + * the same time is minimal: + *
    + *
  • There is a run-time check in node_get_key which is execute per each node visited.
  • + *
  • Theoretically, there is no memory overhead. In practice, there were no + * flags in \c struct HashTable till now, so we had to add a first bit flag, but the + * overhead will disappear if a second flag is added for a different reason later.
  • + *
  • There is a little interface overhead, since we have two different versions of + * \c ht_insert(), one with the key passed as parameter and one without, but in + * the common case (external keys) both can be used.
  • + *
+ * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +/*#* + *#* $Log$ + *#* Revision 1.8 2007/02/06 16:05:01 asterix + *#* Replaced ROTATE_* with ROT* defined in macros.h + *#* + *#* Revision 1.7 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2006/06/01 12:27:39 marco + *#* Added utilities for protocols + *#* + *#*/ + +#include "hashtable.h" +#include +#include +#include //ROTL(), ROTR(); + +#include + + + +typedef const void** HashNodePtr; +#define NODE_EMPTY(node) (!*(node)) +#define HT_HAS_INTERNAL_KEY(ht) (CONFIG_HT_OPTIONAL_INTERNAL_KEY && ht->flags.key_internal) + +/** For hash tables with internal keys, compute the pointer to the internal key for a given \a node. */ +INLINE uint8_t *key_internal_get_ptr(struct HashTable *ht, HashNodePtr node) +{ + uint8_t* key_buf = ht->key_data.mem; + size_t index; + + // Compute the index of the node and use it to move within the whole key buffer + index = node - &ht->mem[0]; + ASSERT(index < (size_t)(1 << ht->max_elts_log2)); + key_buf += index * (INTERNAL_KEY_MAX_LENGTH + 1); + + return key_buf; +} + + +INLINE void node_get_key(struct HashTable* ht, HashNodePtr node, const void** key, uint8_t* key_length) +{ + if (HT_HAS_INTERNAL_KEY(ht)) + { + uint8_t* k = key_internal_get_ptr(ht, node); + + // Key has its length stored in the first byte + *key_length = *k++; + *key = k; + } + else + *key = ht->key_data.hook(*node, key_length); +} + + +INLINE bool node_key_match(struct HashTable* ht, HashNodePtr node, const void* key, uint8_t key_length) +{ + const void* key2; + uint8_t key2_length; + + node_get_key(ht, node, &key2, &key2_length); + + return (key_length == key2_length && memcmp(key, key2, key_length) == 0); +} + + +static uint16_t calc_hash(const void* _key, uint8_t key_length) +{ + const char* key = (const char*)_key; + uint16_t hash = key_length; + int i; + int len = (int)key_length; + + for (i = 0; i < len; ++i) + hash = ROTL(hash, 4) ^ key[i]; + + return hash ^ (hash >> 6) ^ (hash >> 13); +} + + +static HashNodePtr perform_lookup(struct HashTable* ht, + const void* key, uint8_t key_length) +{ + uint16_t hash = calc_hash(key, key_length); + uint16_t mask = ((1 << ht->max_elts_log2) - 1); + uint16_t index = hash & mask; + uint16_t first_index = index; + uint16_t step; + HashNodePtr node; + + // Fast-path optimization: we check immediately if the current node + // is the one we were looking for, so we save the computation of the + // increment step in the common case. + node = &ht->mem[index]; + if (NODE_EMPTY(node) + || node_key_match(ht, node, key, key_length)) + return node; + + // Increment while going through the hash table in case of collision. + // This implements the double-hash technique: we use the higher part + // of the hash as a step increment instead of just going to the next + // element, to minimize the collisions. + // Notice that the number must be odd to be sure that the whole table + // is traversed. Actually MCD(table_size, step) must be 1, but + // table_size is always a power of 2, so we just ensure that step is + // never a multiple of 2. + step = (ROTR(hash, ht->max_elts_log2) & mask) | 1; + + do + { + index += step; + index &= mask; + + node = &ht->mem[index]; + if (NODE_EMPTY(node) + || node_key_match(ht, node, key, key_length)) + return node; + + // The check is done after the key compare. This actually causes + // one more compare in the case the table is full (since the first + // element was compared at the very start, and then at the end), + // but it makes faster the common path where we enter this loop + // for the first time, and index will not match first_index for + // sure. + } while (index != first_index); + + return NULL; +} + + +void ht_init(struct HashTable* ht) +{ + memset(ht->mem, 0, sizeof(ht->mem[0]) * (1 << ht->max_elts_log2)); +} + + +static bool insert(struct HashTable* ht, const void* key, uint8_t key_length, const void* data) +{ + HashNodePtr node; + + if (!data) + return false; + + if (HT_HAS_INTERNAL_KEY(ht)) + key_length = MIN(key_length, (uint8_t)INTERNAL_KEY_MAX_LENGTH); + + node = perform_lookup(ht, key, key_length); + if (!node) + return false; + + if (HT_HAS_INTERNAL_KEY(ht)) + { + uint8_t* k = key_internal_get_ptr(ht, node); + *k++ = key_length; + memcpy(k, key, key_length); + } + + *node = data; + return true; +} + + +bool ht_insert_with_key(struct HashTable* ht, const void* key, uint8_t key_length, const void* data) +{ +#ifdef _DEBUG + if (!HT_HAS_INTERNAL_KEY(ht)) + { + // Construct a fake node and use it to match the key + HashNodePtr node = &data; + if (!node_key_match(ht, node, key, key_length)) + { + ASSERT2(0, "parameter key is different from the external key"); + return false; + } + } +#endif + + return insert(ht, key, key_length, data); +} + + +bool ht_insert(struct HashTable* ht, const void* data) +{ + const void* key; + uint8_t key_length; + +#ifdef _DEBUG + if (HT_HAS_INTERNAL_KEY(ht)) + { + ASSERT("parameter cannot be a hash table with internal keys - use ht_insert_with_key()" + && 0); + return false; + } +#endif + + key = ht->key_data.hook(data, &key_length); + + return insert(ht, key, key_length, data); +} + + +const void* ht_find(struct HashTable* ht, const void* key, uint8_t key_length) +{ + HashNodePtr node; + + if (HT_HAS_INTERNAL_KEY(ht)) + key_length = MIN(key_length, (uint8_t)INTERNAL_KEY_MAX_LENGTH); + + node = perform_lookup(ht, key, key_length); + + if (!node || NODE_EMPTY(node)) + return NULL; + + return *node; +} + + +#if 0 + +#include + +bool ht_test(void); + +static const void* test_get_key(const void* ptr, uint8_t* length) +{ + const char* s = ptr; + *length = strlen(s); + return s; +} + +#define NUM_ELEMENTS 256 +DECLARE_HASHTABLE_STATIC(test1, 256, test_get_key); +DECLARE_HASHTABLE_INTERNALKEY_STATIC(test2, 256); + +static char data[NUM_ELEMENTS][10]; +static char keydomain[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +static bool single_test(void) +{ + int i; + + ht_init(&test1); + ht_init(&test2); + + for (i=0;i + * + * \brief Portable hash table + * + * This file implements a portable hash table, with the following features: + * + * \li Open double-hashing. The maximum number of elements is fixed. The double hashing + * function improves recovery in case of collisions. + * \li Configurable size (which is clamped to a power of two) + * \li Visiting interface through iterator (returns the element in random order). + * \li The key is stored within the data and a hook is used to extract it. Optionally, it + * is possible to store a copy of the key within the hash table. + * + * Since the hashing is open, there is no way to remove elements from the table. Instead, a + * function is provided to clear the table completely. + * + * The data stored within the table must be a pointer. The NULL pointer is used as + * a marker for a free node, so it is invalid to store a NULL pointer in the table + * with \c ht_insert(). + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + +/*#* + *#* $Log$ + *#* Revision 1.8 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.7 2006/06/01 12:27:39 marco + *#* Added utilities for protocols + *#* + *#*/ + +#ifndef MWARE_HASHTABLE_H +#define MWARE_HASHTABLE_H + +#include +#include +#include + +/** + * Enable/disable support to declare special hash tables which maintain a copy of + * the key internally instead of relying on the hook to extract it from the data. + */ +#define CONFIG_HT_OPTIONAL_INTERNAL_KEY 1 + +/// Maximum length of the internal key (use (2^n)-1 for slight speedup) +#define INTERNAL_KEY_MAX_LENGTH 15 + +/** + * Hook to get the key from \a data, which is an element of the hash table. The + * key must be returned together with \a key_length (in words). + */ +typedef const void *(*hook_get_key)(const void *data, uint8_t *key_length); + + +/** + * Hash table description + * + * \note This structures MUST NOT be accessed directly. Its definition is + * provided in the header file only for optimization purposes (see the rationale + * in hashtable.c). + * + * \note If new elements must be added to this list, please double check + * \c DECLARE_HASHTABLE, which requires the existing elements to be at the top. + */ +struct HashTable +{ + const void **mem; ///< Buckets of data + uint16_t max_elts_log2; ///< Log2 of the size of the table + struct { + bool key_internal : 1; ///< true if the key is copied internally + } flags; + union { + hook_get_key hook; ///< Hook to get the key + uint8_t *mem; ///< Pointer to the key memory + } key_data; +}; + + +/// Iterator to walk the hash table +typedef struct +{ + const void** pos; + const void** end; +} HashIterator; + + +/** + * Declare a hash table in the current scope + * + * \param name Variable name + * \param size Number of elements + * \param hook_gk Hook to be used to extract the key from the node + * + * \note The number of elements will be rounded down to the nearest + * power of two. + * + */ +#define DECLARE_HASHTABLE(name, size, hook_gk) \ + static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ + struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, hook_gk } + +/** Exactly like \c DECLARE_HASHTABLE, but the variable will be declared as static. */ +#define DECLARE_HASHTABLE_STATIC(name, size, hook_gk) \ + static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ + static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, { hook_gk } } + +#if CONFIG_HT_OPTIONAL_INTERNAL_KEY + /** Declare a hash table with internal copies of the keys. This version does not + * require a hook, nor it requires the user to allocate static memory for the keys. + * It is mostly suggested for tables whose keys are computed on the fly and need + * to be stored somewhere. + */ + #define DECLARE_HASHTABLE_INTERNALKEY(name, size) \ + static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \ + static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ + struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys } + + /** Exactly like \c DECLARE_HASHTABLE_INTERNALKEY, but the variable will be declared as static. */ + #define DECLARE_HASHTABLE_INTERNALKEY_STATIC(name, size) \ + static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \ + static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ + static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys } +#endif + +/** + * Initialize (and clear) a hash table in a memory buffer. + * + * \param ht Hash table declared with \c DECLARE_HASHTABLE + * + * \note This function must be called before using the hash table. Optionally, + * it can be called later in the program to clear the hash table, + * removing all its elements. + */ +void ht_init(struct HashTable* ht); + +/** + * Insert an element into the hash table + * + * \param ht Handle of the hash table + * \param data Data to be inserted into the table + * \return true if insertion was successful, false otherwise (table is full) + * + * \note The key for the element to insert is extract from the data with + * the hook. This means that this function cannot be called for hashtables + * with internal keys. + * + * \note If an element with the same key already exists in the table, + * it will be overwritten. + * + * \note It is not allowed to store NULL in the table. If you pass NULL as data, + * the function call will fail. + */ +bool ht_insert(struct HashTable* ht, const void* data); + +/** + * Insert an element into the hash table + * + * \param ht Handle of the hash table + * \param key Key of the element + * \param key_length Length of the key in characters + * \param data Data to be inserted into the table + * \return true if insertion was successful, false otherwise (table is full) + * + * \note If this function is called for hash table with external keys, + * the key provided must be match the key that would be extracted with the + * hook, otherwise the function will fail. + * + * \note If an element with the same key already exists in the table, + * it will be overwritten. + * + * \note It is not allowed to store NULL in the table. If you pass NULL as data, + * the function call will fail. + */ +bool ht_insert_with_key(struct HashTable* ht, const void* key, uint8_t key_length, const void* data); + +/** + * Find an element in the hash table + * + * \param ht Handle of the hash table + * \param key Key of the element + * \param key_length Length of the key in characters + * \return Data of the element, or NULL if no element was found for the given key. + */ +const void* ht_find(struct HashTable* ht, const void* key, uint8_t key_length); + +/** Similar to \c ht_insert_with_key() but \a key is an ASCIIZ string */ +#define ht_insert_str(ht, key, data) ht_insert_with_key(ht, key, strlen(key), data) + +/** Similar to \c ht_find() but \a key is an ASCIIZ string */ +#define ht_find_str(ht, key) ht_find(ht, key, strlen(key)) + +/// Get an iterator to the begin of the hash table \a ht +INLINE HashIterator ht_iter_begin(struct HashTable* ht) +{ + HashIterator h; + + h.pos = &ht->mem[0]; + h.end = &ht->mem[1 << ht->max_elts_log2]; + + while (h.pos != h.end && !*h.pos) + ++h.pos; + + return h; +} + +/** + * Get an iterator to the (exclusive) end of the hash table \a ht + * + * \note Like in STL, the end iterator is not a valid iterator (you + * cannot call \c ht_iter_get() on it), and it must be used only to + * detect if we reached the end of the iteration (through \c ht_iter_cmp()). + */ +INLINE HashIterator ht_iter_end(struct HashTable* ht) +{ + HashIterator h; + + h.pos = h.end = &ht->mem[1 << ht->max_elts_log2]; + + return h; +} + +/// Compare \a it1 and \a it2 for equality +INLINE bool ht_iter_cmp(HashIterator it1, HashIterator it2) +{ + ASSERT(it1.end == it2.end); + return it1.pos == it2.pos; +} + +/// Get the element within the hash table \a ht pointed by the iterator \a iter +INLINE const void* ht_iter_get(HashIterator iter) +{ return *iter.pos; } + +/** Return an iterator pointing to the element following \a h + * + * \note The order of the elements visited during the iteration is casual, + * and depends on the implementation. + * + */ +INLINE HashIterator ht_iter_next(HashIterator h) +{ + ++h.pos; + while (h.pos != h.end && !(*h.pos)) + ++h.pos; + + return h; +} + +#endif /* MWARE_HASHTABLE_H */ diff --git a/bertos/mware/heap.c b/bertos/mware/heap.c new file mode 100644 index 00000000..bced107e --- /dev/null +++ b/bertos/mware/heap.c @@ -0,0 +1,265 @@ +/** + * \file + * + * + * \brief Heap subsystem (public interface). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.9 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.8 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.7 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.6 2004/10/26 09:02:13 bernie + *#* heap_free(): Handle NULL pointers like free(), write documentation. + *#* + *#* Revision 1.5 2004/10/03 20:43:22 bernie + *#* Import changes from sc/firmware. + *#* + *#* Revision 1.1 2004/07/31 16:33:58 rasky + *#* Spostato lo heap da kern/ a mware/ + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 17:27:00 bernie + *#* Import kern/ subdirectory. + *#* + *#*/ + +#include "heap.h" +#include // memset() +#include // IS_POW2() +#include // ASSERT() + +/* NOTE: struct size must be a 2's power! */ +typedef struct _MemChunk +{ + struct _MemChunk *next; + size_t size; +} MemChunk; + +STATIC_ASSERT(IS_POW2(sizeof(MemChunk))); + +#define FREE_FILL_CODE 0xDEAD +#define ALLOC_FILL_CODE 0xBEEF + +void heap_init(struct Heap* h, void* memory, size_t size) +{ +#ifdef _DEBUG + memset(memory, FREE_FILL_CODE, size); +#endif + + /* Initialize heap with a single big chunk */ + h->FreeList = (MemChunk *)memory; + h->FreeList->next = NULL; + h->FreeList->size = size; +} + + +void *heap_allocmem(struct Heap* h, size_t size) +{ + MemChunk *chunk, *prev; + + /* Round size up to the allocation granularity */ + size = ROUND2(size, sizeof(MemChunk)); + + /* Handle allocations of 0 bytes */ + if (!size) + size = sizeof(MemChunk); + + /* Walk on the free list looking for any chunk big enough to + * fit the requested block size. + */ + for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList; + chunk; + prev = chunk, chunk = chunk->next) + { + if (chunk->size >= size) + { + if (chunk->size == size) + { + /* Just remove this chunk from the free list */ + prev->next = chunk->next; + #ifdef _DEBUG + memset(chunk, ALLOC_FILL_CODE, size); + #endif + return (void *)chunk; + } + else + { + /* Allocate from the END of an existing chunk */ + chunk->size -= size; + #ifdef _DEBUG + memset((uint8_t *)chunk + chunk->size, ALLOC_FILL_CODE, size); + #endif + return (void *)((uint8_t *)chunk + chunk->size); + } + } + } + + return NULL; /* fail */ +} + + +void heap_freemem(struct Heap* h, void *mem, size_t size) +{ + MemChunk *prev; + + ASSERT(mem); + +#ifdef _DEBUG + memset(mem, FREE_FILL_CODE, size); +#endif + + /* Round size up to the allocation granularity */ + size = ROUND2(size, sizeof(MemChunk)); + + /* Handle allocations of 0 bytes */ + if (!size) + size = sizeof(MemChunk); + + /* Special case: first chunk in the free list */ + ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList); + if (((uint8_t *)mem) < ((uint8_t *)h->FreeList)) + { + /* Insert memory block before the current free list head */ + prev = (MemChunk *)mem; + prev->next = h->FreeList; + prev->size = size; + h->FreeList = prev; + } + else /* Normal case: not the first chunk in the free list */ + { + /* + * Walk on the free list. Stop at the insertion point (when mem + * is between prev and prev->next) + */ + prev = h->FreeList; + while (prev->next < (MemChunk *)mem && prev->next) + prev = prev->next; + + /* Make sure mem is not *within* prev */ + ASSERT((uint8_t*)mem >= (uint8_t*)prev + prev->size); + + /* Should it be merged with previous block? */ + if (((uint8_t *)prev) + prev->size == ((uint8_t *)mem)) + { + /* Yes */ + prev->size += size; + } + else /* not merged with previous chunk */ + { + MemChunk *curr = (MemChunk*)mem; + + /* insert it after the previous node + * and move the 'prev' pointer forward + * for the following operations + */ + curr->next = prev->next; + curr->size = size; + prev->next = curr; + + /* Adjust for the following test */ + prev = curr; + } + } + + /* Also merge with next chunk? */ + if (((uint8_t *)prev) + prev->size == ((uint8_t *)prev->next)) + { + prev->size += prev->next->size; + prev->next = prev->next->next; + + /* There should be only one merge opportunity, becuase we always merge on free */ + ASSERT((uint8_t*)prev + prev->size != (uint8_t*)prev->next); + } +} + +#if CONFIG_HEAP_MALLOC + +void *heap_malloc(struct Heap* h, size_t size) +{ + size_t *mem; + + size += sizeof(size_t); + if ((mem = (size_t*)heap_allocmem(h, size))) + *mem++ = size; + + return mem; +} + +void *heap_calloc(struct Heap* h, size_t size) +{ + void *mem; + + if ((mem = heap_malloc(h, size))) + memset(mem, 0, size); + + return mem; +} + +/** + * Free a block of memory, determining its size automatically. + * + * \param h Heap from which the block was allocated. + * \param mem Pointer to a block of memory previously allocated with + * either heap_malloc() or heap_calloc(). + * + * \note If \a mem is a NULL pointer, no operation is performed. + * + * \note Freeing the same memory block twice has undefined behavior. + * + * \note This function works like the ANSI C free(). + */ +void heap_free(struct Heap *h, void *mem) +{ + size_t *_mem = (size_t *)mem; + + if (_mem) + { + --_mem; + heap_freemem(h, _mem, *_mem); + } +} + +#endif /* CONFIG_HEAP_MALLOC */ diff --git a/bertos/mware/heap.h b/bertos/mware/heap.h new file mode 100644 index 00000000..97cef8a3 --- /dev/null +++ b/bertos/mware/heap.h @@ -0,0 +1,123 @@ +/** + * \file + * + * + * \brief Heap subsystem (public interface). + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \todo Heap memory could be defined as an array of MemChunk, and used + * in this form also within the implementation. This would probably remove + * memory alignment problems, and also some aliasing issues. + * + */ + +/*#* + *#* $Log$ + *#* Revision 1.7 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.6 2005/11/27 23:36:19 bernie + *#* Use appconfig.h instead of cfg/config.h. + *#* + *#* Revision 1.5 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.4 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.3 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.2 2004/08/04 15:54:18 rasky + *#* Merge da SC: prima versione veramente funzionante + *#* + *#* Revision 1.1 2004/07/31 16:33:58 rasky + *#* Spostato lo heap da kern/ a mware/ + *#* + *#* Revision 1.2 2004/06/03 11:27:09 bernie + *#* Add dual-license information. + *#* + *#* Revision 1.1 2004/05/23 17:27:00 bernie + *#* Import kern/ subdirectory. + *#* + *#*/ + +#ifndef MWARE_HEAP_H +#define MWARE_HEAP_H + +#include +#include + +struct _MemChunk; + +/// A heap +struct Heap +{ + struct _MemChunk *FreeList; ///< Head of the free list +}; + + +/// Initialize \a heap within the buffer pointed by \a memory which is of \a size bytes +void heap_init(struct Heap* heap, void* memory, size_t size); + +/// Allocate a chunk of memory of \a size bytes from the heap +void *heap_allocmem(struct Heap* heap, size_t size); + +/// Free a chunk of memory of \a size bytes from the heap +void heap_freemem(struct Heap* heap, void *mem, size_t size); + + +#define HNEW(heap, type) \ + (type*)heap_allocmem(heap, sizeof(type)) + +#define HNEWVEC(heap, type, nelem) \ + (type*)heap_allocmem(heap, sizeof(type) * (nelem)) + +#define HDELETE(heap, type, mem) \ + heap_freemem(heap, mem, sizeof(type)) + +#define HDELETEVEC(heap, type, nelem, mem) \ + heap_freemem(heap, mem, sizeof(type) * (nelem)) + + +#if CONFIG_HEAP_MALLOC + +void *heap_malloc(struct Heap* heap, size_t size); +void *heap_calloc(struct Heap* heap, size_t size); +void heap_free(struct Heap* heap, void * mem); + +#endif + +#endif /* MWARE_HEAP_H */ diff --git a/bertos/mware/hex.c b/bertos/mware/hex.c new file mode 100644 index 00000000..01c41642 --- /dev/null +++ b/bertos/mware/hex.c @@ -0,0 +1,44 @@ +/** + * \file + * + * + * \brief Poor man's hex arrays (implementation). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + + +#include "hex.h" + +const char hex_tab[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; +const char HEX_tab[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; diff --git a/bertos/mware/hex.h b/bertos/mware/hex.h new file mode 100644 index 00000000..2c703066 --- /dev/null +++ b/bertos/mware/hex.h @@ -0,0 +1,46 @@ +/** + * \file + * + * + * \brief Poor man's hex arrays (implementation). + * + * \version $Id$ + * + * \author Bernardo Innocenti + */ + +#ifndef MWARE_HEX_H +#define MWARE_HEX_H + +extern const char hex_tab[16]; +extern const char HEX_tab[16]; + +#endif /* MWARE_HEX_H */ diff --git a/bertos/mware/list.h b/bertos/mware/list.h new file mode 100644 index 00000000..ddbad8c4 --- /dev/null +++ b/bertos/mware/list.h @@ -0,0 +1,323 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief General pourpose double-linked lists + */ + +#ifndef MWARE_LIST_H +#define MWARE_LIST_H + +#include /* INLINE */ +#include /* ASSERT() */ + +/** + * This structure represents a node for bidirectional lists. + * + * Data is usually appended to nodes by making them the first + * field of another struture, as a poor-man's form of inheritance. + */ +typedef struct _Node +{ + struct _Node *succ; + struct _Node *pred; +} Node; + +/** + * Head of a doubly-linked list of \c Node structs. + * + * Lists must be initialized with LIST_INIT() prior to use. + * + * Nodes can be added and removed from either end of the list + * with O(1) performance. Iterating over these lists can be + * tricky: use the FOREACH_NODE() macro instead. + */ +typedef struct _List +{ + Node head; + Node tail; +} List; + +/** + * Extended node for priority queues. + */ +typedef struct _PriNode +{ + Node link; + int pri; +} PriNode; + + +/** + * Template for a naked node in a list of \a T structures. + * + * To be used as data member in other structures: + * + * \code + * struct Foo + * { + * DECLARE_NODE_ANON(struct Foo) + * int a; + * float b; + * } + * + * DECLARE_LIST_TYPE(Foo); + * + * void foo(void) + * { + * static LIST_TYPE(Foo) foo_list; + * static Foo foo1, foo2; + * Foo *fp; + * + * LIST_INIT(&foo_list); + * ADDHEAD(&foo_list, &foo1); + * INSERT_BEFORE(&foo_list, &foo2); + * FOREACH_NODE(fp, &foo_list) + * fp->a = 10; + * } + * + * \endcode + */ +#define DECLARE_NODE_ANON(T) \ + T *succ; T *pred; + +/** Declare a typesafe node for structures of type \a T. */ +#define DECLARE_NODE_TYPE(T) \ + typedef struct T##Node { T *succ; T *pred; } T##Node + +/** Template for a list of \a T structures. */ +#define DECLARE_LIST_TYPE(T) \ + DECLARE_NODE_TYPE(T); \ + typedef struct T##List { \ + T##Node head; \ + T##Node tail; \ + } T##List + +#define NODE_TYPE(T) T##Node +#define LIST_TYPE(T) T##List + +/** + * Get a pointer to the first node in a list. + * + * If \a l is empty, result points to l->tail. + */ +#define LIST_HEAD(l) ((l)->head.succ) + +/** + * Get a pointer to the last node in a list. + * + * If \a l is empty, result points to l->head. + */ +#define LIST_TAIL(l) ((l)->tail.pred) + +// TODO: move in compiler.h +#if COMPILER_TYPEOF + #define TYPEOF_OR_VOIDPTR(type) typeof(type) +#else + #define TYPEOF_OR_VOIDPTR(type) void * +#endif + +/** + * Iterate over all nodes in a list. + * + * This macro generates a "for" statement using the following parameters: + * \param n Node pointer to be used in each iteration. + * \param l Pointer to list. + */ +#define FOREACH_NODE(n, l) \ + for( \ + (n) = (TYPEOF_OR_VOIDPTR(n))LIST_HEAD(l); \ + ((Node *)(n))->succ; \ + (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->succ) \ + ) + +/** + * Iterate backwards over all nodes in a list. + * + * This macro generates a "for" statement using the following parameters: + * \param n Node pointer to be used in each iteration. + * \param l Pointer to list. + */ +#define REVERSE_FOREACH_NODE(n, l) \ + for( \ + (n) = (TYPEOF_OR_VOIDPTR(n))LIST_TAIL(l); \ + ((Node *)(n))->pred; \ + (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->pred) \ + ) + +/** Initialize a list. */ +#define LIST_INIT(l) \ + do { \ + (l)->head.succ = (TYPEOF_OR_VOIDPTR((l)->head.succ)) &(l)->tail; \ + (l)->head.pred = NULL; \ + (l)->tail.succ = NULL; \ + (l)->tail.pred = (TYPEOF_OR_VOIDPTR((l)->tail.pred)) &(l)->head; \ + } while (0) + +#ifdef _DEBUG + /** Make sure that a list is valid (it was initialized and is not corrupted). */ + #define LIST_ASSERT_VALID(l) \ + do { \ + Node *n, *pred; \ + ASSERT((l)->head.succ != NULL); \ + ASSERT((l)->head.pred == NULL); \ + ASSERT((l)->tail.succ == NULL); \ + ASSERT((l)->tail.pred != NULL); \ + pred = &(l)->head; \ + FOREACH_NODE(n, l) \ + { \ + ASSERT(n->pred == pred); \ + pred = n; \ + } \ + ASSERT(n == &(l)->tail); \ + } while (0) + + #define INVALIDATE_NODE(n) ((n)->succ = (n)->pred = NULL) +#else + #define LIST_ASSERT_VALID(l) do {} while (0) + #define INVALIDATE_NODE(n) do {} while (0) +#endif + +/** Add node to list head. */ +#define ADDHEAD(l,n) \ + do { \ + ASSERT(l); \ + ASSERT(n); \ + (n)->succ = (l)->head.succ; \ + (n)->pred = (l)->head.succ->pred; \ + (n)->succ->pred = (n); \ + (n)->pred->succ = (n); \ + } while (0) + +/** Add node to list tail. */ +#define ADDTAIL(l,n) \ + do { \ + ASSERT(l); \ + ASSERT(n); \ + (n)->succ = &(l)->tail; \ + (n)->pred = (l)->tail.pred; \ + (n)->pred->succ = (n); \ + (l)->tail.pred = (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 INSERT_BEFORE(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. + * + * \note Removing a node that has not previously been + * inserted into a list invokes undefined behavior. + */ +#define REMOVE(n) \ + do { \ + (n)->pred->succ = (n)->succ; \ + (n)->succ->pred = (n)->pred; \ + INVALIDATE_NODE(n); \ + } while (0) + +/** Tell whether a list is empty. */ +#define LIST_EMPTY(l) ( (void *)((l)->head.succ) == (void *)(&(l)->tail) ) + +/** + * Insert a priority node in a priority queue. + * + * The new node is inserted immediately before the + * first node with lower priority or appended to + * the tail if no such node exists. + */ +#define LIST_ENQUEUE(list, node) \ + do { \ + PriNode *ln; \ + FOREACH_NODE(ln, (list)) \ + if (ln->pri < (node)->pri) \ + break; \ + INSERT_BEFORE(&(node)->link, &ln->link); \ + } while (0) + + +/** + * Unlink a node from the head of the list \a l. + * + * \return Pointer to node, or NULL if the list was empty. + */ +INLINE Node *list_remHead(List *l) +{ + Node *n; + + if (LIST_EMPTY(l)) + return (Node *)0; + + n = l->head.succ; /* Get first node. */ + l->head.succ = n->succ; /* Link list head to second node. */ + n->succ->pred = &l->head; /* Link second node to list head. */ + + INVALIDATE_NODE(n); + return n; +} + +/** + * Unlink a node from the tail of the list \a l. + * + * \return Pointer to node, or NULL if the list was empty. + */ +INLINE Node *list_remTail(List *l) +{ + Node *n; + + if (LIST_EMPTY(l)) + return (Node *)0; + + n = l->tail.pred; /* Get last node. */ + l->tail.pred = n->pred; /* Link list tail to second last node. */ + n->pred->succ = &l->tail; /* Link second last node to list tail. */ + + INVALIDATE_NODE(n); + return n; +} + +#endif /* MWARE_LIST_H */ diff --git a/bertos/mware/mean.h b/bertos/mware/mean.h new file mode 100644 index 00000000..893241e2 --- /dev/null +++ b/bertos/mware/mean.h @@ -0,0 +1,41 @@ +#warning revise me! + + +/** + * DECLARE_SMEAN(temperature, uint8_t, uint16_t); + * for (i = 0; i < TEMP_MEANS; ++i) + * SMEAN_ADD(temperature, adc_get(), TEMP_MEANS); + * printf("mean temperature = %d\n", SMEAN_GET(temperature)); + */ + +/** + * Instantiate a mean instance + */ +#define DECLARE_SMEAN(name, Type, SumType) \ + struct { \ + SumType sum; \ + Type result; \ + int count; \ + } name = { 0, 0, 0 } + +/** + * Insert a new sample into the mean. + * + * \note \a mean and \a max_samples are evaluated multiple times + */ +#define SMEAN_ADD(mean, sample, max_samples) \ + do { \ + (mean).sum += (sample); \ + if ((mean).count++ >= (max_samples)) \ + { \ + (mean).result = (mean).sum / (max_samples); \ + (mean).sum = 0; \ + (mean).count = 0; \ + } \ + } while (0) + +/** + * Return current mean value. + */ +#define SMEAN_GET(mean) ((mean).result) + diff --git a/bertos/mware/msg.c b/bertos/mware/msg.c new file mode 100644 index 00000000..f565c8ab --- /dev/null +++ b/bertos/mware/msg.c @@ -0,0 +1,78 @@ +/** + * \file + * + * + * \brief Messages for LCD. + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/07/19 12:56:28 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.1 2005/03/01 23:31:02 bernie + *#* String table and localization stuff. + *#* + *#*/ + +#include "msg.h" + +/** + * Array of pointers to localized strings. Should be filled + * by localization stuff, but not for now. + */ +const char *msg_strings[MSG_COUNT] = { + 0, + // TODO: add your strings here +}; + +/* Buffer for catalog file */ +/* char msg_buf[MSG_BUFSIZE]; */ + + +/* The following does not work (move string tables into the DMSG/CMSG segments) + * #pragma memory=dataseg(DMSG) + * #pragma memory=constseg(CMSG) + */ + + +/** + * Untranslated constant strings used more than once are + * grouped here to save ROM space. + */ +const char + str_empty[] = ""; + diff --git a/bertos/mware/msg.h b/bertos/mware/msg.h new file mode 100644 index 00000000..14d4c128 --- /dev/null +++ b/bertos/mware/msg.h @@ -0,0 +1,75 @@ +/** + * \file + * + * + * \brief Definitions of constant string messages. + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + */ + +/*#* + *#* $Log$ + *#* Revision 1.2 2006/02/10 11:30:37 bernie + *#* C++ fixes. + *#* + *#* Revision 1.1 2005/03/01 23:31:02 bernie + *#* String table and localization stuff. + *#* + *#*/ +#ifndef MWARE_MSG_H +#define MWARE_MSG_H + +enum +{ + MSG_NULL, + + // TODO: add your labels here. + + MSG_COUNT +}; + + +#define MSG_BUFSIZE 6144 /* FIXME: how much? */ + +/* String tables */ +extern const char *msg_strings const [MSG_COUNT]; +/* extern char msg_buf[MSG_BUFSIZE]; */ + + +/* Macros to access translated messages */ +#define MSG(x) msg_strings[x] +#define PTRMSG(x) ((x) < (const_iptr_t)256 ? msg_strings[(unsigned int)(x)] : (const char *)(x)) + + +#endif /* MWARE_MSG_H */ diff --git a/bertos/mware/observer.c b/bertos/mware/observer.c new file mode 100644 index 00000000..a3acf98c --- /dev/null +++ b/bertos/mware/observer.c @@ -0,0 +1,81 @@ +/** + * \file + * + * + * \brief Simple notifier for the observer/subject pattern (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "observer.h" +#include // IRQ_DISABLE/IRQ_ENABLE + + +void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)) +{ + observer->event = event; +} + +void observer_InitSubject(Subject *subject) +{ + LIST_INIT(&subject->observers); +} + +void observer_Subscribe(Subject *subject, Observer *observer) +{ + ATOMIC(ADDHEAD(&subject->observers, &observer->link)); +} + +void observer_Unsubscribe(UNUSED_ARG(Subject *,subject), Observer *observer) +{ + ATOMIC(REMOVE(&observer->link)); +} + +void observer_notify(Subject *subject, int event_id, void *param) +{ + Observer *observer; + cpuflags_t irqstate; + IRQ_SAVE_DISABLE(irqstate); + + /* + * Run over list with protection against other + * threads, but re-enable irqs in callbacks. + */ + FOREACH_NODE(observer, &subject->observers) + { + IRQ_RESTORE(irqstate); + observer->event(event_id, param); + IRQ_SAVE_DISABLE(irqstate); + } + + IRQ_RESTORE(irqstate); +} diff --git a/bertos/mware/observer.h b/bertos/mware/observer.h new file mode 100644 index 00000000..39d33d68 --- /dev/null +++ b/bertos/mware/observer.h @@ -0,0 +1,96 @@ +/** + * \file + * + * + * \brief Simple notifier for the subject/observer pattern (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + */ +#ifndef MWARE_OBSERVER_H +#define MWARE_OBSERVER_H + +#include + +/** + * + * Here's a simple example: + * + * \code + * Subject kbd_driver; + * + * Observer kbd_observer; + * + * void key_pressed(int event, void *_param) + * { + * char *param = (char *)_param; + * + * if (event == EVENT_KBD_PRESSED) + * printf("You pressed %c\n", *param); + * } + * + * void register_kbd_listener(void) + * { + * observer_SetEvent(&kbd_observer, key_pressed); + * observer_Subscribe(&kbd_driver, &kbd_observer); + * } + * \endcode + */ +typedef struct Observer +{ + Node link; + void (*event)(int event_id, void *param); +} Observer; + +typedef struct Subject +{ + /// Subscribed observers. + List observers; + +} Subject; + +void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)); + +#define OBSERVER_INITIALIZER(callback) { { NULL, NULL }, callback } + +void observer_InitSubject(Subject *subject); + +/// Aggiunge un Observer all'insieme +void observer_Subscribe(Subject *subject, Observer *observer); + +/// Rimuove un Observer dall'insieme +void observer_Unsubscribe(Subject *subject, Observer *observer); + +/// per tutti gli elementi nel set notifica l'evento, chiamando la relativa +/// funzione event +void observer_notify(Subject *subject, int event_id, void *param); + +#endif /* MWARE_OBSERVER_H */ diff --git a/bertos/mware/parser.c b/bertos/mware/parser.c new file mode 100644 index 00000000..cc20b4e6 --- /dev/null +++ b/bertos/mware/parser.c @@ -0,0 +1,392 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * \author Giovanni Bajo + * + * \brief Serial protocol parser and commands. + * + * This file contains the serial protocol parser and + * the definition of the protocol commands. Commands are defined + * in a "CmdTemplate" type array, containing: + * - the name of the command, + * - the arguments it expects to receive, + * - the output values, + * - the name of the function implementing the command. + * + * The arguments and results are passed to command function + * using an union: the element of the union to use for each + * argument is determined by format strings present in the + * CmdTemplate table. + */ + + +#include "parser.h" +#include + +#include // atol(), NULL +#include // strchr(), strcmp() + +#include + +#include "appconfig.h" + +#define ARG_SEP_S " " +#define ARG_SEP_C ' ' + +#define MAX_COMMANDS_NUMBER 128 // 64 + +/// Hashtable hook to extract the key from a command +static const void* get_key_from_command(const void* cmd, uint8_t* length); + +/// Hashtable that handles the commands that can be executed +DECLARE_HASHTABLE_STATIC(commands, MAX_COMMANDS_NUMBER, get_key_from_command); + + +/** + * \brief Tokenize one word at a time from a text. + * + * This function is similar to strtok, but does not use any implicit + * context, nor it does modify the input buffer in any form. + * The word is returned as a STL-like [begin,end) range. + * + * To extract the first word, make both begin and end point at the + * start of the text, and call the function. Then, subsequent + * calls will return the following words (assuming the begin/end + * variable are not modified between calls). + * + * \param begin Will contain the index of the first character of the word + * \param end Will contain the index of the character after the last + * character of the word + * + * \return True if a word was extracted, false if we got to the end + * of the string without extracting any word. + */ +static bool get_word(const char **begin, const char **end) +{ + const char *cur = *end; + + while ((*cur == ' ' || *cur == '\t') && *cur) + ++cur; + + *begin = cur; + + while ((*cur != ' ' && *cur != '\t') && *cur) + ++cur; + + *end = cur; + + return (*end != *begin); +} + + +/** + * \brief Command arguments parser. + * + * Using the format pointed by the argument fmt + * parses the input string filling the array argv + * with input parameters of the correct type. + * + * \param fmt Parameters format string. + * \param input Input string. + * \param argv Array filled with parameters. + * + * \return False in case of errors, otherwise true. + */ +static bool parseArgs(const char *fmt, const char *input, parms argv[]) +{ + const char *begin = input, *end = input; + + while (*fmt) + { + // Extract the argument + if (!get_word(&begin, &end)) + return false; + + switch (*fmt) + { + case 'd': + (*argv++).l = atol(begin); + break; + + case 's': + (*argv++).s = begin; + break; + + default: + ASSERT2(0, "Unknown format for argument"); + return false; + } + + ++fmt; + } + + /* check if there are remaining args */ + if (get_word(&begin, &end)) + return false; + + return true; +} + + +#ifdef UNUSED_CODE +/** + * \brief Command result formatting and printing. + * + * Prints out on device fd the values contained + * in the array result, using the format specified + * in fmt. + * + * \param ser Serial handle. + * \param fmt Values format string. + * \param result Array containing result to be printed. + * + * \return -1 in case of errors, otherwise 0. + */ +static int printResult(struct Serial *ser, const char *fmt, parms result[]) +{ + long n; + char repeat_cnt = 0; + + while (*fmt) + { + if (*fmt >= '0' && *fmt <= '9') + { + /* Collect repeat count digit (left to right order) */ + repeat_cnt = (repeat_cnt * 10) + (*fmt - '0'); + } + else + { + /* Set default repeat cnt of 1 when not specified */ + if (repeat_cnt == 0) + repeat_cnt = 1; + + /* Loop repeat_cnt times */ + do + { + switch (*fmt) + { + case 'd': + ser_printf(ser, ARG_SEP_S "%ld", (*result).l); + result++; + break; + case 'c': + ser_print(ser, ARG_SEP_S); + ser_print(ser, (*result).s); + result++; + break; + case 's': + ser_printf(ser, ARG_SEP_S "%s", (*result).s); + result++; + break; + case 'n': + n = (*result++).l; + ser_printf(ser, ARG_SEP_S "%ld", n); + while (n--) { + ser_printf(ser, ARG_SEP_S "%ld", (*result).l); + result++; + } + break; + default: + break; + } + } + while (--repeat_cnt); + } + + /* Skip to next format char */ + ++fmt; + + } /* while (*fmt) */ + + + ser_print(ser, "\r\n"); + return 0; +} +#endif /* UNUSED_CODE */ + +/// Hook provided by the parser for matching of command names (TAB completion) for readline +const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) +{ + HashIterator cur; + HashIterator end = ht_iter_end(&commands); + const char *found = NULL; + + for (cur = ht_iter_begin(&commands); + !ht_iter_cmp(cur, end); + cur = ht_iter_next(cur)) + { + const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); + if (strncmp(cmdp->name, word, word_len) == 0) + { + // If there was another matching word, it means that we have a multiple + // match: then return NULL. + if (found) + return NULL; + + found = cmdp->name; + } + } + + return found; +} + +bool parser_get_cmd_id(const char* line, unsigned long* ID) +{ + const char *begin = line, *end = line; + char *end2; + + // The first word is the ID + if (!get_word(&begin, &end)) + return false; + + *ID = strtoul(begin, &end2, 10); + if (end2 != end) + return false; + + return true; +} + +const struct CmdTemplate* parser_get_cmd_template(const char *input) +{ +// const struct CmdTemplate *cmdp; +// int cmdlen; + const char *begin = input, *end = input; + + // Skip the ID, and get the command + if (!get_word(&begin, &end)) + return NULL; + if (!get_word(&begin, &end)) + return NULL; + + return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); +} + +static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp) +{ + const char *begin = input, *end = input; + + // Skip the ID, and get the command + if (!get_word(&begin, &end)) + return NULL; + if (!get_word(&begin, &end)) + return NULL; + + ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified"); + ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified"); + + return end; +} + +bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[PARSER_MAX_ARGS]) +{ + input = skip_to_params(input, cmdp); + if (!input) + return false; + + args[0].s = cmdp->name; + if (!parseArgs(cmdp->arg_fmt, input, args + 1)) + return false; + + return true; +} + +static const void* get_key_from_command(const void* cmd, uint8_t* length) +{ + const struct CmdTemplate* c = cmd; + *length = strlen(c->name); + return c->name; +} + +bool parser_process_line(const char* input) +{ + const struct CmdTemplate *cmdp; + parms args[PARSER_MAX_ARGS]; + + cmdp = parser_get_cmd_template(input); + if (!cmdp) + return false; + + if (!parser_get_cmd_arguments(input, cmdp, args)) + return false; + + if (!parser_execute_cmd(cmdp, args)) + return false; + + return true; +} + +void parser_register_cmd(const struct CmdTemplate* cmd) +{ + ht_insert(&commands, cmd); +} + +#if CONFIG_INTERNAL_COMMANDS +static ResultCode cmd_help(void) +{ +#ifdef _DEBUG + + // FIXME: There is no way at the moment to access the serial port. Dump + // this through JTAG for now + for (HashIterator iter = ht_iter_begin(&commands); + !ht_iter_cmp(iter, ht_iter_end(&commands)); + iter = ht_iter_next(iter)) + { + struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter); + kprintf("%-20s", cmd->name); + for (unsigned j = 0; cmd->arg_fmt[j]; ++j) + kprintf("%c ", 'a' + j); + kprintf("\r\n"); + } +#endif + + return RC_OK; +} + +#include "cmd_hunk.h" +DECLARE_CMD_HUNK(help, (NIL), (NIL)); + +#endif // CONFIG_INTERNAL_COMMANDS + + +void parser_init(void) +{ + // Initialize the hashtable used to store the command description + ht_init(&commands); + +#if CONFIG_INTERNAL_COMMANDS + parser_register_cmd(&CMD_HUNK_TEMPLATE(help)); +#endif +} diff --git a/bertos/mware/parser.h b/bertos/mware/parser.h new file mode 100644 index 00000000..b4e2f61d --- /dev/null +++ b/bertos/mware/parser.h @@ -0,0 +1,185 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * \author Giovanni Bajo + * + * \brief serial protocol parser and commands. + */ + + +#ifndef PARSER_H +#define PARSER_H + +#include + +/** Max number of arguments and results for each command */ +#define PARSER_MAX_ARGS 8 + +/** + * Error generated by the commands through the return code. + */ +typedef enum +{ + RC_ERROR = -1, ///< Reply with error. + RC_OK = 0, ///< No reply (ignore reply arguments). + RC_REPLY = 1, ///< Reply command arguments. + RC_SKIP = 2 ///< Skip following commands +} ResultCode; + +/** union that contains parameters passed to and from commands */ +typedef union { long l; const char *s; } parms; +/** pointer to commands */ +typedef ResultCode (*CmdFuncPtr)(parms args_results[]); + +/** + * Define a command that can be tokenized by the parser. + * + * The format strings are sequences of characters, one for each + * parameter/result. Valid characters are: + * + * d - a long integer, in decimal format + * s - a var string (in RAM) + * + * \note To create and fill an instance for this function, it is strongly + * advised to use \c DECLARE_CMD_HUNK (cmd_hunk.h). + */ +struct CmdTemplate +{ + const char *name; ///< Name of command + const char *arg_fmt; ///< Format string for the input + const char *result_fmt; ///< Format string for the output + CmdFuncPtr func; ///< Pointer to the handler function + uint16_t flags; ///< Currently unused. +}; + +/** + * Initialize the parser module + * + * \note This function must be called before any other function in this module + */ +void parser_init(void); + + +/** + * Register a new command into the parser + * + * \param cmd Command template describing the command + * + */ +void parser_register_cmd(const struct CmdTemplate* cmd); + + +/** + * Hook for readline to provide completion support for the commands + * registered in the parser. + * + * \note This is meant to be used with mware/readline.c. See the + * documentation there for a description of this hook. + */ +const char* parser_rl_match(void* dummy, const char* word, int word_len); + + +/** + * \brief Command input handler. + * + * Process the input, calling the requested command + * (if found) and calling printResult() to give out + * the result (on device specified with parameter fd). + * + * \param line Text line to be processed (ASCIIZ) + * + * \return true if everything is OK, false in case of errors + */ +bool parser_process_line(const char* line); + + +/** + * Execute a command with its arguments, and fetch its results. + * + * \param templ Template of the command to be executed + * \param args Arguments for the command, and will contain the results + * + * \return False if the command returned an error, true otherwise + */ +INLINE bool parser_execute_cmd(const struct CmdTemplate* templ, parms args[PARSER_MAX_ARGS]) +{ + return (templ->func(args) == 0); +} + + +/** + * Find the template for the command contained in the text line. + * The template can be used to tokenize the command and interpret + * it. + * + * This function can be used to find out which command is contained + * in a given text line without parsing all the parameters and + * executing it. + * + * \param line Text line to be processed (ASCIIZ) + * + * \return The command template associated with the command contained + * in the line, or NULL if the command is invalid. + */ +const struct CmdTemplate* parser_get_cmd_template(const char* line); + + +/** + * Extract the arguments for the command contained in the text line. + * + * \param line Text line to be processed (ASCIIZ) + * \param templ Command template for this line + * \param args Will contain the extracted parameters + * + * \return True if everything OK, false in case of parsing error. + */ +bool parser_get_cmd_arguments(const char* line, const struct CmdTemplate* templ, parms args[PARSER_MAX_ARGS]); + + +/** + * Extract the ID from the command text line. + * + * \param line Text line to be processed (ASCIIZ) + * \param ID Will contain the ID extracted. + * + * \return True if everything ok, false if there is no ID + * + */ +bool parser_get_cmd_id(const char* line, unsigned long* ID); + + +#endif /* PARSER_H */ + diff --git a/bertos/mware/pgm.h b/bertos/mware/pgm.h new file mode 100644 index 00000000..eebe87fe --- /dev/null +++ b/bertos/mware/pgm.h @@ -0,0 +1,211 @@ +/** + * \file + * + * + * \brief Support for reading program memory on Harvard architectures. + * + * Support is currently provided for AVR microcontrollers only. + * + * These macros allow building code twice, with and without + * pgm support (e.g.: strcpy() and strcpy_P()). + * + * Set the _PROGMEM predefine to compile in conditional + * program-memory support. + * + * + * \note This module contains code ripped out from avr-libc, + * which is distributed under a 3-clause BSD license. + */ +#ifndef MWARE_PGM_H +#define MWARE_PGM_H + +#include /* For intXX_t */ +#include +#include /* For CPU_HARVARD */ +#include /* For SIZEOF_INT */ + +#if CPU_AVR + + #ifdef __AVR_ENHANCED__ + #define pgm_read_char(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ \ + ( \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "z" (__addr16) \ + ); \ + __result; \ + }) + #define pgm_read_uint16_t(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint16_t __result; \ + __asm__ \ + ( \ + "lpm %A0, Z+" "\n\t" \ + "lpm %B0, Z" "\n\t" \ + : "=r" (__result), "=z" (__addr16) \ + : "1" (__addr16) \ + ); \ + __result; \ + }) + + + #else /* !__AVR_ENHANCED__ */ + + #define pgm_read_char(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ \ + ( \ + "lpm" "\n\t" \ + "mov %0, r0" "\n\t" \ + : "=r" (__result) \ + : "z" (__addr16) \ + : "r0" \ + ); \ + __result; \ + }) + #define pgm_read_uint16_t(addr) \ + ({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint16_t __result; \ + __asm__ \ + ( \ + "lpm" "\n\t" \ + "mov %A0, r0" "\n\t" \ + "adiw r30, 1" "\n\t" \ + "lpm" "\n\t" \ + "mov %B0, r0" "\n\t" \ + : "=r" (__result), "=z" (__addr16) \ + : "1" (__addr16) \ + : "r0" \ + ); \ + __result; \ + }) + + #endif /* !__AVR_ENHANCED__ */ + + #if SIZEOF_INT == 2 + #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr)) + #else + #error Missing support for CPU word size != 16bit + #endif + + #ifndef PROGMEM + #define PROGMEM __attribute__((__progmem__)) + #endif + #ifndef PSTR + #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; }) + #endif + #ifndef PFUNC + #define PFUNC(x) x ## _P + #endif + +#elif CPU_HARVARD + #error Missing CPU support +#endif + +#ifndef PSTR +#define PSTR /* nothing */ +#endif + +#ifndef PFUNC +#define PFUNC(x) x +#endif + +#ifndef PROGMEM +#define PROGMEM /* nothing */ +#endif + +/** + * \name Types for variables stored in program memory (harvard processors). + * \{ + */ +typedef PROGMEM char pgm_char; +typedef PROGMEM int8_t pgm_int8_t; +typedef PROGMEM uint8_t pgm_uint8_t; +typedef PROGMEM int16_t pgm_int16_t; +typedef PROGMEM uint16_t pgm_uint16_t; +typedef PROGMEM int32_t pgm_int32_t; +typedef PROGMEM uint32_t pgm_uint32_t; +/*\}*/ + +/** + * \name PGM support macros. + * + * These macros enable dual compilation of code for both program + * and data memory. + * + * Such a function may be defined like this: + * + * \code + * void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str) + * { + * char c; + * while ((c = PGM_READ_CHAR(str++)) + * lcd_putchar(c); + * } + * \endcode + * + * The above code can be compiled twice: once with the _PROGMEM preprocessor + * symbol defined, and once without. The two object modules can then be + * linked in the same application for use by client code: + * + * \code + * lcd_puts("Hello, world!"); + * lcd_puts_P(PSTR("Hello, world!")); + * + * // To be used when invoking inside other PGM_FUNC functions: + * PGM_FUNC(lcd_puts)(some_string); + * \endcode + * + * \{ + */ +#ifdef _PROGMEM + #define PGM_READ_CHAR(s) pgm_read_char(s) + #define PGM_FUNC(x) PFUNC(x) + #define PGM_STR(x) PSTR(x) + #define PGM_ATTR PROGMEM +#else + #define PGM_READ_CHAR(s) (*(s)) + #define PGM_FUNC(x) x + #define PGM_STR(x) x + #define PGM_ATTR /* nothing */ +#endif +/* \} */ + + +#endif /* MWARE_PGM_H */ diff --git a/bertos/mware/pool.h b/bertos/mware/pool.h new file mode 100644 index 00000000..a6834e6c --- /dev/null +++ b/bertos/mware/pool.h @@ -0,0 +1,90 @@ +/** + * \file + * + * + * \brief Pool macros. + * + * \version $Id$ + * \author Giovanni Bajo + */ + +/*#* + *#* $Log$ + *#* Revision 1.6 2006/07/19 12:56:28 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.5 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.4 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.3 2004/12/08 08:09:01 bernie + *#* Add missing header. + *#* + *#*/ +#ifndef MWARE_POOL_H +#define MWARE_POOL_H + +#include +#include + +#define EXTERN_POOL(name) \ + extern List name + +#define DECLARE_POOL_WITH_STORAGE(name, type, num, storage) \ + static type name##_items[num]; \ + storage name; \ + INLINE void name##_init(void (*init_func)(type*)) \ + { \ + int i; \ + LIST_INIT(&name); \ + for (i=0;i + * + * --> + * + * \brief Very simple rand() algorithm. + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/* This would really belong to libc */ +static int rand(void) +{ + static unsigned long seed; + + /* Randomize seed */ + seed = (seed ^ 0x4BAD5A39UL) + 6513973UL; + + return (int)(seed>>16); +} diff --git a/bertos/mware/readline.c b/bertos/mware/readline.c new file mode 100644 index 00000000..4c3b3a81 --- /dev/null +++ b/bertos/mware/readline.c @@ -0,0 +1,507 @@ +/** + * \file + * + * + * \brief Line editing support with history + * + * Rationale for basic implementation choices: + * + * \li The history is implemented storing consecutive ASCIIZ strings within an array of memory. When + * the history is full, the first (oldest) line is cancelled and the whole buffer is memmoved to + * overwrite it and make room. while this is is obviously not the fastest algorithm (which would + * require the use of a circular buffer) it is surely good enough for this module, which does not + * aim at fast performances (line editing does not require to be blazingly fast). + * + * \li The first character in the history is always \c \\0, and it is used as a guard. By 'wasting' it + * in this way, the code actually gets much simpler in that we remove many checks when moving + * backward (\c i>0 and similar). + * + * \li While editing, the current index points to the position of the buffer which contains the + * last character typed in (exactly like a stack pointer). This also allows to simplify calculations + * and to make easier using the last byte of history. + * + * \li While editing, the current line is always kept null-terminated. This is important because + * if the user press ENTER, we must have room to add a \c \\0 to terminate the line. If the line + * is as long as the whole history buffer, there would not be space for it. By always keeping the + * \c \\0 at the end, we properly ensure this without making index checks harder. + * + * \li When removing a line from the history (see \c pop_history()), instead of updating all the + * indices we have around, we move backward the pointer to the history we use. This way, we don't + * have to update anything. This means that we keep two pointers to the history: \c real_history + * always points to the physical start, while \c history is the adjusted pointer (that is + * dereference to read/write to it). + * + * \todo Use up/down to move through history The history line will be copied to the current line, + * making sure there is room for it. + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + + +#include "readline.h" + +#include +#include + +#include +#include + + +/// Enable compilation of the unit test code +#define DEBUG_UNIT_TEST 0 + +/// Enable dump of the history after each line +#define DEBUG_DUMP_HISTORY 0 + + +/** Special keys (escape sequences converted to a single code) */ +enum RL_KEYS { + SPECIAL_KEYS = 0x1000, + + /* + * Three byte keys: + * ################# + * UpArrow: 0x1B 0x5B 0X41 + * DownArrow: 0x1B 0x5B 0X42 + * RightArrow: 0x1B 0x5B 0x43 + * LeftArrow: 0x1b 0x5B 0x44 + * Beak(Pause): 0x1b 0x5B 0x50 + */ + KEY_UP_ARROW, + KEY_DOWN_ARROW, + KEY_LEFT_ARROW, + KEY_RIGHT_ARROW, + KEY_PAUSE, + + /* + * Four byte keys: + * ################ + * F1: 0x1b 0x5B 0x5B 0x41 + * F2: 0x1b 0x5B 0x5B 0x42 + * F3: 0x1b 0x5B 0x5B 0x43 + * F4: 0x1b 0x5B 0x5B 0x44 + * F5: 0x1b 0x5B 0x5B 0x45 + * Ins: 0x1b 0x5B 0x32 0x7E + * Home: 0x1b 0x5B 0x31 0x7E + * PgUp: 0x1b 0x5B 0x35 0x7E + * Del: 0x1b 0x5B 0x33 0x7E + * End: 0x1b 0x5B 0x34 0x7E + * PgDn: 0x1b 0x5B 0x36 0x7E + */ + KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, + KEY_INS, KEY_HOME, KEY_PGUP, KEY_DEL, KEY_END, KEY_PGDN, + + /* + * Five byte keys: + * ################ + * F6: 0x1b 0x5B 0x31 0x37 0x7E + * F7: 0x1b 0x5B 0x31 0x38 0x7E + * F8: 0x1b 0x5B 0x31 0x39 0x7E + * F9: 0x1b 0x5B 0x32 0x30 0x7E + * F10: 0x1b 0x5B 0x32 0x31 0x7E + * F11: 0x1b 0x5B 0x32 0x33 0x7E + * F12: 0x1b 0x5B 0x32 0x34 0x7E + */ + KEY_F6, KEY_F7, KEY_F8, KEY_F9, + KEY_F10, KEY_F11, KEY_F12, +}; + +/** Check if \a c is a separator between words. + * \note Parameter \a c is evaluated multiple times + */ +#define IS_WORD_SEPARATOR(c) ((c) == ' ' || (c) == '\0') + +/// Write the string \a txt to the IO output (without any kind of termination) +INLINE void rl_puts(const struct RLContext* ctx, const char* txt) +{ + if (!ctx->put) + return; + + while (*txt) + ctx->put(*txt++, ctx->put_param); +} + +/// Write character \a ch to the IO output. +INLINE void rl_putc(const struct RLContext* ctx, char ch) +{ + if (ctx->put) + ctx->put(ch, ctx->put_param); +} + +/** Read a character from the IO into \a ch. This function also takes + * care of converting the ANSI escape sequences into one of the codes + * defined in \c RL_KEYS. + */ +static bool rl_getc(const struct RLContext* ctx, int* ch) +{ + int c = ctx->get(ctx->get_param); + + if (c == EOF) + { + if (ctx->clear) + ctx->clear(ctx->clear_param); + + return false; + } + + if (c == 0x1B) + { + // Unknown ESC sequence. Ignore it and read + // return next character. + if (ctx->get(ctx->get_param) != 0x5B) + return rl_getc(ctx, ch); + + /* To be added: + * Home: 0x1b 0x5B 0x31 0x7E + * F6: 0x1b 0x5B 0x31 0x37 0x7E + * F7: 0x1b 0x5B 0x31 0x38 0x7E + * F8: 0x1b 0x5B 0x31 0x39 0x7E + * Ins: 0x1b 0x5B 0x32 0x7E + * F9: 0x1b 0x5B 0x32 0x30 0x7E + * F10: 0x1b 0x5B 0x32 0x31 0x7E + * F11: 0x1b 0x5B 0x32 0x33 0x7E + * F12: 0x1b 0x5B 0x32 0x34 0x7E + * Del: 0x1b 0x5B 0x33 0x7E + * End: 0x1b 0x5B 0x34 0x7E + * PgUp: 0x1b 0x5B 0x35 0x7E + * PgDn: 0x1b 0x5B 0x36 0x7E + */ + + c = ctx->get(ctx->get_param); + switch (c) + { + case 0x41: c = KEY_UP_ARROW; break; + case 0x42: c = KEY_DOWN_ARROW; break; + case 0x43: c = KEY_RIGHT_ARROW; break; + case 0x44: c = KEY_LEFT_ARROW; break; + case 0x50: c = KEY_PAUSE; break; + case 0x5B: + c = ctx->get(ctx->get_param); + switch (c) + { + case 0x41: c = KEY_F1; break; + case 0x42: c = KEY_F2; break; + case 0x43: c = KEY_F3; break; + case 0x44: c = KEY_F4; break; + case 0x45: c = KEY_F5; break; + default: return rl_getc(ctx, ch); + } + break; + default: return rl_getc(ctx, ch); + } + } + + *ch = c; + return true; +} + +INLINE void beep(struct RLContext* ctx) +{ + rl_putc(ctx, '\a'); +} + +static bool pop_history(struct RLContext* ctx, int total_len) +{ + // Compute the length of the first command (including terminator). + int len = strlen(ctx->real_history+1)+1; + + // (the first byte of the history should always be 0) + ASSERT(ctx->real_history[0] == '\0'); + + // If it is the only one in the history, do nothing + if (len == total_len) + return false; + + // Overwrite the first command with the second one + memmove(ctx->real_history, ctx->real_history+len, HISTORY_SIZE-len); + + // Move back the ctx->buffer pointer so that all the indices are still valid + ctx->history -= len; + + return true; +} + +/// Check if index \a i points to the begin of the history. +INLINE bool is_history_begin(struct RLContext* ctx, int i) +{ return ctx->history + i == ctx->real_history; } + +/// Check if index \a i points to the (exclusive) end of history +INLINE bool is_history_end(struct RLContext* ctx, int i) +{ return ctx->history + i == ctx->real_history + HISTORY_SIZE; } + +/// Check if index \a i points to the (exclusive) end of history, or somewhere past the end. +INLINE bool is_history_past_end(struct RLContext* ctx, int i) +{ return ctx->history + i >= ctx->real_history + HISTORY_SIZE; } + +/** Insert \a num_chars characters from \a ch into the history buffer at the + * position indicated by \a curpos. If needed, remove old history to make room. + * Returns true if everything was successful, false if there was no room to + * add the characters. + * \note \a num_chars can be 0, in which case we just make sure the line is + * correctly zero-terminated (ASCIIZ format). + */ +static bool insert_chars(struct RLContext* ctx, size_t *curpos, const char* ch, int num_chars) +{ + ASSERT(!is_history_past_end(ctx, *curpos)); + + while (is_history_past_end(ctx, *curpos+num_chars+1)) + { + if (!pop_history(ctx, *curpos)) + return false; + } + + while (num_chars--) + ctx->history[++(*curpos)] = *ch++; + + ASSERT(!is_history_past_end(ctx, *curpos + 1)); + ctx->history[*curpos+1] = '\0'; + return true; +} + +/// Insert a single character \a ch into the buffer (with the same semantic of \c insert_chars()) +static bool insert_char(struct RLContext* ctx, size_t *curpos, char ch) +{ + return insert_chars(ctx, curpos, &ch, 1); +} + +#if DEBUG_DUMP_HISTORY +/// Dump the internal history of a context (used only for debug purposes) +static void dump_history(struct RLContext* ctx) +{ + int k; + char buf[8]; + ASSERT(ctx->real_history[0] == '\0'); + rl_puts(ctx, "History dump:"); + rl_puts(ctx, "\r\n"); + for (k = 1; + ctx->real_history + k != ctx->history + ctx->history_pos + 1; + k += strlen(&ctx->real_history[k]) + 1) + { + rl_puts(ctx, &ctx->real_history[k]); + rl_puts(ctx, "\r\n"); + } + + sprintf(buf, "%d\r\n", ctx->history_pos + (ctx->history - ctx->real_history)); + rl_puts(ctx, buf); +} +#endif /* DEBUG_DUMP_HISTORY */ + +/// Complete the current word. Return false if no unambiguous completion was found +static bool complete_word(struct RLContext *ctx, size_t *curpos) +{ + const char* completed_word; + size_t wstart; + + // If the current character is a separator, + // there is nothing to complete + wstart = *curpos; + if (IS_WORD_SEPARATOR(ctx->history[wstart])) + { + beep(ctx); + return false; + } + + // Find the separator before the current word + do + --wstart; + while (!IS_WORD_SEPARATOR(ctx->history[wstart])); + + // Complete the word through the hook + completed_word = ctx->match(ctx->match_param, ctx->history + wstart + 1, *curpos - wstart); + if (!completed_word) + return false; + + // Move back the terminal cursor to the separator + while (*curpos != wstart) + { + rl_putc(ctx, '\b'); + --*curpos; + } + + // Insert the completed command + insert_chars(ctx, curpos, completed_word, strlen(completed_word)); + rl_puts(ctx, completed_word); + insert_char(ctx, curpos, ' '); + rl_putc(ctx, ' '); + + return true; +} + +void rl_refresh(struct RLContext* ctx) +{ + rl_puts(ctx, "\r\n"); + if (ctx->prompt) + rl_puts(ctx, ctx->prompt); + rl_puts(ctx, ctx->history + ctx->history_pos + 1); +} + +const char* rl_readline(struct RLContext* ctx) +{ + size_t i = ctx->history_pos; + + if (ctx->prompt) + rl_puts(ctx, ctx->prompt); + + insert_chars(ctx, &i, NULL, 0); + + while (1) + { + char ch; + int c; + + ASSERT(ctx->history - ctx->real_history + ctx->line_pos < HISTORY_SIZE); + + if (!rl_getc(ctx, &c)) + return NULL; + + // Just ignore special keys for now + if (c > SPECIAL_KEYS) + continue; + + if (c == '\t') + { + // Ask the match hook if available + if (!ctx->match) + return false; + + complete_word(ctx, &ctx->line_pos); + continue; + } + + if (c == '\r' || c == '\n') + { + if (ctx->prompt) + rl_puts(ctx, ctx->prompt); + + // Terminate line + insert_chars(ctx, &ctx->line_pos, NULL, 0); + rl_puts(ctx, "\r\n"); + break; + } + + // Backspace cancels a character, or it is ignored if at + // the start of the line + if (c == '\b') + { + if (ctx->history[ctx->line_pos] != '\0') + { + --ctx->line_pos; + rl_puts(ctx, "\b \b"); + } + continue; + } + + // Add a character to the buffer, if possible + ch = (char)c; + ASSERT2(ch == c, "a special key was not properly handled"); + if (insert_chars(ctx, &ctx->line_pos, &ch, 1)) + { + rl_putc(ctx, ch); + } + else + { + beep(ctx); + } + } + + ctx->history_pos = ctx->line_pos + 1; + while (ctx->history[ctx->line_pos] != '\0') + --ctx->line_pos; + + // Do not store empty lines in the history + if (ctx->line_pos == ctx->history_pos - 1) + ctx->history_pos -= 1; + +#if DEBUG_DUMP_HISTORY + dump_history(ctx); +#endif + + // Since the current pointer now points to the separator, we need + // to return the first character + return &ctx->history[ctx->line_pos + 1]; +} + + +#if DEBUG_UNIT_TEST + +/** Perform the unit test for the readline library */ +void rl_test(void); + +#if HISTORY_SIZE != 32 + #error This test needs HISTORY_SIZE to be set at 32 +#endif + +static struct RLContext test_ctx; + +static char* test_getc_ptr; +static int test_getc(void* data) +{ + return *test_getc_ptr++; +} + +/** Perform a readline test. The function pipes the characters from \a input_buffer + * through the I/O to \c rl_readline(). After the whole string is sent, \c do_test() + * checks if the current history within the context match \a expected_history. + */ +static bool do_test(char* input_buffer, char* expected_history) +{ + rl_init_ctx(&test_ctx); + rl_sethook_get(&test_ctx, test_getc, NULL); + + test_getc_ptr = input_buffer; + while (*test_getc_ptr) + rl_readline(&test_ctx); + + if (memcmp(test_ctx.real_history, expected_history, HISTORY_SIZE) != 0) + { + ASSERT2(0, "history compare failed"); + return false; + } + + return true; +} + +void rl_test(void) +{ + char* test1_in = "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n"; + char test1_hist[HISTORY_SIZE] = "\0l\0m\0n\0o\0p\0q\0r\0s\0t\0u\0v\0w\0x\0y\0z"; + + if (!do_test(test1_in, test1_hist)) + return; + + kprintf("rl_test successful\n"); +} + +#endif /* DEBUG_UNIT_TEST */ + diff --git a/bertos/mware/readline.h b/bertos/mware/readline.h new file mode 100644 index 00000000..9219bfd7 --- /dev/null +++ b/bertos/mware/readline.h @@ -0,0 +1,117 @@ +/** + * \file + * + * + * \brief Line editing support with history + * + * This file implements a kernel for line editing through a terminal, with history of the typed lines. + * Basic feature of this module: + * + * \li Abstracted from I/O. The user must provide hooks for getc and putc functions. + * \li Basic support for ANSI escape sequences for input of special codes. + * \li Support for command name completion (through a hook). + * + * \version $Id$ + * + * \author Giovanni Bajo + */ + + +#ifndef MWARE_READLINE_H +#define MWARE_READLINE_H + +#include + +#include + +#define HISTORY_SIZE 1024 + +typedef int (*getc_hook)(void* user_data); +typedef void (*putc_hook)(char ch, void* user_data); +typedef const char* (*match_hook)(void* user_data, const char* word, int word_len); +typedef void (*clear_hook)(void* user_data); + +struct RLContext +{ + getc_hook get; + void* get_param; + + putc_hook put; + void* put_param; + + match_hook match; + void* match_param; + + clear_hook clear; + void* clear_param; + + const char* prompt; + + char real_history[HISTORY_SIZE]; + char* history; + size_t history_pos; + size_t line_pos; +}; + +INLINE void rl_init_ctx(struct RLContext *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->history = ctx->real_history; +} + +INLINE void rl_clear_history(struct RLContext *ctx) +{ + memset(ctx->real_history, 0, sizeof(ctx->real_history)); + ctx->history_pos = 0; + ctx->history = ctx->real_history; +} + +INLINE void rl_sethook_get(struct RLContext* ctx, getc_hook get, void* get_param) +{ ctx->get = get; ctx->get_param = get_param; } + +INLINE void rl_sethook_put(struct RLContext* ctx, putc_hook put, void* put_param) +{ ctx->put = put; ctx->put_param = put_param; } + +INLINE void rl_sethook_match(struct RLContext* ctx, match_hook match, void* match_param) +{ ctx->match = match; ctx->match_param = match_param; } + +INLINE void rl_sethook_clear(struct RLContext* ctx, clear_hook clear, void* clear_param) +{ ctx->clear = clear; ctx->clear_param = clear_param; } + +INLINE void rl_setprompt(struct RLContext* ctx, const char* prompt) +{ ctx->prompt = prompt; } + +const char* rl_readline(struct RLContext* ctx); + +void rl_refresh(struct RLContext* ctx); + +#endif /* MWARE_READLINE_H */ diff --git a/bertos/mware/resource.c b/bertos/mware/resource.c new file mode 100644 index 00000000..c723bd64 --- /dev/null +++ b/bertos/mware/resource.c @@ -0,0 +1,113 @@ + +#include "resource.h" +#include + +/** + * Internal structure for building a priority queue + * of processes waiting for the resource to become free. + */ +typedef struct ResourceWaiter +{ + PriNode link; + struct Observer *owner; + +} ResourceWaiter; + + +bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest) +{ + bool success = false; + + ASSERT(releaseRequest); + + sem_obtain(&res->lock); + + if (res->owner == releaseRequest) + { + // Already ours + res->pri = pri; + success = true; + } + else if (!res->owner) + { + // Trivial acquire: nobody was owning the resource + res->pri = pri; + res->owner = releaseRequest; + success = true; + } + else + { + ResourceWaiter waiter; + + // Setup waiter structure and enqueue it to resource + waiter.owner = releaseRequest; + waiter.link.pri = pri; + LIST_ENQUEUE(&res->queue, &waiter.link); + + // Resource busy: are we eligible for preemption? + if ((res->pri < pri) && res->owner->event) + res->owner->event(EVENT_RELEASE, res); + + // Wait in the queue until the timeout occurs. + do + { + sem_release(&res->lock); + // TODO: use a semaphore here instead + ResMan_sleep(); + sem_obtain(&res->lock); + + // Check for ownership + if (res->owner == releaseRequest) + { + success = true; + break; + } + } + while (timeout--); + + // Remove pending waiter + if (!success) + REMOVE(&waiter.link.link); + } + + sem_release(&res->lock); + return success; +} + +void ResMan_Free(Resource *res) +{ + ResourceWaiter *waiter; + + sem_obtain(&res->lock); + + + ASSERT(res->owner); + //TODO: check for real owner calling free + + // Check for new owner candidates. + if ((waiter = (ResourceWaiter *)list_remHead(&res->queue))) + { + // Transfer ownership of the resource + res->owner = waiter->owner; + res->pri = waiter->link.pri; + //ResMan_wakeup(waiter); + } + else + { + // Nobody waiting, free the resource + res->owner = NULL; + res->pri = -1; + } + + sem_release(&res->lock); +} + +void ResMan_Init(Resource *res) +{ + res->owner = NULL; + res->pri = -1; + + sem_init(&res->lock); + LIST_INIT(&res->queue); +} + diff --git a/bertos/mware/resource.h b/bertos/mware/resource.h new file mode 100644 index 00000000..f30b232f --- /dev/null +++ b/bertos/mware/resource.h @@ -0,0 +1,75 @@ +#ifndef MWARE_RESOURCE_H +#define MWARE_RESOURCE_H + +#include // time_t +#include + +/* + * Abstract locking primitives used by host OS. + */ +#if CONFIG_KERNEL + + typedef Semaphore ResourceLock; + #define ResMan_sleep() timer_delay(1) + #define ResMan_time_t mtime_t + +#else /* FreeRTOS */ + + #include + #include + #include // vTaskDelay() + + #define ResMan_sleep() vTaskDelay((portTickType)1 * portTICK_RATE_MS) + #define ResMan_time_t portTickType +#endif + + +// Forward decl +struct Observer; + +/** + * Hold context information for a resource such as an audio channel. + * + * Each driver registers one or more Resource instances with the + * ResMan using ResMan_Register(). + * + * Clients can then allocate the resource through ResMan_Alloc() + * providing a desired priority and an Observer for asynchronous + * notification. + * + * Allocated resources can be stolen by other clients asking for a + * higher priority. ResMan notifies a preemption request by invoking + * the Observer of the current owner. + * + * The Observer callback must take whatever action is needed to + * release the resource as soon as possible to avoid blocking the + * new owner. + */ +typedef struct Resource +{ +//Private + /// Control access to fields below. + Semaphore lock; + + /// Pointer to current owner's observer. NULL if resource is free. + struct Observer *owner; + + /// Priority of current owner (higher values mean higher priority). + int pri; + + /// Queue of processes waiting to obtain the resource. + List queue; +} Resource; + +/// Event sent by ResMan to owners when to request resource release. +enum { EVENT_RELEASE = 1 }; + +/// Try to allocate a resource \a res with priority \a pri for at most \a timeout ticks. +bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest); + +/// Free resource \a res. Will eventually wake-up other queued owners. +void ResMan_Free(Resource *res); + +void ResMan_Init(Resource *res); + +#endif /* MWARE_RESOURCE_H */ diff --git a/bertos/mware/rle.c b/bertos/mware/rle.c new file mode 100644 index 00000000..3231833b --- /dev/null +++ b/bertos/mware/rle.c @@ -0,0 +1,167 @@ +/** + * \file + * + * + * \brief General-purpose run-length {en,de}coding algorithm (implementation) + * + * Original source code from http://www.compuphase.com/compress.htm + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/07/19 12:56:28 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.2 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.1 2004/08/04 02:35:54 bernie + *#* Import simple RLE algorithm. + *#* + *#*/ + +#include "rle.h" + + +/** + * Run-length encode \a len bytes from the \a input buffer + * to the \a output buffer. + */ +int rle(unsigned char *output, const unsigned char *input, int len) +{ + int count, index, i; + unsigned char first; + unsigned char *out; + + + out = output; + count = 0; + while (count < len) + { + index = count; + first = input[index++]; + + /* Scan for bytes identical to the first one */ + while ((index < len) && (index - count < 127) && (input[index] == first)) + index++; + + if (index - count == 1) + { + /* Failed to "replicate" the current byte. See how many to copy. + */ + while ((index < len) && (index - count < 127)) + { + /* Avoid a replicate run of only 2-bytes after a literal run. + * There is no gain in this, and there is a risc of loss if the + * run after the two identical bytes is another literal run. + * So search for 3 identical bytes. + */ + if ((input[index] == input[index - 1]) && + ((index > 1) && (input[index] == input[index - 2]))) + { + /* Reset the index so we can back up these three identical + * bytes in the next run. + */ + index -= 2; + break; + } + + index++; + } + + /* Output a run of uncompressed bytes: write length and values */ + *out++ = (unsigned char)(count - index); + for (i = count; i < index; i++) + *out++ = input[i]; + } + else + { + /* Output a compressed run: write length and value */ + *out++ = (unsigned char)(index - count); + *out++ = first; + } + + count = index; + } + + /* Output EOF marker */ + *out++ = 0; + + return (out - output); +} + + +/** + * Run-length decode from the \a input buffer to the \a output + * buffer. + * + * \note The output buffer must be large enough to accomodate + * all decoded output. + */ +int unrle(unsigned char *output, const unsigned char *input) +{ + signed char count; + unsigned char *out; + unsigned char value; + + + out = output; + + for (;;) + { + count = (signed char)*input++; + if (count > 0) + { + /* replicate run */ + value = *input++; + while (count--) + *out++ = value; + } + else if (count < 0) + { + /* literal run */ + while (count++) + *out++ = *input++; + } + else + /* EOF */ + break; + } + + return (out - output); +} diff --git a/bertos/mware/rle.h b/bertos/mware/rle.h new file mode 100644 index 00000000..61693a68 --- /dev/null +++ b/bertos/mware/rle.h @@ -0,0 +1,61 @@ +/** + * \file + * + * + * \brief General-purpose run-length {en,de}coding algorithm (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +/*#* + *#* $Log$ + *#* Revision 1.4 2006/07/19 12:56:28 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.3 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.2 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.1 2004/08/04 02:35:54 bernie + *#* Import simple RLE algorithm. + *#* + *#*/ +#ifndef RLE_H +#define RLE_H + +int rle(unsigned char *output, const unsigned char *input, int length); +int unrle(unsigned char *output, const unsigned char *input); + +#endif /* RLE_H */ diff --git a/bertos/mware/sprintf.c b/bertos/mware/sprintf.c new file mode 100644 index 00000000..0b05ce7b --- /dev/null +++ b/bertos/mware/sprintf.c @@ -0,0 +1,154 @@ +/** + * \file + * + * + * \brief sprintf() implementation based on _formatted_write() + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include +#include +#include + +#include + + +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_ARG(char, c), UNUSED_ARG(void *, ptr)) +{ + /* nop */ +} + + +int PGM_FUNC(vsprintf)(char *str, const char * PGM_ATTR fmt, va_list ap) +{ + int result; + + if (str) + { + result = PGM_FUNC(_formatted_write)(fmt, __str_put_char, &str, ap); + + /* Terminate string */ + *str = '\0'; + } + else + result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap); + + + return result; +} + + +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); + + return result; +} + +/** + * State information for __sn_put_char() + */ +struct __sn_state +{ + char *str; + size_t len; +}; + +/** + * formatted_write() callback used [v]snprintf(). + */ +static void __sn_put_char(char c, void *ptr) +{ + struct __sn_state *state = (struct __sn_state *)ptr; + + if (state->len) + { + --state->len; + *state->str++ = c; + } +} + + +int PGM_FUNC(vsnprintf)(char *str, size_t size, const char * PGM_ATTR fmt, va_list ap) +{ + int result = 0; + + /* Make room for traling '\0'. */ + if (size--) + { + if (str) + { + struct __sn_state state; + state.str = str; + state.len = size; + + result = PGM_FUNC(_formatted_write)(fmt, __sn_put_char, &state, ap); + + /* Terminate string. */ + *state.str = '\0'; + } + else + result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap); + } + + return result; +} + + +int PGM_FUNC(snprintf)(char *str, size_t size, const char * fmt, ...) +{ + int result; + va_list ap; + + va_start(ap, fmt); + result = PGM_FUNC(vsnprintf)(str, size, fmt, ap); + va_end(ap); + + return result; +} diff --git a/bertos/mware/sprintf_test.c b/bertos/mware/sprintf_test.c new file mode 100644 index 00000000..1bcedfd3 --- /dev/null +++ b/bertos/mware/sprintf_test.c @@ -0,0 +1,96 @@ +/** + * \file + * + * + * \brief sprintf() implementation based on _formatted_write() + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "sprintf.c" +#include "formatwr.c" +#include "hex.c" +#include +#include +#include + +#include /* assert() */ +#include /* strcmp() */ + + +int main(UNUSED_ARG(int, argc), UNUSED_ARG(char **,argv)) +{ + char buf[256]; + static const char test_string[] = "Hello, world!\n"; + static const pgm_char test_string_pgm[] = "Hello, world!\n"; + + snprintf(buf, sizeof buf, "%s", test_string); + assert(strcmp(buf, test_string) == 0); + + snprintf(buf, sizeof buf, "%S", test_string_pgm); + assert(strcmp(buf, test_string_pgm) == 0); + +#define TEST(FMT, VALUE, EXPECT) do { \ + snprintf(buf, sizeof buf, FMT, VALUE); \ + assert(strcmp(buf, EXPECT) == 0); \ + } while (0) + + TEST("%d", 12345, "12345"); + TEST("%ld", 123456789L, "123456789"); + TEST("%ld", -12345678L, "-12345678"); + TEST("%lu", 4294967295UL, "4294967295"); + TEST("%hd", -12345, "-12345"); + TEST("%hu", 65535U, "65535"); + + TEST("%8d", 123, " 123"); + TEST("%8d", -123, " -123"); + TEST("%-8d", -123, "-123 "); + TEST("%08d", -123, "-0000123"); + + TEST("%8.2f", -123.456, " -123.46"); + TEST("%-8.2f", -123.456, "-123.46 "); + TEST("%8.0f", -123.456, " -123"); + +#undef TEST + + /* + * Stress tests. + */ + snprintf(buf, sizeof buf, "%s", NULL); + assert(strcmp(buf, "") == 0); + snprintf(buf, sizeof buf, "%k"); + assert(strcmp(buf, "???") == 0); + sprintf(NULL, test_string); /* must not crash */ + + return 0; +} + diff --git a/bertos/mware/strtol10.c b/bertos/mware/strtol10.c new file mode 100644 index 00000000..6521a6a5 --- /dev/null +++ b/bertos/mware/strtol10.c @@ -0,0 +1,100 @@ +/** + * \file + * + * + * \brief Poor man's hex arrays (implementation). + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "strtol10.h" + +/** + * Convert a formatted base-10 ASCII number to unsigned long binary representation. + * + * Unlike the standard strtoul(), this function has an interface + * that makes it better suited for protocol parsers. It's also + * much simpler and smaller than a full featured strtoul(). + * + * \param first Pointer to first byte of input range (STL-style). + * \param last Pointer to end of input range (STL-style). + * Pass NULL to parse up to the first \\0. + * \param val Pointer to converted value. + * + * \return true for success, false for failure. + * + * \see strtol10() + */ +bool strtoul10(const char *first, const char *last, unsigned long *val) +{ + // Check for no input + if (*first == '\0') + return false; + + *val = 0; + for(/*nop*/; first != last && *first != '\0'; ++first) + { + if ((*first < '0') || (*first > '9')) + return false; + + *val = (*val * 10L) + (*first - '0'); + } + + return true; +} + + +/** + * Convert a formatted base-10 ASCII number to signed long binary representation. + * + * \see strtoul10() + */ +bool strtol10(const char *first, const char *last, long *val) +{ + bool negative = false; + + if (*first == '+') + ++first; /* skip unary plus sign */ + else if (*first == '-') + { + negative = true; + ++first; + } + + bool result = strtoul10(first, last, (unsigned long *)val); + + if (negative) + *val = - *val; + + return result; +} + diff --git a/bertos/mware/strtol10.h b/bertos/mware/strtol10.h new file mode 100644 index 00000000..4dfe7a47 --- /dev/null +++ b/bertos/mware/strtol10.h @@ -0,0 +1,66 @@ +/** + * \file + * + * + * \brief Poor man's hex arrays (implementation). + * + * \version $Id$ + * \author Bernardo Innocenti + */ + + +#ifndef MWARE_STRTOL10_H +#define MWARE_STRTOL10_H + +#include /* bool */ + +bool strtoul10(const char *first, const char *last, unsigned long *val); +bool strtol10(const char *first, const char *last, long *val); + +/** + * Replacement for standard library function atol(). + */ +INLINE long atol(const char *str) +{ + long val; + strtol10(str, NULL, &val); + return val; +} + +/** + * Replacement for standard library function atoi(). + */ +INLINE int atoi(const char *str) +{ + return (int)atol(str); +} + +#endif /* MWARE_STRTOL10_H */ diff --git a/bertos/mware/xmodem.c b/bertos/mware/xmodem.c new file mode 100644 index 00000000..030783d3 --- /dev/null +++ b/bertos/mware/xmodem.c @@ -0,0 +1,433 @@ +/** + * \file + * + * \brief X-Modem serial transmission protocol (implementation) + * + * Supports the CRC-16 and 1K-blocks variants of the standard. + * \see ymodem.txt for the protocol description. + * + * \todo Break xmodem_send() and xmodem_recv() in smaller functions. + * + * \todo Maybe convert drv/ser.c to the KFile interface for symmetry and + * flexibility. + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + + +#include "xmodem.h" + +#include +#include /* for memset() */ +#include +#include +#include + + + + +/** + * \name Protocol control codes + * \{ + */ +#define XM_SOH 0x01 /**< Start Of Header (128-byte block) */ +#define XM_STX 0x02 /**< Start Of Header (1024-byte block) */ +#define XM_EOT 0x04 /**< End Of Transmission */ +#define XM_ACK 0x06 /**< Acknowledge block */ +#define XM_NAK 0x15 /**< Negative Acknowledge */ +#define XM_C 0x43 /**< Request CRC-16 transmission */ +#define XM_CAN 0x18 /**< CANcel transmission */ +/*\}*/ + +#define XM_MAXRETRIES 15 /**< Max retries before giving up */ +#define XM_MAXCRCRETRIES 7 /**< Max retries before switching to BCC */ + +#if CONFIG_XMODEM_1KCRC == 1 + #define XM_BUFSIZE 1024 /**< 1024 bytes of block buffer */ +#else + #define XM_BUFSIZE 128 /**< 128 bytes of block buffer */ +#endif + + +#if CONFIG_XMODEM_RECV +/** + * \brief Receive a file using the XModem protocol. + * + * \param port Serial port to use for transfer + * \param fd Destination file + * + * \note This function allocates a large amount of stack (\see XM_BUFSIZE). + */ +bool xmodem_recv(struct Serial *port, KFile *fd) +{ + char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ + int c, i, blocksize; + int blocknr = 0, last_block_done = 0, retries = 0; + char *buf; + uint8_t checksum; + uint16_t crc; + bool purge = false; + bool usecrc = true; + + + XMODEM_PROGRESS("Starting Transfer...\n"); + purge = true; + ser_setstatus(port, 0); + + /* Send initial NAK to start transmission */ + for(;;) + { + if (XMODEM_CHECK_ABORT) + { + ser_putchar(XM_CAN, port); + ser_putchar(XM_CAN, port); + XMODEM_PROGRESS("Transfer aborted\n"); + return false; + } + + /* + * Discard incoming input until a timeout occurs, then send + * a NAK to the transmitter. + */ + if (purge) + { + purge = false; + + if (ser_getstatus(port)) + XMODEM_PROGRESS("Retries %d\n", retries); + + ser_resync(port, 200); + retries++; + + if (retries >= XM_MAXRETRIES) + { + ser_putchar(XM_CAN, port); + ser_putchar(XM_CAN, port); + XMODEM_PROGRESS("Transfer aborted\n"); + return false; + } + + /* Transmission start? */ + if (blocknr == 0) + { + if (retries < XM_MAXCRCRETRIES) + { + XMODEM_PROGRESS("Request Tx (CRC)\n"); + ser_putchar(XM_C, port); + } + else + { + /* Give up with CRC and fall back to checksum */ + usecrc = false; + XMODEM_PROGRESS("Request Tx (BCC)\n"); + ser_putchar(XM_NAK, port); + } + } + else + ser_putchar(XM_NAK, port); + } + + switch (ser_getchar(port)) + { + #if XM_BUFSIZE >= 1024 + case XM_STX: /* Start of header (1024-byte block) */ + blocksize = 1024; + goto getblock; + #endif + + case XM_SOH: /* Start of header (128-byte block) */ + blocksize = 128; + /* Needed to avoid warning if XM_BUFSIZE < 1024 */ + goto getblock; + getblock: + /* Get block number */ + c = ser_getchar(port); + + /* Check complemented block number */ + if ((~c & 0xff) != ser_getchar(port)) + { + XMODEM_PROGRESS("Bad blk (%d)\n", c); + purge = true; + break; + } + + /* Determine which block is being sent */ + if (c == (blocknr & 0xff)) + /* Last block repeated */ + XMODEM_PROGRESS("Repeat blk %d\n", blocknr); + else if (c == ((blocknr + 1) & 0xff)) + /* Next block */ + XMODEM_PROGRESS("Recv blk %d\n", ++blocknr); + else + { + /* Sync lost */ + XMODEM_PROGRESS("Sync lost (%d/%d)\n", c, blocknr); + purge = true; + break; + } + + buf = block_buffer; /* Reset pointer to start of buffer */ + checksum = 0; + crc = 0; + for (i = 0; i < blocksize; i++) + { + if ((c = ser_getchar(port)) == EOF) + { + purge = true; + break; + } + + /* Store in buffer */ + *buf++ = (char)c; + + /* Calculate block checksum or CRC */ + if (usecrc) + crc = UPDCRC16(c, crc); + else + checksum += (char)c; + } + + if (purge) + break; + + /* Get the checksum byte or the CRC-16 MSB */ + if ((c = ser_getchar(port)) == EOF) + { + purge = true; + break; + } + + if (usecrc) + { + crc = UPDCRC16(c, crc); + + /* Get CRC-16 LSB */ + if ((c = ser_getchar(port)) == EOF) + { + purge = true; + break; + } + + crc = UPDCRC16(c, crc); + + if (crc) + { + XMODEM_PROGRESS("Bad CRC: %04x\n", crc); + purge = true; + break; + } + } + /* Compare the checksum */ + else if (c != checksum) + { + XMODEM_PROGRESS("Bad sum: %04x/%04x\n", checksum, c); + purge = true; + break; + } + + /* + * Avoid flushing the same block twice. + * This could happen when the sender does not receive our + * acknowledge and resends the same block. + */ + if (last_block_done < blocknr) + { + /* Call user function to flush the buffer */ + if (fd->write(fd, block_buffer, blocksize)) + { + /* Acknowledge block and clear error counter */ + ser_putchar(XM_ACK, port); + retries = 0; + last_block_done = blocknr; + } + else + { + /* User callback failed: abort transfer immediately */ + retries = XM_MAXRETRIES; + purge = true; + } + } + break; + + case XM_EOT: /* End of transmission */ + ser_putchar(XM_ACK, port); + XMODEM_PROGRESS("Transfer completed\n"); + return true; + + case EOF: /* Timeout or serial error */ + purge = true; + break; + + default: + XMODEM_PROGRESS("Skipping garbage\n"); + purge = true; + break; + } + } /* End forever */ +} +#endif + + +#if CONFIG_XMODEM_SEND +/** + * \brief Transmit some data using the XModem protocol. + * + * \param port Serial port to use for transfer + * \param fd Source file + * + * \note This function allocates a large amount of stack for + * the XModem transfer buffer (\see XM_BUFSIZE). + */ +bool xmodem_send(struct Serial *port, KFile *fd) +{ + char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ + size_t size = -1; + int blocknr = 1, retries = 0, c, i; + bool proceed, usecrc = false; + uint16_t crc; + uint8_t sum; + + /* + * Reading a block can be very slow, so we read the first block early + * to avoid receiving double XM_C char. + * This could happen if we check for XM_C and then read the block, giving + * the receiving device time to send another XM_C char misinterpretating + * the blocks sent. + */ + size = fd->read(fd, block_buffer, XM_BUFSIZE); + + ser_setstatus(port, 0); + ser_purge(port); + XMODEM_PROGRESS("Wait remote host\n"); + + for(;;) + { + proceed = false; + do + { + if (XMODEM_CHECK_ABORT) + return false; + + switch (c = ser_getchar(port)) + { + case XM_NAK: + XMODEM_PROGRESS("Resend blk %d\n", blocknr); + proceed = true; + break; + + case XM_C: + if (c == XM_C) + { + XMODEM_PROGRESS("Tx start (CRC)\n"); + usecrc = true; + } + else + XMODEM_PROGRESS("Tx start (BCC)\n"); + + proceed = true; + break; + + case XM_ACK: + /* End of transfer? */ + if (!size) + return true; + + /* Call user function to read in one block */ + size = fd->read(fd, block_buffer, XM_BUFSIZE); + XMODEM_PROGRESS("Send blk %d\n", blocknr); + blocknr++; + retries = 0; + proceed = true; + break; + + case EOF: + ser_setstatus(port, 0); + retries++; + XMODEM_PROGRESS("Retries %d\n", retries); + if (retries <= XM_MAXRETRIES) + break; + /* falling through! */ + + case XM_CAN: + XMODEM_PROGRESS("Transfer aborted\n"); + return false; + + default: + XMODEM_PROGRESS("Skipping garbage\n"); + break; + } + } + while (!proceed); + + if (!size) + { + ser_putchar(XM_EOT, port); + continue; + } + + /* Pad block with 0xFF if it's partially full */ + memset(block_buffer + size, 0xFF, XM_BUFSIZE - size); + + /* Send block header (STX, blocknr, ~blocknr) */ + #if XM_BUFSIZE == 128 + ser_putchar(XM_SOH, port); + #else + ser_putchar(XM_STX, port); + #endif + ser_putchar(blocknr & 0xFF, port); + ser_putchar(~blocknr & 0xFF, port); + + /* Send block and compute its CRC/checksum */ + sum = 0; + crc = 0; + for (i = 0; i < XM_BUFSIZE; i++) + { + ser_putchar(block_buffer[i], port); + crc = UPDCRC16(block_buffer[i], crc); + sum += block_buffer[i]; + } + + /* Send CRC/Checksum */ + if (usecrc) + { + crc = UPDCRC16(0, crc); + crc = UPDCRC16(0, crc); + ser_putchar(crc >> 8, port); + ser_putchar(crc & 0xFF, port); + } + else + ser_putchar(sum, port); + } +} +#endif diff --git a/bertos/mware/xmodem.h b/bertos/mware/xmodem.h new file mode 100644 index 00000000..564a6ff7 --- /dev/null +++ b/bertos/mware/xmodem.h @@ -0,0 +1,73 @@ +/** + * \file + * + * \brief X-Modem serial transmission protocol (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + * \author Francesco Sacchi + */ + + +#ifndef MWARE_XMODEM_H +#define MWARE_XMODEM_H +#include +#include + +/** + * Called to know if we want to abort data tranfer. + * Redefine to whatever you need. + * \{ + */ +#ifndef XMODEM_CHECK_ABORT +#define XMODEM_CHECK_ABORT (false) +#endif +/*\}*/ + + +/** + * Called to printf progress messages. + * Default to kprintf debug, redefine to whatever you need. + * \{ + */ +#ifndef XMODEM_PROGRESS +#define XMODEM_PROGRESS(msg, ...) kprintf(msg, ## __VA_ARGS__) +#endif + + +/* fwd decl */ +struct Serial; + +bool xmodem_recv(struct Serial *port, KFile *fd); +bool xmodem_send(struct Serial *port, KFile *fd); + +#endif /* MWARE_XMODEM_H */ diff --git a/bertos/net/keytag.c b/bertos/net/keytag.c new file mode 100644 index 00000000..861169b4 --- /dev/null +++ b/bertos/net/keytag.c @@ -0,0 +1,112 @@ +/** + * \file + * + * + * \author Andrea Grandi + * + * \brief Tag protocol (protocol). + * + * TAG protocol is decribed in this way: + *
+ * ---------------------------------------------------
+ * |STX (0x02)|data...(10 HEX chars)|CR|LF|ETX (0x03)|
+ * ---------------------------------------------------
+ * 
+ */ + +#include "keytag.h" + +#include + +#include +#include + +#include +#include + +static void keytag_clearPkt(struct TagPacket *pkt) +{ + pkt->sync = false; + pkt->len = 0; +} + + void keytag_init(struct TagPacket *pkt) + { + keytag_clearPkt(pkt); + } + + void keytag_poll(struct TagPacket *pkt) +{ + int c; + + /* Get all chars from buffer */ + while ((c = kfile_getc(&pkt->tag_ser->fd)) != EOF) + { + /* Search for STX char in received chars */ + if (c == TAG_STX) + { + /* When STX is found a new packet begins */ + if (pkt->sync) + kprintf("TAG double sync!\n"); + keytag_clearPkt(pkt); + pkt->sync = true; + } + else if (pkt->sync) + { + /* Check for end of packet */ + if (c == TAG_ETX) + { + pkt->buf[TAG_MAX_PRINT_CHARS] = '\x0'; + /* Write read TAG on communication serial */ + kfile_printf(&pkt->comm_ser->fd, "tag %s", pkt->buf); + pkt->sync = false; + } + else + { + /* Check for buffer overflow */ + if (pkt->len >= TAG_MAX_LEN) + { + kprintf("TAG buffer overflow\n"); + pkt->sync = false; + } + else + { + /* Add every char after STX to tag reading buffer */ + if (pkt->sync) + { + pkt->buf[pkt->len] = c; + pkt->len++; + } + } + } + } + } +} diff --git a/bertos/net/keytag.h b/bertos/net/keytag.h new file mode 100644 index 00000000..541005ea --- /dev/null +++ b/bertos/net/keytag.h @@ -0,0 +1,82 @@ +/** + * \file + * + * + * \author Andrea Grandi + * + * \brief Tag protocol. (interface). + */ + +#ifndef NET_KEYTAG_H +#define NET_KEYTAG_H + +#include +#include + +/** + * Starting communication char (STX). + */ +#define TAG_STX 0x02 + +/** + * Ending communication char (ETX). + */ +#define TAG_ETX 0x03 + +/** + * Max buffer lenght + */ +#define TAG_MAX_LEN 14 + +#define TAG_SER_PORT 0 +#define TAG_SER_BAUDRATE 9600 + +/** + * Max number of chars to print in the communication serial + */ +#define TAG_MAX_PRINT_CHARS 12 + +/** + * Structure of a Tag packet + */ +typedef struct TagPacket +{ + KFileSerial *tag_ser; // Tag serial + KFileSerial *comm_ser; // Communication serial + bool sync; // Status flag: true if we find an STX + uint16_t len; // Packet lenght + uint8_t buf[TAG_MAX_LEN]; // Reception buffer +} TagPacket; + +void keytag_init(struct TagPacket *pkt); +void keytag_poll(struct TagPacket *pkt); + +#endif /* NET_TAG_H */ diff --git a/bertos/net/pocketbus.c b/bertos/net/pocketbus.c new file mode 100644 index 00000000..e793f95d --- /dev/null +++ b/bertos/net/pocketbus.c @@ -0,0 +1,260 @@ +/** + * \file + * + * + * \version $Id: pocketbus.c 20131 2007-12-13 17:39:55Z batt $ + * + * \author Francesco Sacchi + * + * \brief pocketBus protocol implementation. + * + * pocketBus protocol is a simple strictly master-slave protocol, usable + * in embedded systems. + * pocketBus frame is as follows: + *
+ * +----------------------------------------+
+ * | STX | VER | ADDR | PAYLOAD | CKS | ETX |
+ * +----------------------------------------+
+ * |     |     |      |         |     |     |
+ * + 1B  + 1B  +  2B  + N Byte  + 2B  + 1B  +
+ * 
+ * + * - STX, 1 byte (0x02), packet start + * - VER, 1 byte, packet version + * - ADDR, 2 byte, slave address + * - PAYLOAD, N byte, data field + * - CKS, 2 byte, checksum + * - ETX, 1 byte, (0x03) packet end + * + * Protocol parsing start on STX reception. When the receiving routine + * finds an STX char, it starts to read characters from the bus + * until an ETX is received. Once a packet is received, + * the parser checks packet correctness and checksum. If all is OK + * the payload is returned. + * + * STX (0x02), ETX(0x03) and ESC(0x1B) are special characters and cannot be + * transmitted inside payload without escaping them. + * To escape a character you must precede it by the ESC char. + * E.G. STX -> ESC + STX + * ETX -> ESC + ETX + * ESC -> ESC + ESC + * + * In the ADDR field is always specified the slave address. + * In the case of master trasmitting, ADDR contains the slave destination + * address. + * In case of slave replying, ADDR contains the slave address itself. + * Thus, the master device does not have an address. Packet must be routed to + * master by hardware bus design. + * + * The checksum algorithm used is rotating hash algortihm, quite simple but more + * reliable than simple checksum. + * The checksum in computed on all fields excluding STX, ETX and CHK fields itself. + * Checksum is computed on the packet *before* escaping. + * Escape sequence counts for 1 character only (the escaped one). + */ + +#include "pocketbus.h" + +#include +#include + +#include + +#include + +#include + +/** + * Send a character over pocketBus channel stream, handling escape mode. + */ +void pocketbus_putchar(struct PocketBusCtx *ctx, uint8_t c) +{ + /* Update checksum */ + rotating_update1(c, &ctx->out_cks); + + /* Escape characters with special meaning */ + if (c == POCKETBUS_ESC || c == POCKETBUS_STX || c == POCKETBUS_ETX) + kfile_putc(POCKETBUS_ESC, ctx->fd); + + kfile_putc(c, ctx->fd); +} + +/** + * Send pocketBus packet header. + */ +void pocketbus_begin(struct PocketBusCtx *ctx, pocketbus_addr_t addr) +{ + PocketBusHdr hdr; + + hdr.ver = POCKETBUS_VER; + hdr.addr = cpu_to_be16(addr); + rotating_init(&ctx->out_cks); + + /* Send STX */ + kfile_putc(POCKETBUS_STX, ctx->fd); + + /* Send header */ + pocketbus_write(ctx, &hdr, sizeof(hdr)); +} + +/** + * Send buffer \a _data over bus, handling escape. + */ +void pocketbus_write(struct PocketBusCtx *ctx, const void *_data, size_t len) +{ + const uint8_t *data = (const uint8_t *)_data; + + while (len--) + pocketbus_putchar(ctx, *data++); +} + +/** + * Send pocketBus packet tail. + */ +void pocketbus_end(struct PocketBusCtx *ctx) +{ + /* Send checksum */ + rotating_t cks = cpu_to_be16(ctx->out_cks); + pocketbus_write(ctx, &cks, sizeof(cks)); + + /* Send ETX */ + kfile_putc(POCKETBUS_ETX, ctx->fd); +} + +/** + * Send buffer of \a data to address \a addr with a pocketBus packet over channel stream. + */ +void pocketbus_send(struct PocketBusCtx *ctx, pocketbus_addr_t addr, const void *data, size_t len) +{ + pocketbus_begin(ctx, addr); + + /* Send data */ + pocketbus_write(ctx, data, len); + + pocketbus_end(ctx); +} + + +/** + * Try to read a packet from the pocketBus. + * \return true if a packet is received, false otherwise. + */ +bool pocketbus_recv(struct PocketBusCtx *ctx, struct PocketMsg *msg) +{ + int c; + + /* Process incoming characters until buffer is not empty */ + while ((c = kfile_getc(ctx->fd)) != EOF) + { + /* Look for STX char */ + if (c == POCKETBUS_STX && !ctx->escape) + { + /* When an STX is found, inconditionally start a new packet */ + if (ctx->sync) + kprintf("pocketBus double sync!\n"); + + ctx->sync = true; + ctx->len = 0; + rotating_init(&ctx->in_cks); + continue; + } + + if (ctx->sync) + { + /* Handle escape mode */ + if (c == POCKETBUS_ESC && !ctx->escape) + { + ctx->escape = true; + continue; + } + + /* Handle message end */ + if (c == POCKETBUS_ETX && !ctx->escape) + { + ctx->sync = false; + + /* Check minimum size */ + if (ctx->len < sizeof(PocketBusHdr) + sizeof(rotating_t)) + { + kprintf("pocketBus short pkt!\n"); + continue; + } + + /* Remove checksum bytes from packet len */ + ctx->len -= sizeof(rotating_t); + + /* Compute checksum */ + rotating_update(ctx->buf, ctx->len, &ctx->in_cks); + rotating_t recv_cks = be16_to_cpu(*((rotating_t *)(ctx->buf + ctx->len))); + + /* Checksum check */ + if (recv_cks == ctx->in_cks) + { + PocketBusHdr *hdr = (PocketBusHdr *)(ctx->buf); + /* Check packet version */ + if (hdr->ver == POCKETBUS_VER) + { + /* Packet received, set msg fields */ + msg->payload = ctx->buf + sizeof(PocketBusHdr); + msg->addr = be16_to_cpu(hdr->addr); + msg->len = ctx->len - sizeof(PocketBusHdr); + msg->ctx = ctx; + return true; + } + else + { + kprintf("pocketBus version mismatch, here[%d], there[%d]\n", POCKETBUS_VER, hdr->ver); + continue; + } + } + else + { + kprintf("pocketBus cks error, here[%04X], there[%04X]\n", ctx->in_cks, recv_cks); + continue; + } + + } + + ctx->escape = false; + + /* Check buffer overflow: simply ignore + received data and go to unsynced state. */ + if (ctx->len >= CONFIG_POCKETBUS_BUFLEN) + { + kprintf("pocketBus buffer overflow\n"); + ctx->sync = false; + continue; + } + + /* Put received data in the buffer */ + ctx->buf[ctx->len] = c; + ctx->len++; + } + } + + /* + * Check stream status. + */ + if (kfile_error(ctx->fd)) + { + TRACEMSG("fd status[%04X]", kfile_error(ctx->fd)); + kfile_clearerr(ctx->fd); + } + + return false; +} + + +/** + * Initialize pocketBus protocol handler. + */ +void pocketbus_init(struct PocketBusCtx *ctx, struct KFile *fd) +{ + ASSERT(ctx); + ASSERT(fd); + + memset(ctx, 0, sizeof(*ctx)); + ctx->fd = fd; +} diff --git a/bertos/net/pocketbus.h b/bertos/net/pocketbus.h new file mode 100644 index 00000000..397cd6eb --- /dev/null +++ b/bertos/net/pocketbus.h @@ -0,0 +1,99 @@ +/** + * \file + * + * + * \version $Id: pocketbus.h 20131 2007-12-13 17:39:55Z batt $ + * + * \author Francesco Sacchi + * + * \brief pocketBus protocol interface. + */ + +#ifndef NET_POCKETBUS_H +#define NET_POCKETBUS_H + +#include +#include +#include +#include +#include "appconfig.h" //for CONFIG_POCKETBUS_BUFLEN + +/** + * pocketBus special characters definitions. + * \{ + */ +#define POCKETBUS_STX 0x02 //ASCII STX +#define POCKETBUS_ETX 0x03 //ASCII ETX +#define POCKETBUS_ESC 0x1B //ASCII ESC +#define POCKETBUS_ACK 0x06 //ASCII ACK +#define POCKETBUS_NAK 0x15 //ASCII NAK +/*\}*/ + +#define POCKETBUS_BROADCAST_ADDR 0xFFFF ///< pocketBus broadcast address + +/** + * Type for pocketBus length. + */ +typedef uint16_t pocketbus_len_t; + +/** + * Type for pocketBus addresses. + */ +typedef uint16_t pocketbus_addr_t; + +/** + * Header of pocketBus messages. + */ +typedef struct PocketBusHdr +{ + #define POCKETBUS_VER 1 + uint8_t ver; ///< packet version + pocketbus_addr_t addr; ///< slave address +} PocketBusHdr; + +/** + * pocketBus context structure. + */ +typedef struct PocketBusCtx +{ + struct KFile *fd; ///< File descriptor + bool sync; ///< Status flag: true if we have received an STX, false otherwise + bool escape; ///< Status flag: true if we are in escape mode, false otherwise + rotating_t in_cks; ///< Checksum computation for received data. + rotating_t out_cks; ///< Checksum computation for transmitted data. + pocketbus_len_t len; ///< Received length + uint8_t buf[CONFIG_POCKETBUS_BUFLEN]; ///< receiving Buffer +} PocketBusCtx; + +/** + * Structure holding pocketBus message parameters. + */ +typedef struct PocketMsg +{ + struct PocketBusCtx *ctx; ///< pocketBus message context + pocketbus_addr_t addr; ///< address for received packet + pocketbus_len_t len; ///< payload length + const uint8_t *payload; ///< payload data +} PocketMsg; + +/** + * This ensure that endianess convertion functions work on + * the right data size. + * \{ + */ +STATIC_ASSERT(sizeof(pocketbus_addr_t) == sizeof(uint16_t)); +STATIC_ASSERT(sizeof(rotating_t) == sizeof(uint16_t)); +/*\}*/ + +void pocketbus_putchar(struct PocketBusCtx *ctx, uint8_t c); +void pocketbus_begin(struct PocketBusCtx *ctx, pocketbus_addr_t addr); +void pocketbus_write(struct PocketBusCtx *ctx, const void *_data, size_t len); +void pocketbus_end(struct PocketBusCtx *ctx); + +void pocketbus_send(struct PocketBusCtx *ctx, pocketbus_addr_t addr, const void *data, size_t len); +bool pocketbus_recv(struct PocketBusCtx *ctx, struct PocketMsg *msg); +void pocketbus_init(struct PocketBusCtx *ctx, struct KFile *fd); + +#endif /* NET_POCKETBUS_H */ diff --git a/bertos/net/pocketcmd.c b/bertos/net/pocketcmd.c new file mode 100644 index 00000000..d59cbf41 --- /dev/null +++ b/bertos/net/pocketcmd.c @@ -0,0 +1,167 @@ +/** + * \file + * + * + * \version $Id: pocketcmd.c 16587 2007-10-02 14:31:02Z batt $ + * + * \author Francesco Sacchi + * + * \brief pocketBus protocol Command layer implementation. + * + * This module implements command layer over pocketBus + * protocol. + * Payload packets received by pocketBus are first checked for + * address matching. + * If a packet is addressed to us we look for a suitable + * callback function to call. + * + * The received payload format is as follows: + *
+ * +----------------------------------------+
+ * |  CMD |            DATA                 |
+ * +----------------------------------------+
+ * |      |                                 |
+ * +  2B  +           0..N Byte             +
+ * 
+ * + * The CMD ID used is the same supplied by the master when + * the command was sent. + */ + +#include "pocketcmd.h" +#include "pocketbus.h" + +#include +#include +#include + +#include + +#include + +#include + +/** + * pocketBus Command poll function. + * Call it to read and process pocketBus commands. + */ +void pocketcmd_poll(struct PocketCmdCtx *ctx) +{ + PocketMsg msg; + + /* Try to read a packet from pocketBus */ + while (pocketbus_recv(ctx->bus_ctx, &msg)) + { + /* Check address */ + if (msg.addr == ctx->addr || + msg.addr == POCKETBUS_BROADCAST_ADDR) + { + const PocketCmdHdr *hdr = (const PocketCmdHdr *)msg.payload; + pocketcmd_t cmd = be16_to_cpu(hdr->cmd); + + /* We're no longer waiting for a reply (in case we were) */ + if (cmd == ctx->waiting) + ctx->waiting = PKTCMD_NULL; + + /* Check for command callback */ + pocketcmd_hook_t callback = ctx->search(cmd); + + /* Call it if exists */ + if (callback) + { + PocketCmdMsg cmd_msg; + + cmd_msg.cmd_ctx = ctx; + cmd_msg.cmd = cmd; + cmd_msg.len = msg.len - sizeof(PocketCmdHdr); + cmd_msg.buf = msg.payload + sizeof(PocketCmdHdr); + + callback(&cmd_msg); + } + } + } +} + +/** + * Send command \a cmd to/from slave adding \a len arguments in \a buf. + * Address used is contained in \a ctx->addr . + * If we are master and the message has a reply, you must set \a wait_reply to true. + * \return true if all is ok, false if we are already waiting a replay from another slave. + */ +bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool wait_reply) +{ + /* Check if we are waiting a reply from someone */ + if (ctx->waiting != PKTCMD_NULL) + { + /* Check is reply timeout is elapsed */ + if (timer_clock() - ctx->reply_timer < ms_to_ticks(PKTCMD_REPLY_TIMEOUT)) + { + TRACEMSG("Pkt discard! waiting cmd[%04X]\n", ctx->waiting); + return false; + } + else + { + TRACEMSG("Timeout waiting cmd[%04X]\n", ctx->waiting); + ctx->waiting = PKTCMD_NULL; + } + } + + /* Endianess! */ + cmd = cpu_to_be16(cmd); + + /* Send packet */ + pocketbus_begin(ctx->bus_ctx, ctx->addr); + pocketbus_write(ctx->bus_ctx, &cmd, sizeof(cmd)); + pocketbus_write(ctx->bus_ctx, buf, len); + pocketbus_end(ctx->bus_ctx); + + if (wait_reply) + { + ctx->waiting = cmd; + ctx->reply_timer = timer_clock(); + } + return true; +} + +/** + * Init pocketBus command layer. + * \a ctx is pocketBus command layer context. + * \a bus_ctx is pocketBus context. + * \a addr is slave address (see pocketcmd_setAddr for details.) + * \a search is the lookup function used to search command ID callbacks. + */ +void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search) +{ + ASSERT(ctx); + ASSERT(bus_ctx); + ASSERT(search); + MOD_CHECK(timer); + + memset(ctx, 0, sizeof(*ctx)); + ctx->bus_ctx = bus_ctx; + ctx->search = search; + pocketcmd_setAddr(ctx, addr); +} + +/** + * Helper function used to reply to master with an ACK. + */ +void pocketcmd_replyAck(struct PocketCmdMsg *msg) +{ + uint8_t ack[] = { POCKETBUS_ACK }; + + pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, ack, sizeof(ack)); +} + +/** + * Helper function used to reply to master with a NAK. + */ +void pocketcmd_replyNak(struct PocketCmdMsg *msg) +{ + uint8_t nak[] = { POCKETBUS_NAK }; + + pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, nak, sizeof(nak)); +} + diff --git a/bertos/net/pocketcmd.h b/bertos/net/pocketcmd.h new file mode 100644 index 00000000..7045f3fe --- /dev/null +++ b/bertos/net/pocketcmd.h @@ -0,0 +1,112 @@ +/** + * \file + * + * + * \version $Id: pocketcmd.h 20030 2007-12-04 16:16:09Z batt $ + * + * \author Francesco Sacchi + * + * \brief pocketBus protocol command layer interface. + */ + +#ifndef NET_POCKETCMD_H +#define NET_POCKETCMD_H + +#include "pocketbus.h" +#include + +#define PKTCMD_NULL 0 ///< pocketBus Null command + +#define PKTCMD_REPLY_TIMEOUT 50 ///< Command replay timeout in milliseconds + +typedef uint16_t pocketcmd_t; ///< Type for Command IDs + +/** + * Header for transmitted pocketBus Commands. + */ +typedef struct PocketCmdHdr +{ + pocketcmd_t cmd; ///< command ID +} PocketCmdHdr; + +/** + * This ensure that endianess convertion functions work on + * the right data size. + * \{ + */ +STATIC_ASSERT(sizeof(pocketcmd_t) == sizeof(uint16_t)); +/*\}*/ + +/* fwd declaration */ +struct PocketCmdCtx; + +/** + * pocketBus command message structure. + */ +typedef struct PocketCmdMsg +{ + struct PocketCmdCtx *cmd_ctx; ///< command context + pocketcmd_t cmd; ///< command id + pocketbus_len_t len; ///< optional arg length + const uint8_t *buf; ///< optional arguments +} PocketCmdMsg; + +/** + * Type for command hooks. + */ +typedef void (*pocketcmd_hook_t)(struct PocketCmdMsg *cmd_msg); + +/** + * Type for lookup function hooks. + */ +typedef pocketcmd_hook_t (*pocketcmd_lookup_t)(pocketcmd_t cmd); + +/** + * pocketBus context for command layer communications. + */ +typedef struct PocketCmdCtx +{ + struct PocketBusCtx *bus_ctx; ///< pocketBus context + pocketbus_addr_t addr; ///< Our address + pocketcmd_lookup_t search; ///< Lookup function used to search for command callbacks + pocketcmd_t waiting; ///< The command ID we are waiting for or PKTCMD_NULL. + ticks_t reply_timer; ///< For waiting_reply +} PocketCmdCtx; + +/** + * Set slave address \a addr for pocketBus command layer. + * If we are a slave this is *our* address. + * If we are the master this is the slave address to send messages to. + */ +INLINE void pocketcmd_setAddr(struct PocketCmdCtx *ctx, pocketbus_addr_t addr) +{ + ctx->addr = addr; +} + +void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search); +void pocketcmd_poll(struct PocketCmdCtx *ctx); +bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool has_replay); +void pocketcmd_replyNak(struct PocketCmdMsg *msg); +void pocketcmd_replyAck(struct PocketCmdMsg *msg); + +/** + * Helper function used by master to send a command to slave \a addr. + */ +INLINE bool pocketcmd_masterSend(struct PocketCmdCtx *ctx, pocketbus_addr_t addr, pocketcmd_t cmd, const void *buf, size_t len) +{ + pocketcmd_setAddr(ctx, addr); + return pocketcmd_send(ctx, cmd, buf, len, true); +} + +/** + * Helper function used by slave to reply to a master command. + */ +INLINE bool pocketcmd_slaveReply(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len) +{ + return pocketcmd_send(ctx, cmd, buf, len, false); +} + + +#endif /* NET_POCKETCMD_H */ diff --git a/bertos/os/hptime.c b/bertos/os/hptime.c new file mode 100644 index 00000000..b93712ba --- /dev/null +++ b/bertos/os/hptime.c @@ -0,0 +1,79 @@ +/** + * \file + * + * + * \brief Portable abstraction for high-resolution time handling (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "hptime.h" + +#if defined(_WIN32) + +#include + +hptime_t hptime_get(void) +{ + FILETIME ft; + + /* + * La precisione dei FileTime sarebbe 100ns, ma il + * valore viene ottenuto convertendo una struttura + * SYSTEMTIME, che ha precisione di 1ms. Il numero + * che otteniamo e' quindi sempre un multiplo di + * 100000. + */ + GetSystemTimeAsFileTime(&ft); + + /* Copy the upper/lower into a quadword. */ + return (((hptime_t)ft.dwHighDateTime) << 32) + (hptime_t)ft.dwLowDateTime; +} + +#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + +#include /* for gettimeofday() */ +#include /* for NULL */ + +hptime_t hptime_get(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return (hptime_t)tv.tv_sec * HPTIME_TICKS_PER_SECOND + + (hptime_t)tv.tv_usec; +} + +#else /* !__unix__ */ + #error OS dependent support code missing for this OS +#endif /* !__unix__ */ + diff --git a/bertos/os/hptime.h b/bertos/os/hptime.h new file mode 100644 index 00000000..7e5b88a0 --- /dev/null +++ b/bertos/os/hptime.h @@ -0,0 +1,84 @@ +/** + * \file + * + * + * \brief Portable abstraction for high-resolution time handling (interface) + * + * \author Bernardo Innocenti + */ +#ifndef HPTIME_H +#define HPTIME_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 + + /** our type for "high precision absolute time" */ + typedef __int64 hptime_t; + + #define HPTIME_TICKS_PER_SECOND (10000000I64) + #define HPTIME_TICKS_PER_MILLISEC (10000I64) + #define HPTIME_TICKS_PER_MICRO (10I64) + +#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + + #include /* int64_t */ + + #ifndef DEVLIB_MTIME_DEFINED + #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with */ + typedef int32_t mtime_t; + #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR) + #define MTIME_INFINITE 0x7FFFFFFFL + #endif + + /** Type for "high precision absolute time". */ + typedef int64_t hptime_t; + + #define HPTIME_TICKS_PER_SECOND (1000000LL) + #define HPTIME_TICKS_PER_MILLISEC (1000LL) + #define HPTIME_TICKS_PER_MICRO (1LL) + +#else /* !__unix__ */ + #error OS dependent support code missing for this OS +#endif /* !__unix__ */ + +/** + * Return the current time with the maximum precision made available from the hosting OS + */ +extern hptime_t hptime_get(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* HPTIME_H */ diff --git a/bertos/rules.mk b/bertos/rules.mk new file mode 100644 index 00000000..68426c43 --- /dev/null +++ b/bertos/rules.mk @@ -0,0 +1,290 @@ +# +# $Id$ +# Copyright 2002,2003,2004,2005,2006 Develer S.r.l. (http://www.develer.com/) +# All rights reserved. +# +# Based on: +# GCC-AVR standard Makefile part 2 +# Volker Oth 1/2000 +# +# Author: Bernardo Innocenti +# + +# Remove all default pattern rules +.SUFFIXES: + +# Verbosity +ifeq ($(V),1) +# Verbose build +Q := +L := @echo >/dev/null +else +# Quiet build +Q := @ +L := @echo +endif + +# Select Bourne Again SHell as default make shell +SHELL := bash + +# Checker build +ifeq ($(C),1) +CC = $(CHECKER) +CFLAGS += -Wundef -D__x86_64__=1 -D__unix__=1 -D__linux__=1 -D__STDC_VERSION__=199901L +endif + +# Initialize $(top_srcdir) with current directory, unless it was already initialized +top_srcdir ?= $(shell pwd) + +# Products +TRG_ELF = $(TRG:%=$(OUTDIR)/%.elf) +TRG_S19 = $(TRG:%=$(OUTDIR)/%.s19) +TRG_HEX = $(TRG:%=$(OUTDIR)/%.hex) +TRG_BIN = $(TRG:%=$(OUTDIR)/%.bin) +TRG_ROM = $(TRG:%=$(OUTDIR)/%.rom) +TRG_COF = $(TRG:%=$(OUTDIR)/%.cof) +TRG_EXE = $(TRG:%=$(OUTDIR)/%) + + +RECURSIVE_TARGETS = all-recursive install-recursive clean-recursive + +# The default target +.PHONY: all +ifeq ($(EMBEDDED_TARGET),1) +all:: all-recursive $(TRG_S19) $(TRG_HEX) $(TRG_BIN) +else +all:: all-recursive $(TRG_EXE) +endif + +# Generate project documentation +.PHONY: docs +docs: + $L "Building documentation" + $Q $(DOXYGEN) + +# Generate ctags +.PHONY: tags +tags: + $L "Rebuilding C tags database" + $Q ctags -R --exclude=doc + +# Run testsuite +.PHONY: check +check: + $L "Running testsuite" + $Q ./run_tests.sh + +define build_target + +ifneq ($$(strip $$($(1)_MCU)),) +# Define all project specific object files +$(1)_CFLAGS += -mmcu=$$($(1)_MCU) +$(1)_CXXFLAGS += -mmcu=$$($(1)_MCU) +$(1)_ASFLAGS += -mmcu=$$($(1)_MCU) +$(1)_CPPAFLAGS += -mmcu=$$($(1)_MCU) +$(1)_LDFLAGS += -mmcu=$$($(1)_MCU) +endif +ifneq ($$(strip $$($(1)_CPU)),) +# Define all project specific object files +$(1)_CFLAGS += -mcpu=$$($(1)_CPU) +$(1)_CXXFLAGS += -mcpu=$$($(1)_CPU) +$(1)_ASFLAGS += -mcpu=$$($(1)_CPU) +$(1)_CPPAFLAGS += -mcpu=$$($(1)_CPU) +$(1)_LDFLAGS += -mcpu=$$($(1)_CPU) +endif +ifneq ($$(strip $$($(1)_LDSCRIPT)),) +$(1)_LDFLAGS += -Wl,-T$$($(1)_LDSCRIPT) +endif + +$(1)_CC = $$($(1)_CROSS)$$(CC) +$(1)_CXX = $$($(1)_CROSS)$$(CXX) +$(1)_AS = $$($(1)_CROSS)$$(AS) +$(1)_OBJCOPY = $$($(1)_CROSS)$$(OBJCOPY) + +$(1)_COBJ = $$(foreach file,$$($(1)_CSRC:%.c=%.o),$$(OBJDIR)/$(1)/$$(file)) +$(1)_CXXOBJ = $$(foreach file,$$($(1)_CXXSRC:%.cpp=%.o),$$(OBJDIR)/$(1)/$$(file)) +$(1)_PCOBJ = $$(foreach file,$$($(1)_PCSRC:%.c=%_P.o),$$(OBJDIR)/$(1)/$$(file)) +$(1)_AOBJ = $$(foreach file,$$($(1)_ASRC:%.s=%.o),$$(OBJDIR)/$(1)/$$(file)) +$(1)_CPPAOBJ = $$(foreach file,$$($(1)_CPPASRC:%.S=%.o),$$(OBJDIR)/$(1)/$$(file)) +$(1)_OBJ := $$($(1)_COBJ) $$($(1)_CXXOBJ) $$($(1)_PCOBJ) $$($(1)_AOBJ) $$($(1)_CPPAOBJ) +$(1)_SRC := $$($(1)_CSRC) $$($(1)_CXXSRC) $$($(1)_PCSRC) $$($(1)_ASRC) $$($(1)_CPPASRC) +OBJ += $$($(1)_OBJ) + +ifneq ($$(strip $$($(1)_CXXSRC)),) +$(1)_LD = $$($(1)_CROSS)$$(LDXX) +else +$(1)_LD = $$($(1)_CROSS)$$(LD) +endif + +# Compile: instructions to create assembler and/or object files from C source +$$($(1)_COBJ) : $$(OBJDIR)/$(1)/%.o : %.c + $L "$(1): Compiling $$< (C)" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CC) -c $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ + +# Compile: instructions to create assembler and/or object files from C++ source +$$($(1)_CXXOBJ) : $$(OBJDIR)/$(1)/%.o : %.cpp + $L "$(1): Compiling $$< (C++)" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CXX) -c $$(CXXFLAGS) $$($(1)_CXXFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ + +# Generate assembly sources from C files (debug) +$$(OBJDIR)/$(1)/%.s : %.c + $L "$(1): Generating asm source $$<" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CC) -S $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$< -o $$@ + +# Generate special progmem variant of a source file +$$($(1)_PCOBJ) : $$(OBJDIR)/$(1)/%_P.o : %.c + $L "$(1): Compiling $$< (PROGMEM)" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CC) -c -D_PROGMEM $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ + +# Assemble: instructions to create object file from assembler files +$$($(1)_AOBJ): $$(OBJDIR)/$(1)/%.o : %.s + $L "$(1): Assembling $$<" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_AS) -c $$(ASFLAGS) $$($(1)_ASFLAGS) $$< -o $$@ + +$$($(1)_CPPAOBJ): $$(OBJDIR)/$(1)/%.o : %.S + $L "$(1): Assembling with CPP $$<" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CC) -c $$(CPPAFLAGS) $$($(1)_CPPAFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ + + +# Link: instructions to create elf output file from object files +$$(OUTDIR)/$(1).elf $$(OUTDIR)/$(1)_nostrip: bumprev $$($(1)_OBJ) $$($(1)_LDSCRIPT) + $L "$(1): Linking $$@" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_LD) $$($(1)_OBJ) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@ + +# Strip debug info +$$(OUTDIR)/$(1): $$(OUTDIR)/$(1)_nostrip + $L "$(1): Generating stripped executable $$@" + $Q $$($(1)_STRIP) -o $$@ $$^ + +# Compile and link (program-at-a-time) +$$(OUTDIR)/$(1)_whole.elf: bumprev $$($(1)_SRC) $$($(1)_LDSCRIPT) + $L "$(1): Compiling and Linking whole program $$@" + @$$(MKDIR_P) $$(dir $$@) + $Q $$($(1)_CC) $$($(1)_SRC) $$(CFLAGS) $$($(1)_CFLAGS) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@ + +# Flash target +# NOTE: we retry in case of failure because the STK500 programmer is crappy +.PHONY: flash_$(1) +flash_$(1): $(OUTDIR)/$(1).s19 flash_$(1)_local + if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U flash:w:$$< ; then \ + $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U flash:w:$$< ; \ + fi + #avarice --mkII -j usb --erase --program --verify --file images/triface.elf + +.PHONY: flash_$(1)_local +flash_$(1)_local: + +.PHONY: fuses_$(!) +fuses_$(1): + if [ ! -z "$$($(1)_efuse)" ] ; then \ + if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U efuse:w:$$($(1)_efuse):m ; then \ + $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U efuse:w:$$($(1)_efuse):m ; \ + fi \ + fi + if [ ! -z "$$($(1)_hfuse)" ] ; then \ + if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U hfuse:w:$$($(1)_hfuse):m ; then \ + $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U hfuse:w:$$($(1)_hfuse):m ; \ + fi \ + fi + if [ ! -z "$$($(1)_lfuse)" ] ; then \ + if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lfuse:w:$$($(1)_lfuse):m ; then \ + $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lfuse:w:$$($(1)_lfuse):m ; \ + fi \ + fi + if [ ! -z "$$($(1)_lock)" ] ; then \ + if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lock:w:$$($(1)_lock):m ; then \ + $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lock:w:$$($(1)_lock):m ; \ + fi \ + fi + +$$(OUTDIR)/$(1).hex: $$(OUTDIR)/$(1).elf + $$($(1)_OBJCOPY) -O ihex $$< $$@ + +$$(OUTDIR)/$(1).s19: $$(OUTDIR)/$(1).elf + $$($(1)_OBJCOPY) -O srec $$< $$@ + +$$(OUTDIR)/$(1).bin: $$(OUTDIR)/$(1).elf + $$($(1)_OBJCOPY) -O binary $$< $$@ + +$$(OUTDIR)/$(1).obj: $$(OUTDIR)/$(1).elf + $$($(1)_OBJCOPY) -O avrobj $$< $$@ + +$$(OUTDIR)/$(1).rom: $$(OUTDIR)/$(1).elf + $$($(1)_OBJCOPY) -O $$(FORMAT) $$< $$@ +# $$($(1)_OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" -O $$(FORMAT) $$< $$(@:.rom=.eep) + +endef + +# Generate build rules for all targets +$(foreach t,$(TRG),$(eval $(call build_target,$(t)))) + +# Generate Qt's moc files from headers +# NOTE: moc totally sucks and can generate empty files for some error conditions, +# leading to puzzling linker errors. Kill 'em and abort build. +%_moc.cpp: %.h + $(MOC) -o $@ $< + if [ ! -s $< ]; then \ + rm -f $@; \ + exit 1; \ + fi + + +%.cof: %.elf + $(COFFCONVERT) -O coff-ext-avr $< $@ +# $(COFFCONVERT) -O coff-avr $< $@ # For use with AVRstudio 3 + +#make instruction to delete created files +clean: clean-recursive + -$(RM_R) $(OBJDIR) + -$(RM_R) $(OUTDIR) + +$(RECURSIVE_TARGETS): + @target=`echo $@ | sed s/-recursive//`; \ + for dir in $(SUBDIRS); do \ + if [ -e $$dir/configure.in ] || [ -e $$dir/configure.ac ] && [ ! -x $$dir/configure ]; then \ + echo "Running autogen.sh in $$dir..."; \ + ( cd $$dir && chmod a+x autogen.sh && ./autogen.sh && rm -f Makefile || exit 1 ); \ + fi; \ + if [ ! -e $$dir/Makefile ]; then \ + if [ -e "$$dir/build-$(ARCH)" ]; then \ + echo "Running build script in $$dir..."; \ + ( cd $$dir && chmod a+x build && ./build || exit 1 ); \ + else \ + echo "Running configure in $$dir..."; \ + ( cd $$dir && ./configure --prefix=$(PREFIX) || exit 1 ); \ + fi; \ + fi; \ + $(MAKE) -C $$dir $$target || exit 1; \ + done + +BUILDREV_H = buildrev.h + +ifeq ($(shell [ -e bertos/verstag.c ] && echo yes),yes) +.PHONY: bumprev +bumprev: + @buildnr=0; \ + if [ -f $(BUILDREV_H) ]; then \ + buildnr=`sed <"$(BUILDREV_H)" -n -e 's/#define VERS_BUILD \([0-9][0-9]*\)/\1/p'`; \ + fi; \ + buildnr=`expr $$buildnr + 1`; \ + buildhost=`hostname`; \ + echo "#define VERS_BUILD $$buildnr" >"$(BUILDREV_H)"; \ + echo "#define VERS_HOST \"$$buildhost\"" >>"$(BUILDREV_H)"; \ + echo "Building revision $$buildnr" +else +.PHONY: bumprev +bumprev: + +endif + +# Include dependencies +ifneq ($(strip $(OBJ)),) +-include $(OBJ:%.o=%.d) +endif diff --git a/bertos/run_tests.sh b/bertos/run_tests.sh new file mode 100755 index 00000000..7edc89df --- /dev/null +++ b/bertos/run_tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright 2005 Develer S.r.l. (http://www.develer.com/) +# All rights reserved. +# +# Author: Bernardo Innocenti +# +# $Id$ +# + + +VERBOSE=1 + +CC=gcc +CFLAGS="-W -Wall -Wextra -I. -fno-builtin -D_DEBUG" + +CXX=g++ +CXXFLAGS="$CFLAGS" + + +for test in `find . -name "*_test.*"`; do + [ $VERBOSE -gt 0 ] && echo "Running $test..." + case "$test" in + *.cpp) + $CXX $CXXFLAGS $test -o test || exit 1 + ./test || exit 1 + rm -f test + ;; + *.c) + $CC $CFLAGS $test -o test || exit 1 + ./test || exit 1 + rm -f test + ;; + esac +done + diff --git a/bertos/verstag.c b/bertos/verstag.c new file mode 100644 index 00000000..a99e2b2c --- /dev/null +++ b/bertos/verstag.c @@ -0,0 +1,51 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Define application version strings + */ +#include + +/* + * "buildrev.h" is auto-generated by the build infrastructure, + * incrementing VERS_BUILD each time the project is rebuilt. + */ +#include "buildrev.h" + +const char vers_tag[] = VERS_TAG; +const char vers_build_str[] = _STRINGIZE(VERS_BUILD); +const char vers_host[] = VERS_HOST; +const int vers_build_nr = VERS_BUILD; + diff --git a/bertos/verstag.h b/bertos/verstag.h new file mode 100644 index 00000000..a37bcc11 --- /dev/null +++ b/bertos/verstag.h @@ -0,0 +1,103 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * + * \brief Declare application version strings + */ +#ifndef DEVLIB_VERSTAG_H +#define DEVLIB_VERSTAG_H + +#ifndef ARCH_CONFIG_H + #include +#endif + +#define APP_NAME "Appname" +#define APP_DESCRIPTION "Long application name description" +#define APP_AUTHOR "Develer" +#define APP_COPYRIGHT "Copyright 2006 Develer (http://www.develer.com/)" + +#if (ARCH & ARCH_FOO) + #define VERS_MAJOR 0 + #define VERS_MINOR 1 + #define VERS_REV 0 + #define VERS_LETTER "" +#elif (ARCH & ARCH_BAR) + #define VERS_MAJOR 0 + #define VERS_MINOR 1 + #define VERS_REV 0 + #define VERS_LETTER "" +#else + #error unknown architecture +#endif + +/** + * If _SNAPSHOT is defined, \c VERS_TAG contains the build date + * date instead of a numeric version string. + */ +#define _SNAPSHOT + +#ifdef _DEBUG + #define VERS_DBG "D" +#else + #define VERS_DBG "" +#endif + +#define __STRINGIZE(x) #x +#define _STRINGIZE(x) __STRINGIZE(x) + +/** Build application version string (i.e.: "1.7.0") */ +#define MAKE_VERS(maj,min,rev) _STRINGIZE(maj) "." _STRINGIZE(min) "." _STRINGIZE(rev) VERS_LETTER VERS_DBG +#ifdef _SNAPSHOT + #define VERS_TAG "snapshot" " " __DATE__ " " __TIME__ " " VERS_LETTER " " VERS_DBG +#else + #define VERS_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV) +#endif + +/** Build application version string suitable for MS windows resource files (i.e.: "1, 7, 0, 1") */ +#define MAKE_RCVERS(maj,min,rev,bld) _STRINGIZE(maj) ", " _STRINGIZE(min) ", " _STRINGIZE(rev) ", " _STRINGIZE(bld) +#define RCVERSION_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV) + +/** The revision string (contains VERS_TAG) */ +extern const char vers_tag[]; + +/** Sequential build number (contains VERS_BUILD) */ +extern const int vers_build_nr; +//extern const char vers_build_str[]; + +/** Hostname of the machine used to build this binary (contains VERS_HOST) */ +extern const char vers_host[]; + +#endif /* DEVLIB_VERSTAG_H */ diff --git a/cfg/arch_config.h b/cfg/arch_config.h deleted file mode 100644 index 01ed05d3..00000000 --- a/cfg/arch_config.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Set system configuration - */ - - -#ifndef ARCH_CONFIG_H -#define ARCH_CONFIG_H - -/** - * \name Architectures - * \{ - */ -#define ARCH_FOO (1<<0) -#define ARCH_BAR (1<<1) -#define ARCH_EMUL (1<<8) -/*\}*/ - -#endif /* ARCH_CONFIG_H */ diff --git a/cfg/compiler.h b/cfg/compiler.h deleted file mode 100644 index a303dc77..00000000 --- a/cfg/compiler.h +++ /dev/null @@ -1,528 +0,0 @@ -/** - * \file - * - * - * \brief Additional support macros for compiler independance - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#ifndef BERTOS_COMPILER_H -#define BERTOS_COMPILER_H - -#include - - -#if defined __GNUC__ && defined __GNUC_MINOR__ - #define GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else - #define GNUC_PREREQ(maj, min) 0 -#endif - -/* Some CW versions do not allow enabling C99 from the settings panel. */ -#if defined(__MWERKS__) - #pragma c99 on -#endif - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #define COMPILER_C99 1 -#else - #define COMPILER_C99 0 -#endif - - -/** Concatenate two different preprocessor tokens (allowing macros to expand) */ -#define PP_CAT(x,y) PP_CAT__(x,y) -#define PP_CAT__(x,y) x ## y -#define PP_CAT3(x,y,z) PP_CAT(PP_CAT(x,y),z) -#define PP_CAT4(x,y,z,w) PP_CAT(PP_CAT3(x,y,z),w) -#define PP_CAT5(x,y,z,w,j) PP_CAT(PP_CAT4(x,y,z,w),j) - -/** String-ize a token (allowing macros to expand) */ -#define PP_STRINGIZE(x) PP_STRINGIZE__(x) -#define PP_STRINGIZE__(x) #x - - -#if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) - - #pragma language=extended - - #if CPU_ARM - - #define COMPILER_VARIADIC_MACROS 1 - - #define INTERRUPT(x) __irq __arm void x (void) - #define INLINE static inline - - /* Include some standard C89/C99 stuff */ - #include - #include - #include - - #elif CPU_I196 - - // IAR has size_t as built-in type, but does not define this symbol. - #define _SIZE_T_DEFINED - - #define INTERRUPT(x) interrupt [x] - #define REGISTER shortad - #define INLINE /* unsupported */ - - /* - * Imported from . Unfortunately, we can't just include - * this header because it typedefs jmp_buf to be an array of chars. - * This would allow the compiler to place the buffer on an odd address. - * The CPU _should_ be able to perform word accesses to - * unaligned data, but there are *BUGS* in the 80196KC with - * some combinations of opcodes and addressing modes. One of - * these, "ST SP,[?GR]+" is used in the longjmp() implementation - * provided by the IAR compiler ANSI C library. When ?GR contains - * an odd address, surprisingly the CPU will copy the high order - * byte of the source operand (SP) in the low order byte of the - * destination operand (the memory location pointed to by ?GR). - * - * We also need to replace the library setjmp()/longjmp() with - * our own versions because the IAR implementation "forgets" to - * save the contents of local registers (?LR). - */ - struct _JMP_BUF - { - void *sp; /* Stack pointer */ - void *return_addr; /* Return address */ - int lr[6]; /* 6 local registers */ - }; - - typedef struct _JMP_BUF jmp_buf[1]; - - int setjmp(jmp_buf env); - void longjmp(jmp_buf env, int val); - - /* Fake bool support */ - #define true (1==1) - #define false (1!=1) - typedef unsigned char bool; - - #else - #error Unsupported CPU - #endif - -#elif defined(_MSC_VER) /* Win32 emulation support */ - - /* MSVC doesn't provide . */ - #ifndef __cplusplus - #define true (1==1) - #define false (1!=1) - typedef int bool; - #endif /* !__cplusplus */ - - /* These C99 functions are oddly named in MSVCRT32.lib */ - #define snprintf _snprintf - #define vsnprintf _vsnprintf - - /* MSVC doesn't support C99's __func__, but has a similar extension. */ - #define __func__ __FUNCTION__ - - /* MSVC doesn't support C99's inline keyword */ - #ifndef __cplusplus - #define INLINE __inline - #endif - -#elif defined(__GNUC__) - - /* Compiler features */ - #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */ - #define COMPILER_TYPEOF 1 - #define COMPILER_STATEMENT_EXPRESSIONS 1 - - /* GCC attributes */ - #define FORMAT(type,fmt,first) __attribute__((__format__(type, fmt, first))) - #define NORETURN __attribute__((__noreturn__)) - #define UNUSED_ARG(type,arg) __attribute__((__unused__)) type arg - #define UNUSED_VAR(type,name) __attribute__((__unused__)) type name - #define USED_VAR(type,name) __attribute__((__used__)) type name - #define INLINE static inline __attribute__((__always_inline__)) - #define LIKELY(x) __builtin_expect(!!(x), 1) - #define UNLIKELY(x) __builtin_expect(!!(x), 0) - #define PURE_FUNC __attribute__((pure)) - #define CONST_FUNC __attribute__((const)) - #define UNUSED_FUNC __attribute__((unused)) - #define USED_FUNC __attribute__((__used__)) - #define RESTRICT __restrict__ - #define MUST_CHECK __attribute__((warn_unused_result)) - #define PACKED __attribute__((packed)) - /** - * Force compiler to realod context variable. - */ - #define MEMORY_BARRIER asm volatile ("" : : : "memory") - - #if GNUC_PREREQ(3,1) - #define DEPRECATED __attribute__((__deprecated__)) - #endif - - #ifndef __cplusplus - #define ASSERT_TYPE_EQUAL(var1, var2) \ - STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2))) - #define ASSERT_TYPE_IS(var, type) \ - STATIC_ASSERT(__builtin_types_compatible_p(typeof(var), type)) - #endif - - /* Include some standard C89/C99 stuff */ - #include - #include - #include - #if !CPU_AVR - #include /* for ssize_t */ - #endif - - #ifndef __cplusplus - /* - * Disallow some C++ keywords as identifiers in C programs, - * for improved portability. - */ - #pragma GCC poison new delete class template typename - #pragma GCC poison private protected public operator - #pragma GCC poison friend mutable using namespace - #pragma GCC poison cin cout cerr clog - #endif - - - -#elif defined(__MWERKS__) - - /* Compiler features */ - #define COMPILER_VARIADIC_MACROS 1 - #define COMPILER_TYPEOF 1 - #define COMPILER_STATEMENT_EXPRESSIONS 1 - - #define typeof __typeof__ - - #define UNUSED_ARG(type,arg) type - - #include - #include - #include - - // CodeWarrior has size_t as built-in type, but does not define this symbol. - #define _SIZE_T_DEFINED - -#else - #error unknown compiler -#endif - - -/* Defaults for compiler extensions. */ - -/** - * \def COMPILER_VARIADIC_MACROS - * Support for macros with variable arguments. - */ -#ifndef COMPILER_VARIADIC_MACROS -#define COMPILER_VARIADIC_MACROS (COMPILER_C99 != 0) -#endif - -/** - * \def COMPILER_TYPEOF - * Support for dynamic type identification. - */ -#ifndef COMPILER_TYPEOF -#define COMPILER_TYPEOF 0 -#endif - -/** - * \def COMPILER_STATEMENT_EXPRESSIONS - * Support for statement expressions. - */ -#ifndef COMPILER_STATEMENT_EXPRESSIONS -#define COMPILER_STATEMENT_EXPRESSIONS 0 -#endif - -/* A few defaults for missing compiler features. */ -#ifndef INLINE -#define INLINE static inline -#endif -#ifndef NORETURN -#define NORETURN /* nothing */ -#endif -#ifndef FORMAT -#define FORMAT(type,fmt,first) /* nothing */ -#endif -#ifndef DEPRECATED -#define DEPRECATED /* nothing */ -#endif -#ifndef UNUSED_ARG -#define UNUSED_ARG(type,arg) type arg -#endif -#define UNUSED UNUSED_ARG /* OBSOLETE */ -#ifndef UNUSED_VAR -#define UNUSED_VAR(type,name) type name -#endif -#ifndef USED_VAR -#define USED_VAR(type,name) type name -#endif -#ifndef REGISTER -#define REGISTER /* nothing */ -#endif -#ifndef LIKELY -#define LIKELY(x) x -#endif -#ifndef UNLIKELY -#define UNLIKELY(x) x -#endif -#ifndef PURE_FUNC -#define PURE_FUNC /* nothing */ -#endif -#ifndef CONST_FUNC -#define CONST_FUNC /* nothing */ -#endif -#ifndef UNUSED_FUNC -#define UNUSED_FUNC /* nothing */ -#endif -#ifndef USED_FUNC -#define USED_FUNC /* nothing */ -#endif -#ifndef RESTRICT -#define RESTRICT /* nothing */ -#endif -#ifndef MUST_CHECK -#define MUST_CHECK /* nothing */ -#endif -#ifndef PACKED -#define PACKED /* nothing */ -#endif -#ifndef MEMORY_BARRIER -#define MEMORY_BARRIER /* nothing */ -#warning No memory barrier defined for select compiler. If you use the kernel check it. -#endif - - -/* Misc definitions */ -#ifndef NULL -#define NULL (void *)0 -#endif -#ifndef EOF -#define EOF (-1) -#endif - -/* Support for hybrid C/C++ applications. */ -#ifdef __cplusplus - #define EXTERN_C extern "C" - #define EXTERN_C_BEGIN extern "C" { - #define EXTERN_C_END } - #define EXTERN_CONST extern const - #define CONST_CAST(TYPE,EXPR) (const_cast(EXPR)) -#else - #define EXTERN_C extern - #define EXTERN_C_BEGIN /* nothing */ - #define EXTERN_C_END /* nothing */ - #define EXTERN_CONST const - #define CONST_CAST(TYPE,EXPR) ((TYPE)(EXPR)) /* FIXME: How can we suppress the warning in C? */ -#endif - - -#if defined(_MSC_VER) \ - || ((defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)) && CPU_I196) - /** - * \name ISO C99 fixed-size types - * - * These should be in , but a few compilers lack them. - * \{ - */ - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef short int int16_t; - typedef unsigned short int uint16_t; - typedef long int int32_t; /* _WIN64 safe */ - typedef unsigned long int uint32_t; /* _WIN64 safe */ - - #ifdef _MSC_VER - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - #else - typedef long long int64_t; - typedef unsigned long long uint64_t; - #endif - /* \} */ -#else - /* This is the standard location. */ - #include -#endif - -#if CPU_AVR_ATMEGA8 - /* - * The ATmega8 has a very small Flash, so we can't afford - * to link in support routines for 32bit integer arithmetic. - */ - typedef int16_t ticks_t; /**< Type for time expressed in ticks. */ - typedef int16_t mtime_t; /**< Type for time expressed in milliseconds. */ - typedef int16_t utime_t; /**< Type for time expressed in microseconds. */ - #define SIZEOF_MTIME_T (16 / CPU_BITS_PER_CHAR) - #define SIZEOF_UTIME_T (16 / CPU_BITS_PER_CHAR) - #define MTIME_INFINITE 0x7FFFL -#else - typedef int32_t ticks_t; /**< Type for time expressed in ticks. */ - - typedef int32_t utime_t; /**< Type for time expressed in microseconds. */ - #define SIZEOF_UTIME_T (32 / CPU_BITS_PER_CHAR) - - #ifndef DEVLIB_MTIME_DEFINED - #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with */ - typedef int32_t mtime_t; /**< Type for time expressed in milliseconds. */ - #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR) - #define MTIME_INFINITE 0x7FFFFFFFL - #endif -#endif - -/** Bulk storage large enough for both pointers or integers. */ -typedef void * iptr_t; - -/** Bulk storage large enough for both pointers to constants or integers. */ -typedef const void * const_iptr_t; - -typedef unsigned char sigbit_t; /**< Type for signal bits. */ -typedef unsigned char sigmask_t; /**< Type for signal masks. */ -typedef unsigned char page_t; /**< Type for banked memory pages. */ - - -/** - * \name Standard type definitions. - * - * These should be in or , but many compilers - * and C libraries lack them. - * - * We check for some common definitions to avoid redefinitions: - * - * glibc, avr-libc: _SIZE_T_DEFINED, __ssize_t_defined - * Darwin libc: _BSD_SIZE_T_DEFINED_, _SIZE_T - * IAR ARM: _SIZE_T - * - * \{ - */ -#if !(defined(size_t) || defined(_SIZE_T_DEFINED) || defined(_BSD_SIZE_T_DEFINED_) \ - || defined(_SIZE_T)) - #if CPU_X86 - /* 32bit or 64bit (32bit for _WIN64). */ - typedef unsigned long size_t; - #else - #error Unknown CPU - #endif -#endif - -#if !(defined(ssize_t) || defined(_SSIZE_T) || defined(__ssize_t_defined)) - #if CPU_X86 - /* 32bit or 64bit (32bit for _WIN64). */ - typedef long ssize_t; - #elif CPU_ARM - typedef int ssize_t; - #elif CPU_AVR - /* 16bit (missing in avr-libc's sys/types.h). */ - typedef int ssize_t; - #else - #error Unknown CPU - #endif -#endif -/*\}*/ - - -/** - * \name Types for hardware registers. - * - * Only use these types for registers whose contents can - * be changed asynchronously by external hardware. - * - * \{ - */ -#if CPU_DSP56K - /* Registers can be accessed only through 16-bit pointers */ - typedef volatile uint16_t reg16_t; -#else - typedef volatile uint8_t reg8_t; - typedef volatile uint16_t reg16_t; - typedef volatile uint32_t reg32_t; -#endif -/*\}*/ - - -/* Quasi-ANSI macros */ -#ifndef offsetof - /** - * Return the byte offset of the member \a m in struct \a s. - * - * \note This macro should be defined in "stddef.h" and is sometimes - * compiler-specific (g++ has a builtin for it). - */ - #define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif -#ifndef countof - /** - * Count the number of elements in the static array \a a. - * - * \note This macro is non-standard, but implements a very common idiom - */ - #define countof(a) (sizeof(a) / sizeof(*(a))) -#endif - -/** - * Cast a member of a structure out to the containing structure. - * - * \param ptr the pointer to the member. - * \param type the type of the container struct this is embedded in. - * \param member the name of the member within the struct. - */ -#if COMPILER_TYPEOF && COMPILER_STATEMENT_EXPRESSIONS - #define containerof(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *_mptr = (ptr); /* type check */ \ - (type *)((char *)_mptr - offsetof(type, member)); \ - }) -#else - #define containerof(ptr, type, member) \ - ( (type *)((char *)(ptr) - offsetof(type, member)) ) -#endif - -/** Issue a compilation error if the \a condition is false */ -#define STATIC_ASSERT(condition) \ - UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1]) - -#ifndef ASSERT_TYPE_EQUAL - /** Ensure two variables have the same type. */ - #define ASSERT_TYPE_EQUAL(var1, var2) \ - do { (void)(&(var1) == &(var2)); } while(0) -#endif - -#ifndef ASSERT_TYPE_IS - /** Ensure variable is of specified type. */ - #define ASSERT_TYPE_IS(var, type) \ - do { (void)(&(var) == (type *)0); } while(0) -#endif - -#endif /* BERTOS_COMPILER_H */ diff --git a/cfg/debug.h b/cfg/debug.h deleted file mode 100644 index a75b4d2d..00000000 --- a/cfg/debug.h +++ /dev/null @@ -1,313 +0,0 @@ -/** - * \file - * - * - * \brief Simple debug facilities for hosted and embedded C/C++ applications. - * - * Debug output goes to stderr in hosted applications. - * Freestanding (AKA embedded) applications use \c drv/kdebug.c to output - * diagnostic messages to a serial terminal or a JTAG debugger. - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#ifndef DEVLIB_DEBUG_H -#define DEVLIB_DEBUG_H - -#include -#include - - -/* - * Defaults for rarely used config stuff. - */ -#ifndef CONFIG_KDEBUG_DISABLE_TRACE -#define CONFIG_KDEBUG_DISABLE_TRACE 0 -#endif - -#ifndef CONFIG_KDEBUG_ASSERT_NO_TEXT -#define CONFIG_KDEBUG_ASSERT_NO_TEXT 0 -#endif - -#if defined(__doxygen__) - /** - * Preprocessor symbol defined only for debug builds. - * - * The build infrastructure must arrange for _DEBUG to - * be predefined for all the source files being compiled. - * - * This is compatible with the MSVC convention for the - * default Debug and Release project targets. - */ - #define _DEBUG 1 -#endif - -#ifdef _DEBUG - - // STLport specific: enable extra checks - #define __STL_DEBUG 1 - - // MSVC specific: Enable memory allocation debug - #if defined(_MSC_VER) - #include - #endif - - /* - * On UNIX systems the extabilished practice is to define - * NDEBUG for release builds and nothing for debug builds. - */ - #ifdef NDEBUG - #undef NDEBUG - #endif - - /** - * This macro duplicates the old MSVC trick of redefining - * THIS_FILE locally to avoid the overhead of many duplicate - * strings in ASSERT(). - */ - #ifndef THIS_FILE - #define THIS_FILE __FILE__ - #endif - - /** - * This macro can be used to conditionally exclude one or more - * statements conditioned on \c _DEBUG, avoiding the clutter - * of ifdef/endif pairs. - * - * \code - * struct FooBar - * { - * int foo; - * bool bar; - * DB(int ref_count;) // Track number of users - * - * void release() - * { - * DB(--ref_count;) - * } - * }; - * \endcode - */ - #define DB(x) x - - #include /* CONFIG_KDEBUG_ASSERT_NO_TEXT */ - #include /* CPU_HARVARD */ - - /* These are implemented in drv/kdebug.c */ - void kdbg_init(void); - void kputchar(char c); - int kputnum(int num); - void kdump(const void *buf, size_t len); - void __init_wall(long *wall, int size); - - #if CPU_HARVARD - #include - void kputs_P(const char *PROGMEM str); - void kprintf_P(const char *PROGMEM fmt, ...) FORMAT(__printf__, 1, 2); - int __assert_P(const char *PROGMEM cond, const char *PROGMEM file, int line); - void __trace_P(const char *func); - void __tracemsg_P(const char *func, const char *PROGMEM fmt, ...); - int __invalid_ptr_P(void *p, const char *PROGMEM name, const char *PROGMEM file, int line); - int __check_wall_P(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line); - #define kputs(str) kputs_P(PSTR(str)) - #define kprintf(fmt, ...) kprintf_P(PSTR(fmt) ,## __VA_ARGS__) - #define __assert(cond, file, line) __assert_P(PSTR(cond), PSTR(file), (line)) - #define __trace(func) __trace_P(func) - #define __tracemsg(func, fmt, ...) __tracemsg_P(func, PSTR(fmt), ## __VA_ARGS__) - #define __invalid_ptr(p, name, file, line) __invalid_ptr_P((p), PSTR(name), PSTR(file), (line)) - #define __check_wall(wall, size, name, file, line) __check_wall_P(wall, size, PSTR(name), PSTR(file), (line)) - #else /* !CPU_HARVARD */ - void kputs(const char *str); - void kprintf(const char *fmt, ...) FORMAT(__printf__, 1, 2); - int __assert(const char *cond, const char *file, int line); - void __trace(const char *func); - void __tracemsg(const char *func, const char *fmt, ...) FORMAT(__printf__, 2, 3); - int __invalid_ptr(void *p, const char *name, const char *file, int line); - int __check_wall(long *wall, int size, const char *name, const char *file, int line); - #endif /* !CPU_HARVARD */ - - #if !CONFIG_KDEBUG_ASSERT_NO_TEXT - #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert(#x, THIS_FILE, __LINE__))) - #define ASSERT2(x, help) ((void)(LIKELY(x) ? 0 : __assert(help " (" #x ")", THIS_FILE, __LINE__))) - #else - #define ASSERT(x) ((void)(LIKELY(x) ? 0 : __assert("", THIS_FILE, __LINE__))) - #define ASSERT2(x, help) ((void)ASSERT(x)) - #endif - - /** - * Check that the given pointer is either NULL or pointing to valid memory. - * - * The assumption here is that valid pointers never point to low - * memory regions. This helps catching pointers taken from - * struct/class memebers when the struct pointer was NULL. - */ - #define ASSERT_VALID_PTR(p) ((void)(LIKELY((p) >= 0x200) ? 0 : __invalid_ptr(p, #p, THIS_FILE, __LINE__))) - - /** - * Check that the given pointer is not pointing to invalid memory. - * - * \see ASSERT_VALID_PTR() - */ - #define ASSERT_VALID_PTR_OR_NULL(p) ((void)(LIKELY((p == NULL) || ((p) >= 0x200)) ? 0 : __invalid_ptr((p), #p, THIS_FILE, __LINE__))) - - #if !CONFIG_KDEBUG_DISABLE_TRACE - #define TRACE __trace(__func__) - #define TRACEMSG(msg,...) __tracemsg(__func__, msg, ## __VA_ARGS__) - #else - #define TRACE do {} while(0) - #define TRACEMSG(...) do {} while(0) - #endif - - /** - * \name Walls to detect data corruption - * \{ - */ - #define WALL_SIZE 8 - #define WALL_VALUE (long)0xABADCAFEL - #define DECLARE_WALL(name,size) long name[(size) / sizeof(long)]; - #define FWD_DECLARE_WALL(name,size) extern long name[(size) / sizeof(long)]; - #define INIT_WALL(name) __init_wall((name), countof(name)) - #define CHECK_WALL(name) __check_wall((name), countof(name), #name, THIS_FILE, __LINE__) - /*\}*/ - - /** - * Check that the given pointer actually points to an object - * of the specified type. - */ - #define ASSERT_VALID_OBJ(_t, _o) do { \ - ASSERT_VALID_PTR((_o)); \ - ASSERT(dynamic_cast<_t>((_o)) != NULL); \ - } - - /** - * \name Debug object creation and destruction. - * - * These macros help track some kinds of leaks in C++ programs. - * Usage is as follows: - * - * \code - * class Foo - * { - * DECLARE_INSTANCE_TRACKING(Foo) - * - * Foo() - * { - * NEW_INSTANCE(Foo); - * // ... - * } - * - * ~Foo() - * { - * DELETE_INSTANCE(Foo); - * // ... - * } - * }; - * - * // Put this in the implementation file of the class - * IMPLEMENT_INSTANCE_TRACKING(Foo) - * - * // Client code - * int main(void) - * { - * Foo *foo = new Foo; - * cout << GET_INSTANCE_COUNT(Foo) << endl; // prints "1" - * delete foo; - * ASSERT_ZERO_INSTANCES(Foo); // OK - * } - * \endcode - * \{ - */ - #define NEW_INSTANCE(CLASS) do { ++CLASS::__instances } while (0) - #define DELETE_INSTANCE(CLASS) do { --CLASS::__instances } while (0) - #define ASSERT_ZERO_INSTANCES(CLASS) ASSERT(CLASS::__instances == 0) - #define GET_INSTANCE_COUNT(CLASS) (CLASS::__instances) - #define DECLARE_INSTANCE_TRACKING(CLASS) static int __instances - #define IMPLEMENT_INSTANCE_TRACKING(CLASS) int CLASS::__instances = 0 - /*\}*/ - -#else /* !_DEBUG */ - - /* - * On UNIX systems the extabilished practice is to define - * NDEBUG for release builds and nothing for debug builds. - */ - #ifndef NDEBUG - #define NDEBUG 1 - #endif - - #define DB(x) /* nothing */ - #ifndef ASSERT - #define ASSERT(x) ((void)0) - #endif /* ASSERT */ - #define ASSERT2(x, help) ((void)0) - #define ASSERT_VALID_PTR(p) ((void)0) - #define ASSERT_VALID_PTR_OR_NULL(p) ((void)0) - #define ASSERT_VALID_OBJ(_t, _o) ((void)0) - #define TRACE do {} while (0) - #if COMPILER_VARIADIC_MACROS - #define TRACEMSG(x, ...) do {} while (0) - #else - INLINE void TRACEMSG(UNUSED_ARG(const char *, msg), ...) - { - /* NOP */ - } - #endif - - #define DECLARE_WALL(name, size) /* nothing */ - #define FWD_DECLARE_WALL(name, size) /* nothing */ - #define INIT_WALL(name) do {} while (0) - #define CHECK_WALL(name) do {} while (0) - - #define NEW_INSTANCE(CLASS) do {} while (0) - #define DELETE_INSTANCE(CLASS) do {} while (0) - #define ASSERT_ZERO_INSTANCES(CLASS) do {} while (0) - #define GET_INSTANCE_COUNT(CLASS) ERROR_ONLY_FOR_DEBUG - #define DECLARE_INSTANCE_TRACKING(CLASS) - #define IMPLEMENT_INSTANCE_TRACKING(CLASS) - - INLINE void kdbg_init(void) { /* nop */ } - INLINE void kputchar(UNUSED_ARG(char, c)) { /* nop */ } - INLINE int kputnum(UNUSED_ARG(int, num)) { return 0; } - INLINE void kputs(UNUSED_ARG(const char *, str)) { /* nop */ } - INLINE void kdump(UNUSED_ARG(const void *, buf), UNUSED_ARG(size_t, len)) { /* nop */ } - - #if defined(__cplusplus) && COMPILER_VARIADIC_MACROS - /* G++ can't inline functions with variable arguments... */ - #define kprintf(fmt,...) do { (void)(fmt); } while(0) - #else - /* ...but GCC can. */ - INLINE void kprintf(UNUSED_ARG(const char *, fmt), ...) { /* nop */ } - #endif - -#endif /* _DEBUG */ - -#endif /* DEVLIB_DEBUG_H */ diff --git a/cfg/macros.h b/cfg/macros.h deleted file mode 100644 index 1006fc42..00000000 --- a/cfg/macros.h +++ /dev/null @@ -1,336 +0,0 @@ -/** - * \file - * - * - * \brief Common and handy function macros - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Giovanni Bajo - */ -#ifndef CFG_MACROS_H -#define CFG_MACROS_H - -#include - -/* avr-gcc does not seem to support libstdc++ */ -#if defined(__cplusplus) && !CPU_AVR - /* Type-generic macros implemented with template functions. */ - #include - - template inline T ABS(T n) { return n >= 0 ? n : -n; } - #define MIN(a,b) std::min(a, b) - #define MAX(a,b) std::max(a, b) - #define SWAP(a,b) std::swap(a, b) -#elif (COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) - /* Type-generic macros implemented with statement expressions. */ - #define ABS(n) ({ \ - typeof(n) _n = (n); \ - (_n < 0) ? -_n : _n; \ - }) - #define MIN(a,b) ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - ASSERT_TYPE_EQUAL(_a, _b); \ - /** \ - * The (typeof(_a)) cast in necessary: \ - * result type of conditional expressions is \ - * *NOT* the type of the value returned but \ - * the type that would be produced if _a and _b \ - * were mixed in an expression. \ - * Even in _a and _b are of the same type, \ - * if mixed in an expression the type will be \ - * promoted to int! \ - */ \ - ((typeof(_a))((_a < _b) ? _a : _b)); \ - }) - #define MAX(a,b) ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - ASSERT_TYPE_EQUAL(_a, _b); \ - /** \ - * The (typeof(_a)) cast in necessary: \ - * result type of conditional expressions is \ - * *NOT* the type of the value returned but \ - * the type that would be produced if _a and _b \ - * were mixed in an expression. \ - * Even in _a and _b are of the same type, \ - * if mixed in an expression the type will be \ - * promoted to int! \ - */ \ - ((typeof(_a))((_a > _b) ? _a : _b)); \ - }) -#else /* !(COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) */ - /* Buggy macros for inferior compilers. */ - #define ABS(a) (((a) < 0) ? -(a) : (a)) - #define MIN(a,b) (((a) < (b)) ? (a) : (b)) - #define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif /* !(COMPILER_STATEMENT_EXPRESSIONS && COMPILER_TYPEOF) */ - -/** Bound \a x between \a min and \a max. */ -#define MINMAX(min,x,max) (MIN(MAX(min, x), max)) - -#ifdef __cplusplus - /* Use standard implementation from */ - #define SWAP(a,b) std::swap(a, b) -#elif COMPILER_TYPEOF - /** - * Type-generic macro to swap \a a with \a b. - * - * \note Arguments are evaluated multiple times. - */ - #define SWAP(a, b) \ - do { \ - typeof(a) tmp; \ - ASSERT_TYPE_EQUAL(a, b); \ - tmp = (a); \ - (a) = (b); \ - (b) = tmp; \ - } while (0) -#else /* !COMPILER_TYPEOF */ - /* Sub-optimal implementation that only works with integral types. */ - #define SWAP(a, b) \ - do { \ - (a) ^= (b); \ - (b) ^= (a); \ - (a) ^= (b); \ - } while (0) - -#endif /* COMPILER_TYPEOF */ - -/** - * Macro to swap \a a with \a b, with explicit type \a T for dumb C89 compilers. - * - * \note Arguments are evaluated multiple times. - */ -#define SWAP_T(a, b, T) \ - do { \ - T tmp; \ - ASSERT_TYPE_IS(a, T); \ - ASSERT_TYPE_IS(b, T); \ - tmp = (a); \ - (a) = (b); \ - (b) = tmp; \ - } while (0) - - -#ifndef BV - /** Convert a bit value to a binary flag. */ - #define BV(x) (1<<(x)) -#endif - -/** Same as BV() but with 32 bit result */ -#define BV32(x) ((uint32_t)1<<(x)) - -/** Same as BV() but with 16 bit result */ -#define BV16(x) ((uint16_t)1<<(x)) - -/** Same as BV() but with 8 bit result */ -#define BV8(x) ((uint8_t)1<<(x)) - -/** - * Perform an integer division rounding the result to the nearest int value. - * \note \a divisor should preferibly be a costant, otherwise this macro generates - * 2 division. Also divisor is evaluated twice. - */ -#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor)) - -/** Round up \a x to an even multiple of the 2's power \a pad. */ -#define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1)) - -/* OBSOLETE */ -#define ROUND2 ROUND_UP2 - -/** - * \name Integer round macros. - * - * Round \a x to a multiple of \a base. - * \note If \a x is signed these macros generate a lot of code. - * \{ - */ -#define ROUND_DOWN(x, base) ( (x) - ((x) % (base)) ) -#define ROUND_UP(x, base) ( ((x) + (base) - 1) - (((x) + (base) - 1) % (base)) ) -#define ROUND_NEAREST(x, base) ( ((x) + (base) / 2) - (((x) + (base) / 2) % (base)) ) -/* \} */ - -/** Check if \a x is an integer power of 2. */ -#define IS_POW2(x) (!(bool)((x) & ((x)-1))) - -/** Calculate a compile-time log2 for a uint8_t */ -#define UINT8_LOG2(x) \ - ((x) < 2 ? 0 : \ - ((x) < 4 ? 1 : \ - ((x) < 8 ? 2 : \ - ((x) < 16 ? 3 : \ - ((x) < 32 ? 4 : \ - ((x) < 64 ? 5 : \ - ((x) < 128 ? 6 : 7))))))) - -/** Calculate a compile-time log2 for a uint16_t */ -#define UINT16_LOG2(x) \ - ((x < 256) ? UINT8_LOG2(x) : UINT8_LOG2((x) >> 8) + 8) - -/** Calculate a compile-time log2 for a uint32_t */ -#define UINT32_LOG2(x) \ - ((x < 65536UL) ? UINT16_LOG2(x) : UINT16_LOG2((x) >> 16) + 16) - -#if COMPILER_VARIADIC_MACROS - /** Count the number of arguments (up to 16). */ - #define PP_COUNT(...) \ - PP_COUNT__(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) - #define PP_COUNT__(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,count,...) \ - count -#endif - -#if COMPILER_VARIADIC_MACROS - /** - * \def BIT_CHANGE(reg, (mask, value), ...) - * - * This macro allows for efficient and compact bit toggling in a hardware - * register. It is meant to replace hand-coded cruft which toggles bits - * in sequence. - * - * It is possible to specify an unlimited pair of (mask, value) parameters. - * For instance: - * - * \code - * void set_timer(bool start) - * { - * BIT_CHANGE(REG_CTRL_TIMER, - * (TIMER_MODE, MODE_COUNT), - * (OVL_IRQ, 1), - * (CMP_IRQ, 1), - * (START, start) - * ); - * } - * \endcode - * - * The macro expansion will be roughly the following: - * - * \code - * REG_CTRL_TIMER = (REG_CTRL_TIMER & ~(TIMER_MODE|OVL_IRQ|CMP_IRQ|START) - * | (MODE_COUNT|OVL_IRQ|CMP_IRQ|(start ? START : 0)); - * \endcode - * - * It is up to the compiler to produce the optimal code. We checked that GCC produces - * the best code in most cases. We preferred this expansion over the use of a block - * with a local variable because CodeWarrior 6.1 was not able to remove completely the - * allocation of the local from the stack. - * - * \note This macro is available only in C99 because it makes use of variadic macros. - * It would be possible to make up an implementation with a slightly different syntax - * for use with C90 compilers, through Boost Preprocessor. - */ - - /** - * \def BIT_CHANGE_BV(reg, (bit, value), ...) - * - * Similar to BIT_CHANGE(), but get bits instead of masks (and applies BV() to convert - * them to masks). - */ - - #define BIT_EXTRACT_FLAG_0(bit, value) bit - #define BIT_EXTRACT_FLAG_1(bit, value) BV(bit) - #define BIT_EXTRACT_VALUE__(bit, value) value - - #define BIT_MASK_SINGLE__(use_bv, index, max, arg) \ - ((index < max) ? (PP_CAT(BIT_EXTRACT_FLAG_, use_bv) arg) : 0) \ - /**/ - - #define BIT_MASK_IF_SINGLE__(use_bv, index, max, arg) \ - (((index < max) && (BIT_EXTRACT_VALUE__ arg)) ? (PP_CAT(BIT_EXTRACT_FLAG_, use_bv) arg) : 0) \ - /**/ - - #define BIT_ITER__2(macro, use_bv, max, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, ...) \ - (macro(use_bv, 0, max, a0) | \ - macro(use_bv, 1, max, a1) | \ - macro(use_bv, 2, max, a2) | \ - macro(use_bv, 3, max, a3) | \ - macro(use_bv, 4, max, a4) | \ - macro(use_bv, 5, max, a5) | \ - macro(use_bv, 6, max, a6) | \ - macro(use_bv, 7, max, a7) | \ - macro(use_bv, 8, max, a8) | \ - macro(use_bv, 9, max, a9) | \ - macro(use_bv, 10, max, a10) | \ - macro(use_bv, 11, max, a11) | \ - macro(use_bv, 12, max, a12) | \ - macro(use_bv, 13, max, a13) | \ - macro(use_bv, 14, max, a14) | \ - macro(use_bv, 15, max, a15)) \ - /**/ - - #define BIT_ITER__(macro, use_bv, ...) \ - BIT_ITER__2(macro, use_bv, PP_COUNT(__VA_ARGS__), __VA_ARGS__, (0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1)) \ - /**/ - - #define BIT_MASKS__(use_bv, ...) \ - BIT_ITER__(BIT_MASK_SINGLE__, use_bv, __VA_ARGS__) - /**/ - - #define BIT_MASKS_CONDITIONAL__(use_bv, ...) \ - BIT_ITER__(BIT_MASK_IF_SINGLE__, use_bv, __VA_ARGS__) - /**/ - - #define BIT_CHANGE__(reg, use_bv, ...) \ - ((reg) = ((reg) & ~BIT_MASKS__(use_bv, __VA_ARGS__)) | BIT_MASKS_CONDITIONAL__(use_bv, __VA_ARGS__)) \ - /**/ - - #define BIT_CHANGE(reg, ...) BIT_CHANGE__(reg, 0, __VA_ARGS__) - #define BIT_CHANGE_BV(reg, ...) BIT_CHANGE__(reg, 1, __VA_ARGS__) - -#endif /* COMPILER_VARIADIC_MACROS */ - -/** - * Macro for rotating bit left or right. - * \{ - */ -#define ROTR(var, rot) (((var) >> (rot)) | ((var) << ((sizeof(var) * 8) - (rot)))) -#define ROTL(var, rot) (((var) << (rot)) | ((var) >> ((sizeof(var) * 8) - (rot)))) -/*\}*/ - -/** - * Make an id from 4 letters, useful for - * file formats and kfile ids. - */ -#define MAKE_ID(a,b,c,d) \ - ( ((uint32_t)(a) << 24) \ - | ((uint32_t)(b) << 16) \ - | ((uint32_t)(c) << 8) \ - | ((uint32_t)(d) << 0) ) - -/** - * Type for id generated by MAKE_ID(). - */ -typedef uint32_t id_t; - -#endif /* MACROS_H */ - diff --git a/cfg/module.h b/cfg/module.h deleted file mode 100644 index 8ada81a1..00000000 --- a/cfg/module.h +++ /dev/null @@ -1,124 +0,0 @@ -/** - * \file - * - * - * \brief Debug macros for inter-module dependency checking. - * - * These macros expand to nothing in release builds. In debug - * builds, they perform run-time dependency checks for modules. - * - * The usage pattern looks like this: - * - * \code - * MOD_DEFINE(phaser) - * - * void phaser_init(void) - * { - * MOD_CHECK(computer); - * MOD_CHECK(warp_core); - * - * [...charge weapons...] - * - * MOD_INIT(phaser); - * } - * - * void phaser_cleanup(void) - * { - * MOD_CLEANUP(phaser); - * - * [...disarm phaser...] - * } - * \endcode - * - * \version $Id$ - * \author Bernardo Innocenti - */ -#ifndef CFG_MODULE_H -#define CFG_MODULE_H - -#include - -/** - * Declare a global variable for module dependency check. - * - * \see MOD_INIT(), MOD_CHECK() - */ -#define MOD_DEFINE(module) DB(extern bool module ## _initialized; bool module ## _initialized;) - -/** - * Check that \a module was already initialized. - * - * Put this check just before accessing any facility - * provided by a module that requires prior initialization. - * - * \see MOD_INIT() - */ - -#define MOD_CHECK(module) \ -do { \ - DB(extern bool module ## _initialized;) \ - ASSERT(module ## _initialized); \ -} while (0) - -/** - * Mark module as initialized. - * - * Marking initialization requires the global data - * previously defined by MOD_DEFINE(). - * - * To prevent double initialization bugs, an initialized - * module must first be cleaned up with MOD_CLEANUP() before - * calling MOD_INIT() another time. - * - * \see MOD_CLEANUP(), MOD_CHECK(), MOD_DEFINE() - */ -#define MOD_INIT(module) \ -do { \ - ASSERT(!module ## _initialized); \ - DB(module ## _initialized = true;) \ -} while (0) - -/** - * Mark module as being no longer initialized. - * - * Marking initialization requires the global data - * previously defined by MOD_DEFINE(). - * - * \see MOD_INIT(), MOD_CHECK(), MOD_DEFINE() - */ -#define MOD_CLEANUP(module) \ -do { \ - ASSERT(module ## _initialized); \ - DB(module ## _initialized = false;) \ -} while (0) - -#endif /* CFG_MODULE_H */ - diff --git a/cfg/os.h b/cfg/os.h deleted file mode 100644 index 924daade..00000000 --- a/cfg/os.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * \file - * - * - * \brief OS-specific definitions - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#ifndef DEVLIB_OS_H -#define DEVLIB_OS_H - -/** Macro to include OS-specific versions of the headers. */ -#define OS_HEADER(module) PP_STRINGIZE(PP_CAT3(module, _, OS_ID).h) -#define OS_CSOURCE(module) PP_STRINGIZE(PP_CAT3(module, _, OS_ID).c) - -/* - * OS autodetection (Some systems trigger multiple OS definitions) - */ -#ifdef _WIN32 - #define OS_WIN32 1 - #define OS_ID win32 - - // FIXME: Maybe disable Win32 exceptions? - typedef int cpuflags_t; - #define IRQ_DISABLE /* FIXME */ - #define IRQ_ENABLE /* FIXME */ - #define IRQ_SAVE_DISABLE(old_sigs) /* FIXME */ - #define IRQ_RESTORE(old_sigs) /* FIXME */ - -#else - #define OS_WIN32 0 -#endif - -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - #define OS_UNIX 1 - #define OS_POSIX 1 /* Not strictly UNIX, but no way to autodetect it. */ - #define OS_ID posix - - /* - * The POSIX moral equivalent of disabling IRQs is disabling signals. - */ - #include - typedef sigset_t cpuflags_t; - - #define SET_ALL_SIGNALS(sigs) \ - do { \ - sigfillset(&sigs); \ - sigdelset(&sigs, SIGINT); \ - sigdelset(&sigs, SIGSTOP); \ - sigdelset(&sigs, SIGCONT); \ - } while(0) - - #define IRQ_DISABLE \ - do { \ - sigset_t sigs; \ - SET_ALL_SIGNALS(sigs); \ - sigprocmask(SIG_BLOCK, &sigs, NULL); \ - } while (0) - - #define IRQ_ENABLE \ - do { \ - sigset_t sigs; \ - SET_ALL_SIGNALS(sigs); \ - sigprocmask(SIG_UNBLOCK, &sigs, NULL); \ - } while (0) - - #define IRQ_SAVE_DISABLE(old_sigs) \ - do { \ - sigset_t sigs; \ - SET_ALL_SIGNALS(sigs); \ - sigprocmask(SIG_BLOCK, &sigs, &old_sigs); \ - } while (0) - - #define IRQ_RESTORE(old_sigs) \ - do { \ - sigprocmask(SIG_SETMASK, &old_sigs, NULL); \ - } while (0) - - #define IRQ_ENABLED() \ - ({ \ - sigset_t sigs; \ - sigprocmask(SIG_SETMASK, NULL, &sigs); \ - sigismember(&sigs, SIGALRM) ? false : true; \ - }) - -#else - #define OS_UNIX 0 - #define OS_POSIX 0 -#endif - -#ifdef __linux__ - #define OS_LINUX 1 -#else - #define OS_LINUX 0 -#endif - -#if defined(__APPLE__) && defined(__MACH__) - #define OS_DARWIN 1 -#else - #define OS_DARWIN 0 -#endif - -/* - * We want Qt and other frameworks to look like OSes because you would - * tipically want their portable abstractions if you're using one of these. - */ -#if defined(_QT) - #define OS_QT 1 - #undef OS_ID - #define OS_ID qt -#else - #define OS_QT 0 -#endif - -/* - * Summarize hosted environments as OS_HOSTED and embedded - * environment with OS_EMBEDDED. - */ -#if OS_WIN32 || OS_UNIX || OS_DARWIN || OS_QT - #define OS_HOSTED 1 - #define OS_EMBEDDED 0 -#else - #define OS_HOSTED 0 - #define OS_EMBEDDED 1 - - /* Embedded environments fall back to CPU-specific code. */ - #define OS_ID CPU_ID -#endif - -/* Self-check for the detection */ -#if !defined(OS_ID) - #error OS_ID not defined -#endif -#if OS_HOSTED && OS_EMBEDDED - #error Both hosted and embedded OS environment -#endif -#if !OS_HOSTED && !OS_EMBEDDED - #error Neither hosted nor embedded OS environment -#endif - -#endif /* DEVLIB_OS_H */ diff --git a/config.mk b/config.mk deleted file mode 100644 index 5ace0dbd..00000000 --- a/config.mk +++ /dev/null @@ -1,122 +0,0 @@ -# -# $Id$ -# Copyright 2002,2003, 2004, 2006 Develer S.r.l. (http://www.develer.com/) -# All rights reserved. -# -# Author: Bernardo Innocenti -# Based on: GCC-AVR standard Makefile part 1, Volker Oth 1/2000 -# - -# -# Programmer type -# see local pgm_config.mk for programmer customization. --include pgm_config.mk -DPROG ?= -V -c stk500 -P /dev/ttyS0 - -# Set to 1 to build for embedded devices. -# e.g. produce target.elf instead of target and target_nostrip -EMBEDDED_TARGET = 1 -#EMBEDDED_TARGET = 0 - -OPTCFLAGS = -ffunction-sections -fdata-sections -#OPTCFLAGS = -funsafe-loop-optimizations - -# For AVRStudio -#DEBUGCFLAGS = -gdwarf-2 - -# For GDB -DEBUGCFLAGS = -ggdb - -# -# define some variables based on the AVR base path in $(AVR) -# -#CROSS = avr- -CC = gcc -CXX = g++ -AS = $(CC) -x assembler-with-cpp -LD = $(CC) -LDXX = $(CXX) -OBJCOPY = objcopy -STRIP = strip -INSTALL = cp -a -RM = rm -f -RM_R = rm -rf -RN = mv -MKDIR_P = mkdir -p -SHELL = /bin/sh -CHECKER = sparse -DOXYGEN = doxygen -AVRDUDE = avrdude -MOC = moc-qt4 -FLEXCAT = $(top_srcdir)/tools/flexcat/flexcat - -# For conversion from ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. -COFFCONVERT=$(OBJCOPY) \ - --debugging \ - --change-section-address .data-0x800000 \ - --change-section-address .bss-0x800000 \ - --change-section-address .noinit-0x800000 \ - --change-section-address .eeprom-0x810000 - -INCDIR = -I. -Ihw -LIBDIR = lib -OBJDIR = obj -OUTDIR = images - -# output format can be srec, ihex (avrobj is always created) -FORMAT = srec -#FORMAT = ihex - -# Compiler flags for generating dependencies -DEP_FLAGS = -MMD -MP - -# Compiler flags for generating source listings -LIST_FLAGS = -Wa,-anhlmsd=$(@:.o=.lst) - -# Linker flags for generating map files -ifeq ($(EMBEDDED_TARGET), 1) -MAP_FLAGS = -Wl,-Map=$(@:%.elf=%.map),--cref -else -MAP_FLAGS = -endif - -# Compiler warning flags for both C and C++ -WARNFLAGS = \ - -W -Wformat -Wall -Wundef -Wpointer-arith -Wcast-qual \ - -Wcast-align -Wwrite-strings -Wsign-compare \ - -Wmissing-noreturn \ - -Wextra -Wstrict-aliasing=2 \ -# -Wunsafe-loop-optimizations - -# Compiler warning flags for C only -C_WARNFLAGS = \ - -Wmissing-prototypes -Wstrict-prototypes - -# Default C preprocessor flags (for C, C++ and cpp+as) -CPPFLAGS = $(INCDIR) - -# Default C compiler flags -CFLAGS = $(OPTCFLAGS) $(DEBUGCFLAGS) $(WARNFLAGS) $(C_WARNFLAGS) \ - $(DEP_FLAGS) $(LIST_FLAGS) -std=gnu99 - -# Default C++ compiler flags -CXXFLAGS = $(OPTCFLAGS) $(DEBUGCFLAGS) $(WARNFLAGS) \ - $(DEP_FLAGS) $(LIST_FLAGS) - -# Default compiler assembly flags -CPPAFLAGS = $(DEBUGCFLAGS) -MMD - -# Default assembler flags -ASFLAGS = $(DEBUGCFLAGS) - -# Default linker flags -#LDFLAGS = $(MAP_FLAGS) - -#bernie: does not complain for missing symbols! -LDFLAGS = $(MAP_FLAGS) -Wl,--gc-sections - -# Flags for avrdude -AVRDUDEFLAGS = $(DPROG) - -# additional libs -LIB = -lm diff --git a/config_kern.h b/config_kern.h deleted file mode 100644 index c703b4de..00000000 --- a/config_kern.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * \file - * - * - * \brief Kernel configuration parameters - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.8 2006/07/19 12:56:24 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.7 2006/02/21 16:05:53 bernie - *#* Move from cfg/ to top-level. - *#* - *#* Revision 1.3 2005/11/04 16:20:01 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.2 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.1 2005/04/11 19:04:13 bernie - *#* Move top-level headers to cfg/ subdir. - *#* - *#* Revision 1.5 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.4 2004/08/24 16:19:38 bernie - *#* Add missing header. - *#* - *#* Revision 1.3 2004/07/30 14:24:16 rasky - *#* Task switching con salvataggio perfetto stato di interrupt (SR) - *#* Kernel monitor per dump informazioni su stack dei processi - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 17:48:35 bernie - *#* Add top-level files. - *#* - *#*/ -#ifndef CONFIG_KERN_H -#define CONFIG_KERN_H - -#include /* ARCH_EMUL */ - -/** - * \name Modules activation - * - * \{ - */ -/* Module/option Active Dependencies */ -#define CONFIG_KERN_SCHED (1) -#define CONFIG_KERN_SIGNALS (1 && CONFIG_KERN_SCHED) -#define CONFIG_KERN_TIMER (1) -#define CONFIG_KERN_HEAP (0) -#define CONFIG_KERN_SEMAPHORES (0 && CONFIG_KERN_SIGNALS) -#define CONFIG_KERN_MONITOR (1 && CONFIG_KERN_SCHED) -/*\}*/ - -/* EXPERIMENTAL */ -#define CONFIG_KERN_PREEMPTIVE (0 && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER) - -#define CONFIG_KERN_QUANTUM 50 /**< Time sharing quantum in timer ticks. */ - -#if (ARCH & ARCH_EMUL) - /* We need a large stack because system libraries are bloated */ - #define CONFIG_PROC_DEFSTACKSIZE 65536 -#else - /** - * Default stack size for each thread, in bytes. - * - * The goal here is to allow a minimal task to save all of its - * registers twice, plus push a maximum of 32 variables on the - * stack. - * - * The actual size computed by the default formula is: - * AVR: 102 - * i386: 156 - * ARM: 164 - * x86_64: 184 - * - * Note that on most 16bit architectures, interrupts will also - * run on the stack of the currently running process. Nested - * interrupts will greatly increases the amount of stack space - * required per process. Use irqmanager to minimize stack - * usage. - */ - #define CONFIG_PROC_DEFSTACKSIZE \ - (CPU_SAVED_REGS_CNT * 2 * sizeof(cpustack_t) \ - + 32 * sizeof(int)) -#endif - -/* OBSOLETE */ -#define CONFIG_KERN_DEFSTACKSIZE CONFIG_PROC_DEFSTACKSIZE - -/* Memory fill codes to help debugging */ -#if CONFIG_KERN_MONITOR - #include - #if (SIZEOF_CPUSTACK_T == 1) - /* 8bit cpustack_t */ - #define CONFIG_KERN_STACKFILLCODE 0xA5 - #define CONFIG_KERN_MEMFILLCODE 0xDB - #elif (SIZEOF_CPUSTACK_T == 2) - /* 16bit cpustack_t */ - #define CONFIG_KERN_STACKFILLCODE 0xA5A5 - #define CONFIG_KERN_MEMFILLCODE 0xDBDB - #elif (SIZEOF_CPUSTACK_T == 4) - /* 16bit cpustack_t */ - #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5UL - #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBUL - #elif (SIZEOF_CPUSTACK_T == 8) - /* 16bit cpustack_t */ - #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5A5A5A5A5UL - #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBDBDBDBDBUL - #else - #error No cpustack_t size supported! - #endif -#endif - - -#endif /* CONFIG_KERN_H */ diff --git a/doc/TracFooter.html b/doc/TracFooter.html deleted file mode 100644 index 139597f9..00000000 --- a/doc/TracFooter.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/doc/TracHeader.html b/doc/TracHeader.html deleted file mode 100644 index 139597f9..00000000 --- a/doc/TracHeader.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/drv/adc.c b/drv/adc.c deleted file mode 100644 index 7fbf7f2c..00000000 --- a/drv/adc.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief ADC driver (implementation) - * - * \version $Id$ - * \author Francesco Sacchi - */ - - -#include -#include - -#include CPU_CSOURCE(adc) - -#include // ASSERT() -#include // MIN() -#include -#include - -/** - * Read the ADC channel \a ch. - */ -adcread_t adc_read(adc_ch_t ch) -{ - ASSERT(ch <= (adc_ch_t)ADC_MUX_MAXCH); - ch = MIN(ch, (adc_ch_t)ADC_MUX_MAXCH); - - adc_hw_select_ch(ch); - - return(adc_hw_read()); -} - -MOD_DEFINE(adc); - -/** - * Initialize the ADC hardware. - */ -void adc_init(void) -{ - adc_hw_init(); - - MOD_INIT(adc); -} diff --git a/drv/adc.h b/drv/adc.h deleted file mode 100644 index 91f1ebd6..00000000 --- a/drv/adc.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief ADC driver (interface) - * - * \version $Id$ - * \author Francesco Sacchi - */ - - -#ifndef DRV_ADC_H -#define DRV_ADC_H - -#include -#include -#include -#include CPU_HEADER(adc) - -/** Type for ADC return value. */ -typedef uint16_t adcread_t; - -/** Type for channel */ -typedef uint8_t adc_ch_t; - -#define adc_bits() ADC_BITS - -adcread_t adc_read(adc_ch_t ch); -void adc_init(void); - -/** - * Macro used to convert data from adc range (0...(2 ^ADC_BITS - 1)) to - * \a y1 ... \a y2 range. - * \note \a y1, \a y2 can be negative, and put in ascending or descending order as well. - * \note \a data and \a y2 are evaluated only once, \a y1 twice. - */ -#define ADC_RANGECONV(data, y1, y2) ((((data) * ((y2) - (y1))) / ((1 << ADC_BITS) - 1)) + (y1)) - -#endif /* DRV_ADC_H */ diff --git a/drv/buzzer.c b/drv/buzzer.c deleted file mode 100644 index 63cbc4a8..00000000 --- a/drv/buzzer.c +++ /dev/null @@ -1,197 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Buzzer driver (implementation) - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.19 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.18 2006/02/17 21:15:25 bernie - *#* Add MOD_CHECK() checks. - *#* - *#* Revision 1.17 2006/02/10 12:30:18 bernie - *#* Push interrupt protection inside hw module. - *#* - *#* Revision 1.16 2005/11/04 16:19:33 bernie - *#* buz_init(): Restore IRQ protection as in project_bko. - *#* - *#* Revision 1.15 2005/06/27 21:25:50 bernie - *#* Modularize hardware access; Port to new timer interface. - *#* - *#* Revision 1.14 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.13 2005/02/18 11:20:15 bernie - *#* Use mware/event.h; Update copyright info. - *#* - *#* Revision 1.12 2004/12/13 12:07:06 bernie - *#* DISABLE_IRQSAVE/ENABLE_IRQRESTORE: Convert to IRQ_SAVE_DISABLE/IRQ_RESTORE. - *#* - *#* Revision 1.11 2004/12/08 09:11:53 bernie - *#* Rename time_t to mtime_t. - *#* - *#* Revision 1.10 2004/10/03 18:38:51 bernie - *#* Add missing AVR header; Fix header. - *#* - *#* Revision 1.9 2004/09/14 21:01:25 bernie - *#* Use new AVR port pin names. - *#*/ - -#include "buzzer.h" - -#include -#include - -#include - -#include -#include - - -/* Local vars */ -static Timer buz_timer; -static bool buz_timer_running; -static mtime_t buz_repeat_interval; -static mtime_t buz_repeat_duration; - - -/** - * Turn off buzzer, called by software timer - */ -static void buz_softint(void) -{ - if (IS_BUZZER_ON) - { - BUZZER_OFF; - if (buz_repeat_interval) - { - /* Wait for interval time */ - timer_setDelay(&buz_timer, ms_to_ticks(buz_repeat_interval)); - timer_add(&buz_timer); - } - else - buz_timer_running = false; - } - else if (buz_repeat_interval) - { - /* Wait for beep time */ - BUZZER_ON; - timer_setDelay(&buz_timer, ms_to_ticks(buz_repeat_duration)); - timer_add(&buz_timer); - } - else - buz_timer_running = false; -} - - -/** - * Beep for the specified ms time - */ -void buz_beep(mtime_t time) -{ - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - /* Remove the software interrupt if it was already queued */ - if (buz_timer_running) - timer_abort(&buz_timer); - - /* Turn on buzzer */ - BUZZER_ON; - - /* Add software interrupt to turn the buzzer off later */ - buz_timer_running = true; - timer_setDelay(&buz_timer, ms_to_ticks(time)); - timer_add(&buz_timer); - - IRQ_RESTORE(flags); -} - - -/** - * Start buzzer repetition - */ -void buz_repeat_start(mtime_t duration, mtime_t interval) -{ - buz_repeat_interval = interval; - buz_repeat_duration = duration; - buz_beep(duration); -} - - -/** - * Stop buzzer repetition - */ -void buz_repeat_stop(void) -{ - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - /* Remove the software interrupt if it was already queued */ - if (buz_timer_running) - { - timer_abort(&buz_timer); - buz_timer_running = false; - } - - buz_repeat_interval = 0; - BUZZER_OFF; - - IRQ_RESTORE(flags); -} - -MOD_DEFINE(buzzer) - -/** - * Initialize buzzer. - */ -void buz_init(void) -{ - MOD_CHECK(timer); - - BUZZER_HW_INIT; - - /* Init software interrupt. */ - timer_set_event_softint(&buz_timer, (Hook)buz_softint, 0); - - MOD_INIT(buzzer); -} diff --git a/drv/buzzer.h b/drv/buzzer.h deleted file mode 100644 index 7d8837c1..00000000 --- a/drv/buzzer.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Buzzer driver - */ - -/*#* - *#* $Log$ - *#* Revision 1.10 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.9 2005/11/27 23:32:15 bernie - *#* Update copyright information. - *#* - *#* Revision 1.8 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.7 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.6 2004/12/08 09:11:53 bernie - *#* Rename time_t to mtime_t. - *#* - *#* Revision 1.5 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.4 2004/08/24 16:53:43 bernie - *#* Add missing headers. - *#* - *#* Revision 1.3 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.2 2004/05/23 18:21:53 bernie - *#* Trim CVS logs and cleanup header info. - *#* - *#*/ -#ifndef DRV_BUZZER_H -#define DRV_BUZZER_H - -#include - -extern void buz_init(void); -extern void buz_beep(mtime_t time); -extern void buz_repeat_start(mtime_t duration, mtime_t interval); -extern void buz_repeat_stop(void); - -#endif /* DRV_BUZZER_H */ diff --git a/drv/buzzerled.c b/drv/buzzerled.c deleted file mode 100644 index 7ce6f53c..00000000 --- a/drv/buzzerled.c +++ /dev/null @@ -1,123 +0,0 @@ -/** - * \file - * - * - * \brief Generic library to handle buzzers and leds - * - * This library is divided into three different layers: - * - * - The topmost portable layer is buzzerled.[ch] which exposes a common API - * enable/disable the devices. Basically, it handles the asynchronism to - * implement bld_beep and bld_repeat. - * - The middle layer is CPU-specific and exposes a single main function which - * turns on/off each device. - * - The lower layer is board-specific and communicates with the middle layer - * with any required API. The idea is that devices can be tied to the CPU in - * many different ways (many different pins), so this part should describe - * which devices are present, and how they are connected. - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.5 2004/12/08 09:43:41 bernie - *#* Add a todo item. - *#* - *#* Revision 1.4 2004/08/25 14:12:08 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.3 2004/07/14 14:04:29 rasky - *#* Merge da SC: spostata bld_set inline perché si ottimizza parecchio tramite propagazione di costanti - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 18:36:05 bernie - *#* Import buzzerled driver. - *#* - *#*/ - -#include "buzzerled.h" -#include "timer.h" - -static struct Timer timers[NUM_BLDS]; -static bool timer_go[NUM_BLDS]; - -INLINE enum BLD_DEVICE hook_parm_to_device(void* parm) -{ - struct Timer* t = (struct Timer*)parm; - int num_bld = t - &timers[0]; - - ASSERT(num_bld >= 0); - ASSERT(num_bld < NUM_BLDS); - - return (enum BLD_DEVICE)num_bld; -} - -static void hook_turn_off(void* parm) -{ - enum BLD_DEVICE num_bld = hook_parm_to_device(parm); - bld_set(num_bld, false); -} - -void bld_init(void) -{ - bld_hw_init(); -} - -void bld_beep(enum BLD_DEVICE device, uint16_t duration) -{ - // \todo This is not reentrant for the same device. FIXME! - struct Timer *t = &timers[device]; - timer_set_delay(t, duration); - timer_set_event_softint(t, hook_turn_off, t); - timer_add(t); - - bld_set(device, true); -} - -void bld_beep_and_wait(enum BLD_DEVICE device, uint16_t duration) -{ - bld_set(device, true); - timer_delay(duration); - bld_set(device, false); -} - diff --git a/drv/buzzerled.h b/drv/buzzerled.h deleted file mode 100644 index 14fab030..00000000 --- a/drv/buzzerled.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * \file - * - * - * \brief Generic library to handle buzzers and leds - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -#ifndef DRV_BUZZERLED_H -#define DRV_BUZZERLED_H - -#include - -/** Include hw.h. We expect hw.h to define enum BLD_DEVICE, which must contain - * an enumarator for each device, plus a special symbol NUM_BLDS containing the - * number of devices. - */ -#include - - -/* Include hw-level implementation. This allows inlining of bld_set, which in turns - * should allow fast constant propagation for the common case (where the parameter - * device is a constant). - */ -#include CPU_HEADER(buzzerled) - - -/** Initialize the buzzerled library. - * - * \note This function must be called before any other function in the library. - */ -void bld_init(void); - - -/** Set or reset a device. - * - * \param device Device to be set - * \param enable Enable/disable status - */ -#define bld_set(device, enable) bld_hw_set(device, enable) - - -/** Enable a device for a certain interval of time - * - * \param device Device to be enabled - * \param duration Number of milliseconds the device must be enabled - * - * \note This function is non-blocking, so it will return immediately. - */ -void bld_beep(enum BLD_DEVICE device, uint16_t duration); - - -/** Enable a device for a certain interval of time and wait. - * - * \param device Device to be enabled - * \param duration Number of milliseconds the device must be enabled - * - * \note This function is blocking, so it will return after the specified period of time. - */ -void bld_beep_and_wait(enum BLD_DEVICE device, uint16_t duration); - -#endif /* DRV_BUZZERLED_H */ diff --git a/drv/dataflash.c b/drv/dataflash.c deleted file mode 100644 index d9392f9a..00000000 --- a/drv/dataflash.c +++ /dev/null @@ -1,494 +0,0 @@ -/** - * \file - * - * - * \brief Function library for AT45DBXX Data Flash memory. - * - * - * \version $Id: dataflash.c 20677 2008-02-19 14:29:52Z batt $ - * \author Daniele Basile - * \author Francesco Sacchi - */ - -#include "dataflash.h" -#include - -#include -#include -#include -#include -#include - -#if CONFIG_KERNEL -#include -#endif - -#include - -/** - * Array used to describe dataflash memory devices currently supported. - */ -static const DataflashInfo mem_info[] = -{ - { - /* AT45DB041B */ - .density_id = 0x07, - .page_size = 264, - .page_bits = 9, - .page_cnt = 2048, - .read_cmd = DFO_READ_FLASH_MEM_BYTE_B, - }, - { - /* AT45DB081D */ - .density_id = 0x09, - .page_size = 264, - .page_bits = 9, - .page_cnt = 4096, - .read_cmd = DFO_READ_FLASH_MEM_BYTE_D, - }, - { - /* AT45DB161D */ - .density_id = 0x0B, - .page_size = 528, - .page_bits = 10, - .page_cnt = 4096, - .read_cmd = DFO_READ_FLASH_MEM_BYTE_D, - }, - /* Add other memories here */ -}; - -STATIC_ASSERT(countof(mem_info) == DFT_CNT); - -/** - * Macro that toggle CS of dataflash. - * \note This is equivalent to fd->setCS(false) immediately followed by fd->setCS(true). - */ -INLINE void CS_TOGGLE(KFileDataflash *fd) -{ - fd->setCS(false); - fd->setCS(true); -} - -/** - * Send a generic command to dataflash memory. - * This function send only 4 byte: opcode, page address and - * byte address. - */ -static void send_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode) -{ - - /* - * Make sure to toggle CS signal in order, - * and reset dataflash command decoder. - */ - CS_TOGGLE(fd); - - - /* - * To send one command to data flash memory, we send 4 byte. - * First byte is opcode command, second and third byte are - * page address, in last byte we write a byte page address. - * (see datasheet for more detail). - * - * \note Generaly a defaul memory page size is more than 256 byte. - * In this case we need for addressing a byte in one page more than - * 8 bit, so we put in fourth byte low part of address byte, and - * hight part of address byte in third byte togheter low par of page - * address. - * - */ - - /* - * Send opcode. - */ - kfile_putc(opcode, fd->channel); - - /* - * Send page address. - */ - kfile_putc((uint8_t)(page_addr >> (16 - mem_info[fd->dev].page_bits)), fd->channel); - kfile_putc((uint8_t)((page_addr << (mem_info[fd->dev].page_bits - 8)) + (byte_addr >> 8)), fd->channel); - - /* - * Send byte page address. - */ - kfile_putc((uint8_t)byte_addr, fd->channel); -} - -/** - * Reset dataflash memory function. - * - * If \a fd->setReset function is not NULL, - * this function resets data flash memory - * with one pulse reset long about 10usec. - * - */ -static void dataflash_reset(KFileDataflash *fd) -{ - fd->setCS(false); - - if (fd->setReset) - { - fd->setReset(true); - timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH)); - fd->setReset(false); - timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH)); - } -} - - -/** - * Read status register of dataflah memory. - */ -static uint8_t dataflash_stat(KFileDataflash *fd) -{ - /* - * Make sure to toggle CS signal - * and reset dataflash command decoder. - */ - CS_TOGGLE(fd); - - kfile_putc(DFO_READ_STATUS, fd->channel); - - return kfile_getc(fd->channel); -} - - -/** - * Send one command to data flash memory, and - * return status register value. - * - */ -static uint8_t dataflash_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode) -{ - uint8_t stat; - - send_cmd(fd, page_addr, byte_addr, opcode); - - CS_TOGGLE(fd); - - /* - * We chech data flash memory state, and wait until busy-flag - * is high. - */ - while (!(dataflash_stat(fd) & BUSY_BIT)) - { - #if CONFIG_KERNEL - proc_switch(); - #endif - } - - stat = dataflash_stat(fd); - - kfile_flush(fd->channel); // Flush channel - /* - * Data flash has completed a bus cycle, so disable CS. - */ - fd->setCS(false); - - return stat; -} - -/** - * Read \a len bytes from main data flash memory or buffer data - * flash memory, and put it in \a *block. - */ -static void dataflash_readBlock(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflash_size_t len) -{ - send_cmd(fd, page_addr, byte_addr, opcode); - - if (opcode == DFO_READ_FLASH_MEM_BYTE_B) - { - /* - * Send 24 don't care bits. - */ - uint8_t dummy[] = { 0, 0, 0 }; - kfile_write(fd->channel, dummy, sizeof(dummy)); - } - - kfile_putc(0, fd->channel); //Send 8 don't care bit. - kfile_read(fd->channel, block, len); //Read len bytes ad put in block buffer. - kfile_flush(fd->channel); // Flush channel - fd->setCS(false); -} - - -/** - * Write \a len bytes in dataflash memory buffer. - * - * \note Is not possible to write directly in dataflash main memory. - * To perform a write in main memory you must first write in dataflash buffer - * memory and then send a command to write the page in main memory. - */ -static void dataflash_writeBlock(KFileDataflash *fd, dataflash_offset_t offset, DataFlashOpcode opcode, const uint8_t *block, dataflash_size_t len) -{ - ASSERT(offset + len <= mem_info[fd->dev].page_size); - - send_cmd(fd, 0x00, offset, opcode); - - kfile_write(fd->channel, block, len); //Write len bytes. - kfile_flush(fd->channel); // Flush channel - - fd->setCS(false); -} - - -/** - * Load selct page from dataflash memory to buffer. - */ -static void dataflash_loadPage(KFileDataflash *fd, dataflash_page_t page_addr) -{ - dataflash_cmd(fd, page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1); -} - -/** - * Flush select page (stored in buffer) in data flash main memory page. - */ -static int dataflash_flush(KFile *_fd) -{ - KFileDataflash *fd = KFILEDATAFLASH(_fd); - if (fd->page_dirty) - { - dataflash_cmd(fd, fd->current_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E); - - fd->page_dirty = false; - - kprintf("Flushing page <%ld>\n", fd->current_page); - } - return 0; -} - -/* Kfile interface section */ - -/** - * Close file \a fd. - */ -static int dataflash_close(struct KFile *_fd) -{ - dataflash_flush(_fd); - TRACE; - return 0; -} - -/** - * Reopen dataflash file \a fd. - */ -static KFile *dataflash_reopen(KFile *_fd) -{ - KFileDataflash *fd = KFILEDATAFLASH(_fd); - dataflash_close(_fd); - - fd->current_page = 0; - fd->fd.seek_pos = 0; - - /* Load selected page from dataflash memory */ - dataflash_loadPage(fd, fd->current_page); - - TRACE; - return &fd->fd; -} - - -/** - * Read in \a buf \a size bytes from dataflash memmory. - * - * \note For reading data flash memory, we - * check flag page_dirty, if is true (that mean - * we have written a byte in buffer memory) we - * flush current page in main memory and - * then read from memory, else we read byte - * directly from data flash main memory. - * - * \return the number of bytes read. - */ -static size_t dataflash_read(struct KFile *_fd, void *buf, size_t size) -{ - KFileDataflash *fd = KFILEDATAFLASH(_fd); - - dataflash_offset_t byte_addr; - dataflash_page_t page_addr; - uint8_t *data = (uint8_t *)buf; - - - ASSERT(fd->fd.seek_pos + size <= fd->fd.size); - size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos); - - kprintf("Reading at pos[%lu]\n", fd->fd.seek_pos); - - /* - * We select page and offest from absolute address. - */ - page_addr = fd->fd.seek_pos / mem_info[fd->dev].page_size; - byte_addr = fd->fd.seek_pos % mem_info[fd->dev].page_size; - - kprintf("[page-<%ld>, byte-<%ld>]", page_addr, byte_addr); - - /* - * Flush current page in main memory if - * we had been written a byte in memory - */ - dataflash_flush(&fd->fd); - - /* - * Read byte in main page data flash memory. - */ - dataflash_readBlock(fd, page_addr, byte_addr, mem_info[fd->dev].read_cmd, data, size); - - fd->fd.seek_pos += size; - kprintf("Read %ld bytes\n", size); - - return size; -} - -/** - * Write \a _buf in dataflash memory - * - * \note For writing \a _buf in dataflash memory, we must - * first write in buffer data flash memory. At the end of write, - * we can put page in dataflash main memory. - * If we write in two contiguous pages, we put in main memory current - * page and then reload the page which we want to write. - * - * \return the number of bytes write. - */ -static size_t dataflash_write(struct KFile *_fd, const void *_buf, size_t size) -{ - KFileDataflash *fd = KFILEDATAFLASH(_fd); - - dataflash_offset_t offset; - dataflash_page_t new_page; - size_t total_write = 0; - - const uint8_t *data = (const uint8_t *) _buf; - - ASSERT(fd->fd.seek_pos + size <= fd->fd.size); - size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos); - - kprintf("Writing at pos[%lu]\n", fd->fd.seek_pos); - - while (size) - { - /* - * We select page and offest from absolute address. - */ - new_page = fd->fd.seek_pos / mem_info[fd->dev].page_size; - offset = fd->fd.seek_pos % mem_info[fd->dev].page_size; - - - size_t wr_len = MIN(size, mem_info[fd->dev].page_size - offset); - - kprintf(" [page-<%ld>, byte-<%ld>]",new_page, offset); - - if (new_page != fd->current_page) - { - /* Flush current page in main memory*/ - dataflash_flush(&fd->fd); - /* Load select page memory from data flash memory*/ - dataflash_loadPage(fd, new_page); - - fd->current_page = new_page; - kprintf(" >> Load page: <%ld> ", new_page); - } - /* - * Write byte in current page, and set true - * page_dirty flag. - */ - dataflash_writeBlock(fd, offset, DFO_WRITE_BUFF1, data, wr_len); - fd->page_dirty = true; - - data += wr_len; - fd->fd.seek_pos += wr_len; - size -= wr_len; - total_write += wr_len; - } - - kprintf("written %lu bytes\n", total_write); - return total_write; -} - -MOD_DEFINE(dataflash); - -/** - * Dataflash init function. - * This function initialize \a fd with SPI channel \a ch and test if data flash memory - * density is the same specified by device \a dev. - * \a setCS is a callback used to set/reset CS line. - * \a setReset is a callback used to set/reset the dataflash (can be NULL if reset is unconnected) - * \return true if ok, false if memory density read from dataflash is not compliant with the - * configured one. - */ -bool dataflash_init(KFileDataflash *fd, KFile *ch, DataflashType dev, dataflash_setCS_t *setCS, dataflash_setReset_t *setReset) -{ - uint8_t stat; - - MOD_CHECK(dataflash_hw); - - ASSERT(fd); - ASSERT(ch); - ASSERT(setCS); - ASSERT(dev < DFT_CNT); - - memset(fd, 0, sizeof(*fd)); - DB(fd->fd._type = KFT_DATAFLASH); - fd->dev = dev; - fd->channel = ch; - fd->setReset = setReset; - fd->setCS = setCS; - - // Setup data flash programming functions. - fd->fd.reopen = dataflash_reopen; - fd->fd.close = dataflash_close; - fd->fd.read = dataflash_read; - fd->fd.write = dataflash_write; - fd->fd.seek = kfile_genericSeek; - fd->fd.flush = dataflash_flush; - - dataflash_reset(fd); - - stat = dataflash_stat(fd); - - /* - * 2,3,4,5 bits of 1 byte status register - * indicate a device density of dataflash memory - * (see datasheet for more detail.) - */ - if (GET_ID_DESITY_DEVICE(stat) != mem_info[fd->dev].density_id) - return false; - - fd->current_page = 0; - fd->fd.seek_pos = 0; - fd->fd.size = mem_info[fd->dev].page_size * mem_info[fd->dev].page_cnt; - - /* Load selected page from dataflash memory */ - dataflash_loadPage(fd, fd->current_page); - MOD_INIT(dataflash); - return true; -} diff --git a/drv/dataflash.h b/drv/dataflash.h deleted file mode 100644 index 61858167..00000000 --- a/drv/dataflash.h +++ /dev/null @@ -1,187 +0,0 @@ -/** - * \file - * - * - * \brief Function library for AT45DB081D Flash memory. - * - * - * \version $Id: dataflash.h 20677 2008-02-19 14:29:52Z batt $ - * \author Daniele Basile - */ - - -#ifndef DRV_DATAFLASH_H -#define DRV_DATAFLASH_H - -#include -#include - -#include - - -/** - * Type definitions for dflash memory. - * \{ - */ -typedef uint32_t dataflash_page_t; -typedef uint32_t dataflash_offset_t; -typedef uint32_t dataflash_size_t; -/*\}*/ - -/** - * - */ -typedef void (dataflash_setReset_t)(bool); -typedef void (dataflash_setCS_t)(bool); - -/** - * Memory definitions. - * - * List of supported memory devices by this drive. - * Every time we call dataflash_init() we check device id to - * ensure we choose the right memory configuration. - * (see dataflash.c for more details). - */ -typedef enum DataflashType -{ - DFT_AT45DB041B, - DFT_AT45DB081D, - DFT_AT45DB161D, - DFT_CNT -} DataflashType; - - -/** - * Dataflash KFile context structure. - */ -typedef struct KFileDataflash -{ - KFile fd; ///< File descriptor. - KFile *channel; ///< Dataflash comm channel (usually SPI). - DataflashType dev; ///< Memory device type; - dataflash_page_t current_page; ///< Current loaded dataflash page. - bool page_dirty; ///< True if current_page is dirty (needs to be flushed). - dataflash_setReset_t *setReset; ///< Callback used to set reset pin of dataflash. - dataflash_setCS_t *setCS; ///< Callback used to set CS pin of dataflash. -} KFileDataflash; - -/** - * ID for dataflash. - */ -#define KFT_DATAFLASH MAKE_ID('D', 'F', 'L', 'H') - -/** - * Convert + ASSERT from generic KFile to KFileDataflash. - */ -INLINE KFileDataflash * KFILEDATAFLASH(KFile *fd) -{ - ASSERT(fd->_type == KFT_DATAFLASH); - return (KFileDataflash *)fd; -} - -#define RESET_PULSE_WIDTH 10 ///< Width of reset pulse in usec. -#define BUSY_BIT 0x80 ///< Select a busy bit in status register. -#define CMP_BIT 0x40 ///< Select a compare bit in status register. - -/** - * Select bits 2-5 of status register. These - * bits indicate device density (see datasheet for - * more details). - */ -#define GET_ID_DESITY_DEVICE(reg_stat) (((reg_stat) & 0x3C) >> 2) - -/** - * Data flash opcode commands. - */ -typedef enum DataFlashOpcode { - /** - * Dataflash read commands. - * \{ - */ - DFO_READ_FLASH_MEM_BYTE_D = 0x0B, ///< Continuos array read for D type memories. - DFO_READ_FLASH_MEM_BYTE_B = 0xE8, ///< Continuos array read for B type memories. - - DFO_READ_FLASH_MEM = 0xD2, ///< Main memory page read. - DFO_READ_BUFF1 = 0xD4, ///< SRAM buffer 1 read. - DFO_READ_BUFF2 = 0xD6, ///< SRAM buffer 2 read. - /* \}*/ - - /** - * Program and erase commands data flash. - * \{ - */ - DFO_WRITE_BUFF1 = 0x84, ///< SRAM buffer 1 write. - DFO_WRITE_BUFF2 = 0x87, ///< SRAM buffer 2 write. - DFO_WRITE_BUFF1_TO_MEM_E = 0x83, ///< Buffer 1 to main memory page program with built-in erase. - DFO_WRITE_BUFF2_TO_MEM_E = 0x86, ///< Buffer 2 to main memory page program with built-in erase. - DFO_WRITE_BUFF1_TO_MEM = 0x88, ///< Buffer 1 to main memory page program without built-in erase. - DFO_WRITE_BUFF2_TO_MEM = 0x89, ///< Buffer 2 to main memory page program without built-in erase. - DFO_ERASE_PAGE = 0x81, ///< Erase page. - DFO_ERASE_BLOCK = 0x50, ///< Erase block. - DFO_ERASE_SECTOR = 0x7C, ///< Erase sector. - DFO_WRITE_MEM_TR_BUFF1 = 0x82, ///< Write main memory page through buffer 1. - DFO_WRITE_MEM_TR_BUFF2 = 0x85, ///< Write main memory page through buffer 2. - /* \}*/ - - /** - * Additional dataflash commands. - * \{ - */ - DFO_MOV_MEM_TO_BUFF1 = 0x53, ///< Transfer main mmemory to buffer 1. - DFO_MOV_MEM_TO_BUFF2 = 0x55, ///< Transfer main mmemory to buffer 2. - DFO_CMP_MEM_TO_BUFF1 = 0x60, ///< Compare main mmemory with buffer 1. - DFO_CMP_MEM_TO_BUFF2 = 0x61, ///< Compare main mmemory with buffer 2. - DFO_ARW_MEM_TR_BUFF1 = 0x58, ///< Auto page rewrite through buffer 1. - DFO_ARW_MEM_TR_BUFF2 = 0x59, ///< Auto page rewrite through buffer 2 - DFO_PWR_DOWN = 0xB9, ///< Deep power-down. - DFO_RESUME_PWR_DOWN = 0xAB, ///< Resume from deep power-down. - DFO_READ_STATUS = 0xD7, ///< Read status register. - DFO_ID_DEV = 0x9F ///< Read manufacturer and device ID. - /* \}*/ -} DataFlashOpcode; - - -/** - * Structure used to describe a dataflash memory. - */ -typedef struct DataflashInfo -{ - uint8_t density_id; ///< Density id, used to check memory type. - dataflash_size_t page_size; ///< Page size, in bytes. - uint8_t page_bits; ///< Number of bits needed to access a page. - uint16_t page_cnt; ///< Number of pages on memory. - DataFlashOpcode read_cmd; ///< Command to be used to perform a continuous array. -} DataflashInfo; - - -bool dataflash_init(KFileDataflash *fd, KFile *ch, DataflashType type, dataflash_setCS_t *setCS, dataflash_setReset_t *setReset); - -#endif /* DRV_DATAFLASH_H */ diff --git a/drv/eeprom.c b/drv/eeprom.c deleted file mode 100644 index 4e7f615f..00000000 --- a/drv/eeprom.c +++ /dev/null @@ -1,341 +0,0 @@ -/** - * \file - * - * - * \brief Driver for the 24xx16 and 24xx256 I2C EEPROMS (implementation) - * - * \note This implementation is AVR specific. - * - * \version $Id$ - * \author Stefano Fedrigo - * \author Bernardo Innocenti - */ - -#include "eeprom.h" - -#include -#include // CONFIG_EEPROM_VERIFY -#include // MIN() -#include -#include CPU_HEADER(twi) -#include -#include // cpu_to_be16() - -#include // memset() - - -// Configuration sanity checks -#if !defined(CONFIG_EEPROM_VERIFY) || (CONFIG_EEPROM_VERIFY != 0 && CONFIG_EEPROM_VERIFY != 1) - #error CONFIG_EEPROM_VERIFY must be defined to either 0 or 1 -#endif - -/** - * EEPROM ID code - */ -#define EEPROM_ID 0xA0 - -/** - * This macros form the correct slave address for EEPROMs - */ -#define EEPROM_ADDR(x) (EEPROM_ID | (((uint8_t)(x)) << 1)) - - - - -/** - * Copy \c count bytes from buffer \c buf to - * eeprom at address \c addr. - */ -static bool eeprom_writeRaw(e2addr_t addr, const void *buf, size_t count) -{ - bool result = true; - ASSERT(addr + count <= EEPROM_SIZE); - - while (count && result) - { - /* - * Split write in multiple sequential mode operations that - * don't cross page boundaries. - */ - size_t size = - MIN(count, (size_t)(EEPROM_BLKSIZE - (addr & (EEPROM_BLKSIZE - 1)))); - - #if CONFIG_EEPROM_TYPE == EEPROM_24XX16 - /* - * The 24LC16 uses the slave address as a 3-bit - * block address. - */ - uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07); - uint8_t blk_offs = (uint8_t)addr; - - result = - twi_start_w(EEPROM_ADDR(blk_addr)) - && twi_send(&blk_offs, sizeof blk_offs) - && twi_send(buf, size); - - #elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 - - // 24LC256 wants big-endian addresses - uint16_t addr_be = cpu_to_be16(addr); - - result = - twi_start_w(EEPROM_ID) - && twi_send((uint8_t *)&addr_be, sizeof addr_be) - && twi_send(buf, size); - - #else - #error Unknown device type - #endif - - twi_stop(); - - // DEBUG - //kprintf("addr=%d, count=%d, size=%d, *#?=%d\n", - // addr, count, size, - // (EEPROM_BLKSIZE - (addr & (EEPROM_BLKSIZE - 1))) - //); - - /* Update count and addr for next operation */ - count -= size; - addr += size; - buf = ((const char *)buf) + size; - } - - if (!result) - TRACEMSG("Write error!"); - return result; -} - - -#if CONFIG_EEPROM_VERIFY -/** - * Check that the contents of an EEPROM range - * match with a provided data buffer. - * - * \return true on success. - */ -static bool eeprom_verify(e2addr_t addr, const void *buf, size_t count) -{ - uint8_t verify_buf[16]; - bool result = true; - - while (count && result) - { - /* Split read in smaller pieces */ - size_t size = MIN(count, sizeof verify_buf); - - /* Read back buffer */ - if (eeprom_read(addr, verify_buf, size)) - { - if (memcmp(buf, verify_buf, size) != 0) - { - TRACEMSG("Data mismatch!"); - result = false; - } - } - else - { - TRACEMSG("Read error!"); - result = false; - } - - /* Update count and addr for next operation */ - count -= size; - addr += size; - buf = ((const char *)buf) + size; - } - - return result; -} -#endif /* CONFIG_EEPROM_VERIFY */ - - -bool eeprom_write(e2addr_t addr, const void *buf, size_t count) -{ -#if CONFIG_EEPROM_VERIFY - int retries = 5; - - while (retries--) - if (eeprom_writeRaw(addr, buf, count) - && eeprom_verify(addr, buf, count)) - return true; - - return false; - -#else /* !CONFIG_EEPROM_VERIFY */ - return eeprom_writeRaw(addr, buf, count); -#endif /* !CONFIG_EEPROM_VERIFY */ -} - - -/** - * Copy \c count bytes at address \c addr - * from eeprom to RAM to buffer \c buf. - * - * \return true on success. - */ -bool eeprom_read(e2addr_t addr, void *buf, size_t count) -{ - ASSERT(addr + count <= EEPROM_SIZE); - -#if CONFIG_EEPROM_TYPE == EEPROM_24XX16 - /* - * The 24LC16 uses the slave address as a 3-bit - * block address. - */ - uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07); - uint8_t blk_offs = (uint8_t)addr; - - bool res = - twi_start_w(EEPROM_ADDR(blk_addr)) - && twi_send(&blk_offs, sizeof blk_offs) - && twi_start_r(EEPROM_ADDR(blk_addr)) - && twi_recv(buf, count); - -#elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 - - // 24LC256 wants big-endian addresses - addr = cpu_to_be16(addr); - - bool res = - twi_start_w(EEPROM_ID) - && twi_send((uint8_t *)&addr, sizeof(addr)) - && twi_start_r(EEPROM_ID) - && twi_recv(buf, count); -#else - #error Unknown device type -#endif - - twi_stop(); - - if (!res) - TRACEMSG("Read error!"); - return res; -} - - -/** - * Write a single character \a c at address \a addr. - */ -bool eeprom_write_char(e2addr_t addr, char c) -{ - return eeprom_write(addr, &c, 1); -} - - -/** - * Read a single character at address \a addr. - * - * \return the requested character or -1 in case of failure. - */ -int eeprom_read_char(e2addr_t addr) -{ - char c; - - if (eeprom_read(addr, &c, 1)) - return c; - else - return -1; -} - - -/** - * Erase specified part of eeprom, writing 0xFF. - * - * \param addr starting address - * \param count length of block to erase - */ -void eeprom_erase(e2addr_t addr, size_t count) -{ - uint8_t buf[EEPROM_BLKSIZE]; - memset(buf, 0xFF, sizeof buf); - - // Clear all but struct hw_info at start of eeprom - while (count) - { - // Long operation, reset watchdog - wdt_reset(); - - size_t size = MIN(count, sizeof buf); - eeprom_write(addr, buf, size); - addr += size; - count -= size; - } -} - - -/** - * Initialize TWI module. - */ -void eeprom_init(void) -{ - twi_init(); -} - - -#ifdef _DEBUG - -#include - -void eeprom_test(void) -{ - static const char magic[14] = "Humpty Dumpty"; - char buf[sizeof magic]; - size_t i; - - // Write something to EEPROM using unaligned sequential writes - for (i = 0; i < 42; ++i) - { - wdt_reset(); - eeprom_write(i * sizeof magic, magic, sizeof magic); - } - - // Read back with single-byte reads - for (i = 0; i < 42 * sizeof magic; ++i) - { - wdt_reset(); - eeprom_read(i, buf, 1); - kprintf("EEPROM byte read: %c (%d)\n", buf[0], buf[0]); - ASSERT(buf[0] == magic[i % sizeof magic]); - } - - // Read back again using sequential reads - for (i = 0; i < 42; ++i) - { - wdt_reset(); - memset(buf, 0, sizeof buf); - eeprom_read(i * sizeof magic, buf, sizeof magic); - kprintf("EEPROM seq read @ 0x%x: '%s'\n", i * sizeof magic, buf); - ASSERT(memcmp(buf, magic, sizeof magic) == 0); - } -} - -#endif // _DEBUG diff --git a/drv/eeprom.h b/drv/eeprom.h deleted file mode 100644 index 21ae105a..00000000 --- a/drv/eeprom.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Stefano Fedrigo - * \author Bernardo Innocenti - * - * \brief Driver for the 24xx16 and 24xx256 I2C EEPROMS (interface) - */ - -#ifndef DRV_EEPROM_H -#define DRV_EEPROM_H - -#include -#include - -/** - * \name Values for CONFIG_EEPROM_TYPE - * \{ - */ -#define EEPROM_24XX16 1 -#define EEPROM_24XX256 2 -/*\}*/ - -#if CONFIG_EEPROM_TYPE == EEPROM_24XX16 - #define EEPROM_BLKSIZE 0x10 ///< Eeprom block size (16byte) - #define EEPROM_SIZE 0x800 ///< Eeprom total size (2kB) -#elif CONFIG_EEPROM_TYPE == EEPROM_24XX256 - #define EEPROM_BLKSIZE 0x40 ///< Eeprom block size (64byte) - #define EEPROM_SIZE 0x8000 ///< Eeprom total size (32kB) -#else - #error Unsupported EEPROM type. -#endif - -/// Type for EEPROM addresses -typedef uint16_t e2addr_t; - -/** - * Macro for E2Layout offset calculation - * - * \note We can't just use offsetof() here because we could use - * non-constant expressions to access array elements. - * - * \note 'type' is the structure type holding eeprom layout - * and must be defined in user files. - */ -#define e2addr(type, field) ((e2addr_t)&(((type *)0)->field)) - - -bool eeprom_write(e2addr_t addr, const void *buf, size_t count); -bool eeprom_read(e2addr_t addr, void *buf, size_t count); -bool eeprom_write_char(e2addr_t addr, char c); -int eeprom_read_char(e2addr_t addr); -void eeprom_erase(e2addr_t addr, size_t count); -void eeprom_init(void); -void eeprom_test(void); - -#endif /* DRV_EEPROM_H */ diff --git a/drv/flash25.c b/drv/flash25.c deleted file mode 100644 index 2f90d52f..00000000 --- a/drv/flash25.c +++ /dev/null @@ -1,439 +0,0 @@ -/** - * \file - * - * - * \brief Function library for serial Flash memory. - * - * Module provide a kfile interface, that ensure an abstraction - * from comunication channel and give a standard interface. - * Typicaly this kind of memory use an SPI bus, but you should - * use another comunication channel you have defined. - * - * \version $Id$ - * \author Daniele Basile - */ - -#include - -#include -#include - -#include -#include - -#if CONFIG_KERNEL -#include -#endif - -/* - * We use a spi bus, thus include hardware specific definition. - * If you use another channel you must redefine this macros. - */ -#include "hw_spi.h" - -#include - -/** - * Global definition of channel handler (usually SPI). - */ -static KFile *channel; - -/** - * Wait until flash memory is ready. - */ -static void flash25_waitReady(void) -{ - uint8_t stat; - - while (1) - { - CS_ENABLE(); - - kfile_putc(FLASH25_RDSR, channel); - stat = kfile_getc(channel); - - CS_DISABLE(); - - if (!(stat & RDY_BIT)) - break; - #if CONFIG_KERNEL - else - proc_switch(); - #endif - } -} - -/** - * Send a single command to serial flash memory. - */ -static void flash25_sendCmd(Flash25Opcode cmd) -{ - CS_ENABLE(); - - kfile_putc(cmd, channel); - - CS_DISABLE(); -} - -/** - * flash25 init function. - * This function init a comunication channel and - * try to read manufacturer id of serial memory, - * then check if is equal to selected type. - */ -static bool flash25_pin_init(void) -{ - uint8_t device_id; - uint8_t manufacturer; - - SPI_HW_INIT(); - - CS_ENABLE(); - /* - * Send read id productor opcode on - * comunication channel - * TODO:controllare se ha senso - */ - kfile_putc(FLASH25_RDID, channel); - - manufacturer = kfile_getc(channel); - device_id = kfile_getc(channel); - - CS_DISABLE(); - - if((FLASH25_MANUFACTURER_ID == manufacturer) && - (FLASH25_DEVICE_ID == device_id)) - return true; - else - return false; -} - -/** - * Reopen a serial memory interface. - * - * For serial memory this function reinit only - * the size and seek_pos in kfile stucture. - * Return a kfile pointer, after assert check. - */ -static KFile * flash25_reopen(struct KFile *fd) -{ - KFILE_ASSERT_GENERIC(fd); - - fd->seek_pos = 0; - fd->size = FLASH25_MEM_SIZE; - - kprintf("flash25 file opened\n"); - return fd; -} - -/** - * Close a serial memory interface. - * - * For serial memory this funtion do nothing, - * and return always 0. - */ -static int flash25_close(UNUSED_ARG(struct KFile *,fd)) -{ - kprintf("flash25 file closed\n"); - return 0; -} - -/** - * Read \a _buf lenght \a size byte from serial flash memmory. - * - * For read in serial flash memory we - * enble cs pin and send one byte of read opcode, - * and then 3 byte of address of memory cell we - * want to read. After the last byte of address we - * can read data from so pin. - * - * \return the number of bytes read. - */ -static size_t flash25_read(struct KFile *fd, void *buf, size_t size) -{ - uint8_t *data = (uint8_t *)buf; - - KFILE_ASSERT_GENERIC(fd); - - ASSERT(fd->seek_pos + size <= fd->size); - size = MIN((uint32_t)size, fd->size - fd->seek_pos); - - //kprintf("Reading at addr[%lu], size[%d]\n", fd->seek_pos, size); - CS_ENABLE(); - - kfile_putc(FLASH25_READ, channel); - - - /* - * Address that we want to read. - */ - kfile_putc((fd->seek_pos >> 16) & 0xFF, channel); - kfile_putc((fd->seek_pos >> 8) & 0xFF, channel); - kfile_putc(fd->seek_pos & 0xFF, channel); - - kfile_read(channel, data, size); - - CS_DISABLE(); - - fd->seek_pos += size; - - return size; -} - -/** - * Write \a _buf in serial flash memory - * - * Before to write data into flash we must enable - * memory writing. To do this we send a WRE command opcode. - * After this command the flash is ready to be write, and so - * we send a PROGRAM opcode followed to 3 byte of - * address memory, at the end of last address byte - * we can send the data. - * When we finish to send all data, we disable cs - * and flash write received data bytes on its memory. - * - * \note: WARNING: you could write only on erased memory section! - * Each write time you could write max a memory page size, - * because if you write more than memory page size the - * address roll over to first byte of page. - * - * \return the number of bytes write. - */ -static size_t flash25_write(struct KFile *fd, const void *_buf, size_t size) -{ - flash25Offset_t offset; - flash25Size_t total_write = 0; - flash25Size_t wr_len; - const uint8_t *data = (const uint8_t *) _buf; - - KFILE_ASSERT_GENERIC(fd); - ASSERT(fd->seek_pos + size <= fd->size); - - size = MIN((flash25Size_t)size, fd->size - fd->seek_pos); - - while (size) - { - offset = fd->seek_pos % (flash25Size_t)FLASH25_PAGE_SIZE; - wr_len = MIN((flash25Size_t)size, FLASH25_PAGE_SIZE - (flash25Size_t)offset); - - kprintf("[seek_pos-<%lu>, offset-<%d>]\n", fd->seek_pos, offset); - - /* - * We check serial flash memory state, and wait until ready-flag - * is high. - */ - flash25_waitReady(); - - /* - * Start write cycle. - * We could write only data not more long than one - * page size. - * - * To write on serial flash memory we must first - * enable write with a WREN opcode command, before - * the PROGRAM opcode. - * - * \note: the same byte cannot be reprogrammed without - * erasing the whole sector first. - */ - flash25_sendCmd(FLASH25_WREN); - - CS_ENABLE(); - kfile_putc(FLASH25_PROGRAM, channel); - - /* - * Address that we want to write. - */ - kfile_putc((fd->seek_pos >> 16) & 0xFF, channel); - kfile_putc((fd->seek_pos >> 8) & 0xFF, channel); - kfile_putc(fd->seek_pos & 0xFF, channel); - - kfile_write(channel, data, wr_len); - - CS_DISABLE(); - - data += wr_len; - fd->seek_pos += wr_len; - size -= wr_len; - total_write += wr_len; - } - - kprintf("written %u bytes\n", total_write); - return total_write; -} - -/** - * Sector erase function. - * - * Erase a select \p sector of serial flash memory. - * - * \note A sector size is FLASH25_SECTOR_SIZE. - * This operation could take a while. - */ -void flash25_sectorErase(Flash25Sector sector) -{ - - /* - * Erase a sector could take a while, - * for debug we measure that time - * see datasheet to compare this time. - */ - DB(ticks_t start_time = timer_clock()); - - CS_ENABLE(); - - /* - * To erase a sector of serial flash memory we must first - * enable write with a WREN opcode command, before - * the SECTOR_ERASE opcode. Sector is automatically - * determinate if any address within the sector - * is selected. - */ - kfile_putc(FLASH25_WREN, channel); - kfile_putc(FLASH25_SECTORE_ERASE, channel); - - /* - * Address inside the sector that we want to - * erase. - */ - kfile_putc(sector, channel); - - CS_DISABLE(); - - /* - * We check serial flash memory state, and wait until ready-flag - * is hight. - */ - flash25_waitReady(); - - DB(kprintf("Erased sector [%d] in %d ms\n", sector, ticks_to_ms(timer_clock() - start_time))); - -} - -/** - * Chip erase function. - * - * Erase all sector of serial flash memory. - * - * \note This operation could take a while. - */ -void flash25_chipErase(void) -{ - /* - * Erase all chip could take a while, - * for debug we measure that time - * see datasheet to compare this time. - */ - DB(ticks_t start_time = timer_clock()); - - /* - * To erase serial flash memory we must first - * enable write with a WREN opcode command, before - * the CHIP_ERASE opcode. - */ - flash25_sendCmd(FLASH25_WREN); - flash25_sendCmd(FLASH25_CHIP_ERASE); - - /* - * We check serial flash memory state, and wait until ready-flag - * is high. - */ - flash25_waitReady(); - - DB(kprintf("Erased all memory in %d ms\n", ticks_to_ms(timer_clock() - start_time))); - -} - -/** - * Init data flash memory interface. - */ -void flash25_init(struct KFile *fd, struct KFile *_channel) -{ - //Set kfile struct type as a generic kfile structure. - DB(fd->_type = KFT_GENERIC); - - // Set up data flash programming functions. - fd->reopen = flash25_reopen; - fd->close = flash25_close; - fd->read = flash25_read; - fd->write = flash25_write; - fd->seek = kfile_genericSeek; - - /* - * Init a local channel structure and flash kfile interface. - */ - channel = _channel; - flash25_reopen(fd); - - /* - * Init data flash memory and micro pin. - */ - if (!flash25_pin_init()) - ASSERT(0); -} - -#if CONFIG_TEST - -/** - * Test function for flash25. - * - * \note: This implentation use a SPI channel. - */ -bool flash25_test(KFile *channel) -{ - KFile fd; - uint8_t test_buf[256]; - - /* - * Init a spi kfile interface and - * flash driver. - */ - flash25_init(&fd, channel); - - kprintf("Init serial flash\n"); - - flash25_chipErase(); - - flash25_sectorErase(FLASH25_SECT1); - flash25_sectorErase(FLASH25_SECT2); - flash25_sectorErase(FLASH25_SECT3); - flash25_sectorErase(FLASH25_SECT4); - - /* - * Launche a kfile test interface. - */ - kprintf("Kfile test start..\n"); - if (!kfile_test(&fd, test_buf, NULL, sizeof(test_buf))) - return false; - - return true; -} -#endif /* CONFIG_TEST */ diff --git a/drv/flash25.h b/drv/flash25.h deleted file mode 100644 index e45dbed4..00000000 --- a/drv/flash25.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * \file - * - * - * \brief Function library for serial Flash memory. - * - * - * \version $Id$ - * \author Daniele Basile - */ - - -#ifndef DRV_FLASH25_H -#define DRV_FLASH25_H - -#include -#include - - -#include - -/** - * Type definition for serial flash memory. - */ -typedef uint32_t flash25Addr_t; -typedef uint32_t flash25Size_t; -typedef uint8_t flash25Offset_t; - - -/** - * Memory definition. - * - * \note Below are defined valid serial flash memory support to - * this drive. Every time we call flash25_init() function we check - * if memory defined are right (see flash25.c form more detail). - * \{ - */ -#define FLASH25_AT25F2048 1 - -#if CONFIG_FLASH25 == FLASH25_AT25F2048 - #define FLASH25_MANUFACTURER_ID 0x1F // ATMEL - #define FLASH25_DEVICE_ID 0x63 // Device ID - #define FLASH25_PAGE_SIZE 256 // Page size in byte - #define FLASH25_NUM_SECTOR 4 // Number of section in serial memory - #define FLASH25_SECTOR_SIZE 65536UL // Section size in byte - #define FLASH25_MEM_SIZE FLASH25_NUM_SECTOR * FLASH25_SECTOR_SIZE - #define FLASH25_NUM_PAGE FLASH25_MEM_SIZE / FLASH25_PAGE_SIZE -#elif - #error Nothing memory defined in CONFIG_FLASH25 are support. -#endif - -#define RDY_BIT 0x1 // Statuts of write cycle -/* \} */ - -/** - * Serial flash opcode commands. - */ -typedef enum { - FLASH25_WREN = 0x6, ///< Set write enable latch - FLASH25_WRDI = 0x4, ///< Reset enable write latch - FLASH25_RDSR = 0x5, ///< Read status register - FLASH25_WRSR = 0x1, ///< Write status register - FLASH25_READ = 0x3, ///< Read data from memory array - FLASH25_PROGRAM = 0x2, ///< Program data into memory array - FLASH25_SECTORE_ERASE = 0x52, ///< Erase one sector in memory array - FLASH25_CHIP_ERASE = 0x62, ///< Erase all sector in memory array - FLASH25_RDID = 0x15 ///< Read Manufacturer and product ID -} Flash25Opcode; - -/** - * Serial flash sector memory address. - */ -#if CONFIG_FLASH25 != FLASH25_AT25F2048 - #error Nothing memory defined in CONFIG_FLASH25 are support. -#endif - -typedef enum { - FLASH25_SECT1 = 0x0, ///< Sector 1 (0x0 -0xFFFF) - FLASH25_SECT2 = 0x10000, ///< Sector 2 (0x10000 -0x1FFFF) - FLASH25_SECT3 = 0x20000, ///< Sector 3 (0x20000 -0x2FFFF) - FLASH25_SECT4 = 0x30000, ///< Sector 4 (0x30000 -0x3FFFF) -} Flash25Sector; - -void flash25_init(struct KFile *fd, struct KFile *_channel); -void flash25_chipErase(void); -void flash25_sectorErase(Flash25Sector sector); -bool flash25_test(KFile *channel); - -#endif /* DRV_FLASH25_H */ - diff --git a/drv/kbd.c b/drv/kbd.c deleted file mode 100644 index f54ebf91..00000000 --- a/drv/kbd.c +++ /dev/null @@ -1,500 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \author Francesco Sacchi - * - * \brief Keyboard driver (implementation) - */ - -#include - -#include -#include - -#include -#include -#include - -/* Configuration sanity checks */ -#if !defined(CONFIG_KBD_POLL) || (CONFIG_KBD_POLL != KBD_POLL_SOFTINT && CONFIG_KBD_POLL != CONFIG_POLL_FREERTOS) - #error CONFIG_KBD_POLL must be defined to either KBD_POLL_SOFTINT or CONFIG_POLL_FREERTOS -#endif -#if !defined(CONFIG_KBD_BEEP) || (CONFIG_KBD_BEEP != 0 && CONFIG_KBD_BEEP != 1) - #error CONFIG_KBD_BEEP must be defined to either 0 or 1 -#endif -#if !defined(CONFIG_KBD_OBSERVER) || (CONFIG_KBD_OBSERVER != 0 && CONFIG_KBD_OBSERVER != 1) - #error CONFIG_KBD_OBSERVER must be defined to either 0 or 1 -#endif -#if !defined(CONFIG_KBD_LONGPRESS) || (CONFIG_KBD_LONGPRESS != 0 && CONFIG_KBD_LONGPRESS != 1) - #error CONFIG_KBD_LONGPRESS must be defined to either 0 or 1 -#endif - -#if CONFIG_KBD_BEEP - #include -#endif - -#define KBD_CHECK_INTERVAL 10 /**< (ms) Timing for kbd softint */ -#define KBD_DEBOUNCE_TIME 30 /**< (ms) Debounce time */ -#define KBD_BEEP_TIME 5 /**< (ms) Duration of keybeep */ - -#define KBD_REPEAT_DELAY 400 /**< (ms) Keyboard repeat delay for first character */ -#define KBD_REPEAT_RATE 100 /**< (ms) Initial interchar delay for keyboard repeat */ -#define KBD_REPEAT_MAXRATE 20 /**< (ms) Minimum delay for keyboard repeat */ -#define KBD_REPEAT_ACCEL 5 /**< (ms) Keyboard repeat speed increase */ - -#define KBD_LNG_DELAY 1000 /**< (ms) Keyboard long pression keys delay */ - - -/** Status for keyboard repeat state machine */ -static enum { KS_IDLE, KS_REPDELAY, KS_REPEAT } kbd_rptStatus; - - -static volatile keymask_t kbd_buf; /**< Single entry keyboard buffer */ -static volatile keymask_t kbd_cnt; /**< Number of keypress events in \c kbd_buf */ -static keymask_t kbd_rpt_mask; /**< Mask of repeatable keys. */ - -#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT -static Timer kbd_timer; /**< Keyboard softtimer */ -#endif - -static List kbd_rawHandlers; /**< Raw keyboard handlers */ -static List kbd_handlers; /**< Cooked keyboard handlers */ - -static KbdHandler kbd_defHandler; /**< The default keyboard handler */ -static KbdHandler kbd_debHandler; /**< The debounce keyboard handler */ -static KbdHandler kbd_rptHandler; /**< Auto-repeat keyboard handler */ - -#if CONFIG_KBD_LONGPRESS -static KbdHandler kbd_lngHandler; /**< Long pression keys handler */ -#endif - -#if CONFIG_KBD_OBSERVER - #include - Subject kbd_subject; -#endif - - -/** - * Poll keyboard and dispatch keys to handlers. - * - * Read the key states and invoke all keyboard - * handlers to process the new state. - * - * Call this function periodically using a software - * timer, an interrupt or a process. - */ -static void kbd_poll(void) -{ - /** Currently depressed key */ - static keymask_t current_key; - - struct KbdHandler *handler; - keymask_t key = kbd_readkeys(); - - /* Call raw input handlers */ - FOREACH_NODE(handler, &kbd_rawHandlers) - key = handler->hook(key); - - /* If this key was not previously pressed */ - if (key != current_key) - { - /* Remember last key */ - current_key = key; - - /* Call cooked input handlers */ - FOREACH_NODE(handler, &kbd_handlers) - key = handler->hook(key); - } -} - -#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT - -/** - * Keyboard soft-irq handler. - */ -static void kbd_softint(UNUSED_ARG(iptr_t, arg)) -{ - kbd_poll(); - timer_add(&kbd_timer); -} - -#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS - -#include "FreeRTOS.h" -#include "task.h" - -static portTASK_FUNCTION(kbd_task, arg) -{ - for (;;) - { - kbd_poll(); - timer_delay(KBD_CHECK_INTERVAL); - } -} - -#endif /* CONFIG_KBD_POLL */ - -/** - * \brief Read a key from the keyboard buffer. - * - * When a key is kept depressed between calls of this function a value - * is returned only after the time specified with KBD_REPAT_DELAY to - * avoid too fast keyboard repeat. - * - * \note Calls \c schedule() internally. - * - * \note This function is \b not interrupt safe! - * - * \return The mask of depressed keys or 0 if no keys are depressed. - * - */ -keymask_t kbd_peek(void) -{ - keymask_t key = 0; - -// FIXME: make it optional - /* Let other tasks run for a while */ - extern void schedule(void); - schedule(); - - /* Extract an event from the keyboard buffer */ - IRQ_DISABLE; - if (kbd_cnt) - { - --kbd_cnt; - key = kbd_buf; - } - IRQ_ENABLE; - - return key; -} - -/** - * Wait for a keypress and return the mask of depressed keys. - * - * \note This function is \b not interrupt safe! - */ -keymask_t kbd_get(void) -{ - keymask_t key; - - while (!(key = kbd_peek())) {} - - return key; -} - - -/** - * Wait up to \c timeout ms for a keypress - * and return the mask of depressed keys, or K_TIMEOUT - * if the timeout was reacked. - */ -keymask_t kbd_get_timeout(mtime_t timeout) -{ - keymask_t key; - - ticks_t start = timer_clock(); - ticks_t stop = ms_to_ticks(timeout); - do - { - if ((key = kbd_peek())) - return key; - } - while (timer_clock() - start < stop); - - return K_TIMEOUT; -} - - -void kbd_addHandler(struct KbdHandler *handler) -{ - KbdHandler *node; - List *list; - - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - /* Choose between raw and coocked handlers list */ - list = (handler->flags & KHF_RAWKEYS) ? - &kbd_rawHandlers : &kbd_handlers; - - /* - * Search for the first node whose priority - * is lower than the timer we want to add. - */ - FOREACH_NODE(node,list) - if (node->pri < handler->pri) - break; - - /* Enqueue handler in the handlers chain */ - INSERT_BEFORE(&handler->link, &node->link); - - IRQ_RESTORE(flags); -} - - -void kbd_remHandler(struct KbdHandler *handler) -{ - /* Remove the handler */ - ATOMIC(REMOVE(&handler->link)); -} - - -/** - * This is the default key handler, called after - * all other handlers have had their chance to - * do their special processing. This handler - * pushes all input in the keyboard FIFO buffer. - */ -static keymask_t kbd_defHandlerFunc(keymask_t key) -{ - if (key) - { - /* Force a single event in kbd buffer */ - kbd_buf = key; - kbd_cnt = 1; - - #if CONFIG_KBD_OBSERVER - observer_notify(&kbd_subject, KBD_EVENT_KEY, &key); - #endif - - #if CONFIG_KBD_BEEP - if (!(key & K_REPEAT)) - buz_beep(KBD_BEEP_TIME); - #endif - } - - /* Eat all input */ - return 0; -} - -/** - * Handle keyboard debounce - */ -static keymask_t kbd_debHandlerFunc(keymask_t key) -{ - /** Buffer for debounce */ - static keymask_t debounce_key; - - /** Timer for keyboard debounce */ - static ticks_t debounce_time; - - /** Key aquired after debounce */ - static keymask_t new_key; - - - ticks_t now = timer_clock(); - - if (key != debounce_key) - { - /* Reset debounce timer */ - debounce_key = key; - debounce_time = now; - } - else if ((new_key != debounce_key) - && (now - debounce_time > ms_to_ticks(KBD_DEBOUNCE_TIME))) - { - new_key = debounce_key; - debounce_time = now; - } - - return new_key; -} - -#if CONFIG_KBD_LONGPRESS -/** - * Handle long pression keys. - */ -static keymask_t kbd_lngHandlerFunc(keymask_t key) -{ - static ticks_t start; - ticks_t now = timer_clock(); - - if (key & K_LNG_MASK) - { - if (now - start > ms_to_ticks(KBD_LNG_DELAY)) - key |= K_LONG; - } - else - start = now; - return key; -} -#endif - -/** - * Set current mask of repeatable keys. - */ -keymask_t kbd_setRepeatMask(keymask_t mask) -{ - keymask_t oldmask = kbd_rpt_mask; - ATOMIC(kbd_rpt_mask = mask); - return oldmask; -} - -/** - * Handle keyboard repeat - */ -static keymask_t kbd_rptHandlerFunc(keymask_t key) -{ - /* Timer for keyboard repeat events. */ - static ticks_t repeat_time; - - /* Current repeat rate (for acceleration). */ - static ticks_t repeat_rate; /** Current repeat rate (for acceleration) */ - - ticks_t now = timer_clock(); - - switch (kbd_rptStatus) - { - case KS_IDLE: - if (key & kbd_rpt_mask) - { - repeat_time = now; - kbd_rptStatus = KS_REPDELAY; - } - break; - - case KS_REPDELAY: - if (key & kbd_rpt_mask) - { - if (now - repeat_time > ms_to_ticks(KBD_REPEAT_DELAY)) - { - key = (key & kbd_rpt_mask) | K_REPEAT; - repeat_time = now; - repeat_rate = ms_to_ticks(KBD_REPEAT_RATE); - kbd_rptStatus = KS_REPEAT; - } - else - key = 0; - } - else - kbd_rptStatus = KS_IDLE; - break; - - case KS_REPEAT: - if (key & kbd_rpt_mask) - { - if (now - repeat_time > repeat_rate) - { - /* Enqueue a new event in the buffer */ - key = (key & kbd_rpt_mask) | K_REPEAT; - repeat_time = now; - - /* Repeat rate acceleration */ - if (repeat_rate > ms_to_ticks(KBD_REPEAT_MAXRATE)) - repeat_rate -= ms_to_ticks(KBD_REPEAT_ACCEL); - } - else - key = 0; - } - else - kbd_rptStatus = KS_IDLE; - - break; - } - - return key; -} - - -MOD_DEFINE(kbd) - -/** - * Initialize keyboard ports and softtimer - */ -void kbd_init(void) -{ -#if CONFIG_KBD_BEEP - MOD_CHECK(buzzer); -#endif - - KBD_HW_INIT; - - /* Init handlers lists */ - LIST_INIT(&kbd_handlers); - LIST_INIT(&kbd_rawHandlers); - - /* Add debounce keyboard handler */ - kbd_debHandler.hook = kbd_debHandlerFunc; - kbd_debHandler.pri = 100; /* high priority */ - kbd_debHandler.flags = KHF_RAWKEYS; - kbd_addHandler(&kbd_debHandler); - - #if CONFIG_KBD_LONGPRESS - /* Add long pression keyboard handler */ - kbd_lngHandler.hook = kbd_lngHandlerFunc; - kbd_lngHandler.pri = 90; /* high priority */ - kbd_lngHandler.flags = KHF_RAWKEYS; - kbd_addHandler(&kbd_lngHandler); - #endif - - /* Add repeat keyboard handler */ - kbd_rptHandler.hook = kbd_rptHandlerFunc; - kbd_rptHandler.pri = 80; /* high priority */ - kbd_rptHandler.flags = KHF_RAWKEYS; - kbd_addHandler(&kbd_rptHandler); - - /* Add default keyboard handler */ - kbd_defHandler.hook = kbd_defHandlerFunc; - kbd_defHandler.pri = -128; /* lowest priority */ - kbd_addHandler(&kbd_defHandler); - -#if CONFIG_KBD_OBSERVER - observer_InitSubject(&kbd_subject); -#endif - -#if CONFIG_KBD_POLL == KBD_POLL_SOFTINT - - MOD_CHECK(timer); - - /* Add kbd handler to soft timers list */ - event_initSoftInt(&kbd_timer.expire, kbd_softint, NULL); - timer_setDelay(&kbd_timer, ms_to_ticks(KBD_CHECK_INTERVAL)); - timer_add(&kbd_timer); - -#elif CONFIG_KBD_POLL == CONFIG_POLL_FREERTOS - - /* Create a timer specific thread */ - xTaskCreate(kbd_task, "kbd", CONFIG_STACK_KBD, - NULL, CONFIG_PRI_KBD, NULL); - -#else - #error "Define keyboard poll method" -#endif - - MOD_INIT(kbd); -} diff --git a/drv/kbd.h b/drv/kbd.h deleted file mode 100644 index c1904716..00000000 --- a/drv/kbd.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file - * - * - * \brief Keyboard driver (interface) - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \author Francesco Sacchi - */ - -#ifndef DRV_KBD_H -#define DRV_KBD_H - -#include -#include -#include -#include // CONFIG_KBD_OBSERVER - -/** - * \name Keyboard polling modes. - * - * Define CONFIG_KBD_POLL to one of these. - * - * \{ - */ -#define KBD_POLL_SOFTINT 1 -#define KBD_POLL_FREERTOS 2 -/* \} */ - -/** - * Keyboard handler descriptor - */ -typedef struct KbdHandler -{ - Node link; - keymask_t (*hook)(keymask_t); /**< Hook function */ - int8_t pri; /**< Priority in input queue */ - uint8_t flags; /**< See below for definitions */ -} KbdHandler; - -#define KHF_RAWKEYS BV(0) /**< Handler gets raw key events */ - - -void kbd_init(void); -keymask_t kbd_peek(void); -keymask_t kbd_get(void); -keymask_t kbd_get_timeout(mtime_t timeout); -void kbd_addHandler(struct KbdHandler *handler); -void kbd_remHandler(struct KbdHandler *handler); -keymask_t kbd_setRepeatMask(keymask_t mask); - -#if CONFIG_KBD_OBSERVER - struct Subject; - - /** Subject structure for keyboard observers. */ - extern struct Subject kbd_subject; - - enum - { - /* Event for key presses. */ - KBD_EVENT_KEY = 0x100 - }; -#endif - -#endif /* DRV_KBD_H */ diff --git a/drv/kdebug.c b/drv/kdebug.c deleted file mode 100644 index c461b728..00000000 --- a/drv/kdebug.c +++ /dev/null @@ -1,289 +0,0 @@ -/** - * \file - * - * - * \brief General pourpose debug support for embedded systems (implementation). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#include -#include -#include - -#include /* for BV() */ -#include - -#include -#warning what about these? -//#include /* for CLOCK_FREQ */ -//#include /* Required for bus macros overrides */ - -#include /* for _formatted_write() */ -#include - -#ifdef _DEBUG - -#if CPU_HARVARD && !defined(_PROGMEM) - #error This module build correctly only in program memory! -#endif - - -#if OS_HOSTED - #include - #define KDBG_WAIT_READY() do { /*nop*/ } while(0) - #define KDBG_WRITE_CHAR(c) putc((c), stderr) - #define KDBG_MASK_IRQ(old) do { (void)(old); } while(0) - #define KDBG_RESTORE_IRQ(old) do { /*nop*/ } while(0) - typedef char kdbg_irqsave_t; /* unused */ - - #define kdbg_hw_init() do {} while (0) ///< Not needed - - #if CONFIG_KDEBUG_PORT == 666 - #error BITBANG debug console missing for this platform - #endif -#else - #include CPU_CSOURCE(kdebug) -#endif - - -void kdbg_init(void) -{ - /* Init debug hw */ - kdbg_hw_init(); - kputs("\n\n*** BeRTOS DBG START ***\n"); -} - - -/** - * Output one character to the debug console - */ -static void __kputchar(char c, UNUSED_ARG(void *, unused)) -{ - /* Poll while serial buffer is still busy */ - KDBG_WAIT_READY(); - - /* Send '\n' as '\r\n' for dumb terminals */ - if (c == '\n') - { - KDBG_WRITE_CHAR('\r'); - KDBG_WAIT_READY(); - } - - KDBG_WRITE_CHAR(c); -} - - -void kputchar(char c) -{ - /* Mask serial TX intr */ - kdbg_irqsave_t irqsave; - KDBG_MASK_IRQ(irqsave); - - __kputchar(c, 0); - - /* Restore serial TX intr */ - KDBG_RESTORE_IRQ(irqsave); -} - - -static void PGM_FUNC(kvprintf)(const char * PGM_ATTR fmt, va_list ap) -{ -#if CONFIG_PRINTF - /* Mask serial TX intr */ - kdbg_irqsave_t irqsave; - KDBG_MASK_IRQ(irqsave); - - PGM_FUNC(_formatted_write)(fmt, __kputchar, 0, ap); - - /* Restore serial TX intr */ - KDBG_RESTORE_IRQ(irqsave); -#else - /* A better than nothing printf() surrogate. */ - PGM_FUNC(kputs)(fmt); -#endif /* CONFIG_PRINTF */ -} - -void PGM_FUNC(kprintf)(const char * PGM_ATTR fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - PGM_FUNC(kvprintf)(fmt, ap); - va_end(ap); -} - -void PGM_FUNC(kputs)(const char * PGM_ATTR str) -{ - char c; - - /* Mask serial TX intr */ - kdbg_irqsave_t irqsave; - KDBG_MASK_IRQ(irqsave); - - while ((c = PGM_READ_CHAR(str++))) - __kputchar(c, 0); - - KDBG_RESTORE_IRQ(irqsave); -} - - -/** - * Cheap function to print small integers without using printf(). - */ -int kputnum(int num) -{ - int output_len = 0; - int divisor = 10000; - int digit; - - do - { - digit = num / divisor; - num %= divisor; - - if (digit || output_len || divisor == 1) - { - kputchar(digit + '0'); - ++output_len; - } - } - while (divisor /= 10); - - return output_len; -} - - -static void klocation(const char * PGM_ATTR file, int line) -{ - PGM_FUNC(kputs)(file); - kputchar(':'); - kputnum(line); - PGM_FUNC(kputs)(PGM_STR(": ")); -} - -int PGM_FUNC(__assert)(const char * PGM_ATTR cond, const char * PGM_ATTR file, int line) -{ - klocation(file, line); - PGM_FUNC(kputs)(PGM_STR("Assertion failed: ")); - PGM_FUNC(kputs)(cond); - kputchar('\n'); - BREAKPOINT; - return 1; -} - -/* - * Unfortunately, there's no way to get __func__ in - * program memory, so we waste quite a lot of RAM in - * AVR and other Harvard processors. - */ -void PGM_FUNC(__trace)(const char *name) -{ - PGM_FUNC(kprintf)(PGM_STR("%s()\n"), name); -} - -void PGM_FUNC(__tracemsg)(const char *name, const char * PGM_ATTR fmt, ...) -{ - va_list ap; - - PGM_FUNC(kprintf)(PGM_STR("%s(): "), name); - va_start(ap, fmt); - PGM_FUNC(kvprintf)(fmt, ap); - va_end(ap); - kputchar('\n'); -} - -int PGM_FUNC(__invalid_ptr)(void *value, const char * PGM_ATTR name, const char * PGM_ATTR file, int line) -{ - klocation(file, line); - PGM_FUNC(kputs)(PGM_STR("Invalid ptr: ")); - PGM_FUNC(kputs)(name); - #if CONFIG_PRINTF - PGM_FUNC(kprintf)(PGM_STR(" = 0x%p\n"), value); - #else - (void)value; - kputchar('\n'); - #endif - return 1; -} - - -void __init_wall(long *wall, int size) -{ - while(size--) - *wall++ = WALL_VALUE; -} - - -int PGM_FUNC(__check_wall)(long *wall, int size, const char * PGM_ATTR name, const char * PGM_ATTR file, int line) -{ - int i, fail = 0; - - for (i = 0; i < size; i++) - { - if (wall[i] != WALL_VALUE) - { - klocation(file, line); - PGM_FUNC(kputs)(PGM_STR("Wall broken: ")); - PGM_FUNC(kputs)(name); - #if CONFIG_PRINTF - PGM_FUNC(kprintf)(PGM_STR("[%d] (0x%p) = 0x%lx\n"), i, wall + i, wall[i]); - #else - kputchar('\n'); - #endif - fail = 1; - } - } - - return fail; -} - - -#if CONFIG_PRINTF - -/** - * Dump binary data in hex - */ -void kdump(const void *_buf, size_t len) -{ - const unsigned char *buf = (const unsigned char *)_buf; - - while (len--) - kprintf("%02X", *buf++); - kputchar('\n'); -} - -#endif /* CONFIG_PRINTF */ - -#endif /* _DEBUG */ diff --git a/drv/lcd_gfx.h b/drv/lcd_gfx.h deleted file mode 100644 index 63fe28d2..00000000 --- a/drv/lcd_gfx.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * \file - * - * - * \version $Id: lcd_gfx.h,v 1.6 2006/07/19 12:56:25 bernie Exp $ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief Displaytech 32122A LCD driver - */ -#ifndef LCD_GFX_H -#define LCD_GFX_H - -/* Predefined LCD PWM contrast values */ -#define LCD_DEF_PWM 145 -#define LCD_MAX_PWM 505 -#define LCD_MIN_PWM 130 - -/* Display bitmap dims */ -#define LCD_WIDTH 128 -#define LCD_HEIGHT 64 - -/* fwd decl */ -struct Bitmap; - -extern struct Bitmap lcd_bitmap; - -void lcd_init(void); -void lcd_setPwm(int duty); -void lcd_blitBitmap(struct Bitmap *bm); - -#endif /* LCD_GFX_H */ diff --git a/drv/lcd_gfx_qt.cpp b/drv/lcd_gfx_qt.cpp deleted file mode 100644 index e42be22d..00000000 --- a/drv/lcd_gfx_qt.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Custom control for graphics LCD emulation (interface) - */ - -#include "lcd_gfx_qt.h" -#include -#include -#include // CONFIG_BITMAP_FMT - -#include -#include -#include -#include - -// Display colors -#define LCD_FG_COLOR 0x0, 0x0, 0x0 -#define LCD_BG_COLOR 0xBB, 0xCC, 0xBB - - -EmulLCD::EmulLCD(QWidget *parent, const char *name) : - QFrame(parent, name, Qt::WRepaintNoErase | Qt::WResizeNoErase), - fg_color(LCD_FG_COLOR), - bg_color(LCD_BG_COLOR) -{ - // initialize bitmap - memset(raster, 0xAA, sizeof(raster)); - - // set widget frame - setFrameStyle(QFrame::Panel | QFrame::Sunken); - frame_width = frameWidth(); -} - - -EmulLCD::~EmulLCD() -{ - // nop -} - - -QSizePolicy EmulLCD::sizePolicy() const -{ - return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, false); -} - - -QSize EmulLCD::sizeHint() const -{ - return QSize( - WIDTH + frame_width * 2, - HEIGHT + frame_width * 2); -} - - -void EmulLCD::paintEvent(QPaintEvent * /*event*/) -{ - QPainter p(this); - QImage img(raster, WIDTH, HEIGHT, 1, NULL, 0, QImage::BigEndian); - - p.setBackgroundMode(Qt::OpaqueMode); - p.setPen(fg_color); - p.setBackgroundColor(bg_color); - p.drawImage(frame_width, frame_width, img); -} - -void EmulLCD::writeRaster(uint8_t *new_raster) -{ -#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB - - /* Straight copy */ - memcpy(raster, new_raster, sizeof(raster)); - -#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB - - /* Rotation */ - for (int y = 0; y < HEIGHT; ++y) - { - for (int xbyte = 0; xbyte < WIDTH/8; ++xbyte) - { - uint8_t v = 0; - for (int xbit = 0; xbit < 8; ++xbit) - v |= (new_raster[(xbyte * 8 + xbit) + (y / 8) * WIDTH] & (1 << (y%8)) ) - ? 0 : (1 << (7 - xbit)); - - raster[y * ((WIDTH + 7) / 8) + xbyte] = v; - } - } - -#else - #error Unsupported bitmap format -#endif - - repaint(); -} - - - -#include -#include - -DECLARE_WALL(wall_before_raster, WALL_SIZE) -/** - * Raster buffer to draw into. - * - * Bits in the bitmap bytes have vertical orientation, - * as required by the LCD driver. - */ -static uint8_t lcd_raster[RAST_SIZE(EmulLCD::WIDTH, EmulLCD::HEIGHT)]; -DECLARE_WALL(wall_after_raster, WALL_SIZE) - -/** Default LCD bitmap */ -struct Bitmap lcd_bitmap; - -/*extern "C"*/ void lcd_init(void) -{ - //FIXME INIT_WALL(wall_before_raster); - //FIXME INIT_WALL(wall_after_raster); - gfx_bitmapInit(&lcd_bitmap, lcd_raster, EmulLCD::WIDTH, EmulLCD::HEIGHT); - gfx_bitmapClear(&lcd_bitmap); -} - -/*extern "C"*/ void lcd_blitBitmap(Bitmap *bm) -{ - //FIXME CHECK_WALL(wall_before_raster); - //FIXME CHECK_WALL(wall_after_raster); - emul->emulLCD->writeRaster(bm->raster); -} - -#include "lcd_gfx_qt_moc.cpp" - diff --git a/drv/lcd_gfx_qt.h b/drv/lcd_gfx_qt.h deleted file mode 100644 index 7893dc73..00000000 --- a/drv/lcd_gfx_qt.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Custom control for graphics LCD emulation (interface) - */ - -/*#* - *#* $Log$ - *#* Revision 1.5 2006/05/28 12:17:57 bernie - *#* Drop almost all the Qt3 cruft. - *#* - *#* Revision 1.4 2006/02/20 02:00:40 bernie - *#* Port to Qt 4.1. - *#* - *#* Revision 1.3 2006/02/15 09:13:16 bernie - *#* Switch to BITMAP_FMT_PLANAR_V_LSB. - *#* - *#* Revision 1.2 2006/02/10 12:33:51 bernie - *#* Make emulator display a bit larger. - *#* - *#* Revision 1.1 2006/01/16 03:51:35 bernie - *#* Add LCD Qt emulator. - *#* - *#*/ - -#ifndef DRV_LCD_GFX_QT_H -#define DRV_LCD_GFX_QT_H - -#include -#include - -// fwd decls -class QSizePolicy; -class QPaintEvent; -class QResizeEvent; - - -class EmulLCD : public QFrame -{ - Q_OBJECT - -public: -// Attributes - enum { WIDTH = 128, HEIGHT = 64 }; - -// Construction - EmulLCD(QWidget *parent = 0, const char *name = 0); - virtual ~EmulLCD(); - -// Base class overrides -protected: - virtual QSizePolicy sizePolicy() const; - virtual QSize sizeHint() const; - virtual void paintEvent(QPaintEvent *event); - -// Operations -public: - void writeRaster(uint8_t *raster); - -// Implementation -protected: - /// Frame thickness - int frame_width; - - /// LCD colors - QColor fg_color, bg_color; - - /// Pixel storage - unsigned char raster[(WIDTH * HEIGHT) / 8]; -}; - -#endif // DRV_LCD_GFX_QT_H diff --git a/drv/lcd_gfx_test.c b/drv/lcd_gfx_test.c deleted file mode 100644 index 121555f7..00000000 --- a/drv/lcd_gfx_test.c +++ /dev/null @@ -1,98 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief dot-matrix LCD test. - */ - -/*#* - *#* $Log$ - *#* Revision 1.3 2006/01/17 23:00:26 bernie - *#* Don't use hardcoded coordinates. - *#* - *#* Revision 1.2 2006/01/17 02:31:57 bernie - *#* Test gfx with the usual pentagons. - *#* - *#* Revision 1.1 2006/01/16 03:51:35 bernie - *#* Add LCD Qt emulator. - *#* - *#*/ - -#include -#include -#include - -static void magic(struct Bitmap *bitmap, coord_t x, coord_t y) -{ - static const coord_t coords[] = { 120, 34, 90, 90, 30, 90, 0, 34, 60, 0, 90, 90, 0, 34, 120, 34, 30, 90, 60, 0 }; - unsigned int i; - - gfx_moveTo(bitmap, coords[countof(coords)-2]/2 + x, coords[countof(coords)-1]/3 + y); - for (i = 0; i < countof(coords); i += 2) - gfx_lineTo(bitmap, coords[i]/2 + x, coords[i+1]/3 + y); -} - -int main(int argc, char *argv[]) -{ - emul_init(&argc, argv); - lcd_init(); - - coord_t x = 0, y = LCD_WIDTH / 2; - coord_t xdir = +1, ydir = -1; - Bitmap *bm = &lcd_bitmap; - - for(;;) - { - gfx_bitmapClear(bm); - gfx_setClipRect(bm, 0, 0, bm->width, bm->height); - gfx_rectDraw(bm, 10, 10, bm->width-10, bm->height-10); - gfx_setClipRect(bm, 11, 11, bm->width-11, bm->height-11); - magic(bm, x, y); - - x += xdir; - y += ydir; - if (x >= bm->width) xdir = -1; - if (x <= -50) xdir = +1; - if (y >= bm->height) ydir = -1; - if (y <= -50) ydir = +1; - - lcd_blit_bitmap(bm); - emul_idle(); - usleep(10000); - } - - emul_cleanup(); - return 0; -} diff --git a/drv/lcd_hd44.c b/drv/lcd_hd44.c deleted file mode 100644 index 1c2e52f7..00000000 --- a/drv/lcd_hd44.c +++ /dev/null @@ -1,457 +0,0 @@ -/** - * \file - * - * - * \brief LM044L type LCD hardware module (impl.) - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#include "lcd_hd44.h" -#include "hw_lcd.h" -#include -#include - -#if defined(LCD_READ_H) && defined(LCD_READ_L) && defined(LCD_WRITE_H) && defined(LCD_WRITE_L) - #define CONFIG_LCD_4BIT 1 -#elif defined(LCD_READ) && defined(LCD_WRITE) - #define CONFIG_LCD_4BIT 0 -#else - #error Incomplete or missing LCD_READ/LCD_WRITE macros -#endif - -/** Flag di stato del display */ -#define LCDF_BUSY BV(7) - -#if CONFIG_LCD_ADDRESS_FAST == 1 -#define lcd_address(x) lcd_address[x] -/** - * Addresses of LCD display character positions, expanded - * for faster access (DB7 = 1). - */ -static const uint8_t lcd_address[] = -{ - /* row 0 */ - 0x80, 0x81, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8A, 0x8B, - 0x8C, 0x8D, 0x8E, 0x8F, -#if LCD_COLS > 16 - 0x90, 0x91, 0x92, 0x93, -#endif - - /* row 1 */ - 0xC0, 0xC1, 0xC2, 0xC3, - 0xC4, 0xC5, 0xC6, 0xC7, - 0xC8, 0xC9, 0xCA, 0xCB, - 0xCC, 0xCD, 0xCE, 0xCF, -#if LCD_COLS > 16 - 0xD0, 0xD1, 0xD2, 0xD3, -#endif - -#if LCD_ROWS > 2 - /* row 2 */ - 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9A, 0x9B, - 0x9C, 0x9D, 0x9E, 0x9F, - 0xA0, 0xA1, 0xA2, 0xA3, -#if LCD_COLS > 16 - 0xA4, 0xA5, 0xA6, 0xA7, -#endif - - /* row 3 */ - 0xD4, 0xD5, 0xD6, 0xD7, - 0xD8, 0xD9, 0xDA, 0xDB, - 0xDC, 0xDD, 0xDE, 0xDF, - 0xE0, 0xE1, 0xE2, 0xE3, -#if LCD_COLS > 16 - 0xE4, 0xE5, 0xE6, 0xE7, -#endif - -#endif /* LCD_ROWS > 2 */ -}; - -STATIC_ASSERT(countof(lcd_address) == LCD_ROWS * LCD_COLS); -#else /* CONFIG_LCD_ADDRESS_FAST == 0 */ - -static const uint8_t col_address[] = -{ - 0x80, - 0xC0, -#if LCD_ROWS > 2 - 0x94, - 0xD4 -#endif -}; -STATIC_ASSERT(countof(col_address) == LCD_ROWS); -/** - * Addresses of LCD display character positions, calculated runtime to save RAM - */ -static uint8_t lcd_address(uint8_t addr) -{ - return col_address[addr / LCD_COLS] + addr % LCD_COLS; -} -#endif /* CONFIG_LCD_ADDRESS_FAST */ - -/** - * Current display position. We remember this to optimize - * LCD output by avoiding to set the address every time. - */ -static lcdpos_t lcd_current_addr; - - -#if !defined(ARCH_EMUL) || !(ARCH & ARCH_EMUL) -/* __________________ - * RS - * - * R/W __________________ - * _______ - * ENA _____/ \____ - * - * DATA -<================ - */ -INLINE void lcd_dataWrite(uint8_t data) -{ -#if CONFIG_LCD_4BIT - /* Write high nibble */ - LCD_WRITE_H(data); - LCD_SET_E; - LCD_DELAY_WRITE; - LCD_CLR_E; - LCD_DELAY_WRITE; - - /* Write low nibble */ - LCD_WRITE_L(data); - LCD_SET_E; - LCD_DELAY_WRITE; - LCD_CLR_E; - LCD_DELAY_WRITE; - -#else /* !CONFIG_LCD_4BIT */ - - /* Write data */ - LCD_WRITE(data); - LCD_SET_E; - LCD_DELAY_WRITE; - LCD_CLR_E; - LCD_DELAY_WRITE; - -#endif /* !CONFIG_LCD_4BIT */ -} - -/* __________________ - * RS - * ____________ - * R/W __/ \__ - * _______ - * ENA _____/ \____ - * ______ ____ - * DATA X/ \====/ - */ -INLINE uint8_t lcd_dataRead(void) -{ - uint8_t data; - - LCD_SET_RD; - LCD_DB_IN; /* Set bus as input! */ - LCD_DELAY_READ; - -#if CONFIG_LCD_4BIT - - /* Read high nibble */ - LCD_SET_E; - LCD_DELAY_READ; - data = LCD_READ_H; - LCD_CLR_E; - LCD_DELAY_READ; - - /* Read low nibble */ - LCD_SET_E; - LCD_DELAY_READ; - data |= LCD_READ_L; - LCD_CLR_E; - LCD_DELAY_READ; - -#else /* !CONFIG_LCD_4BIT */ - - /* Read data */ - LCD_SET_E; - LCD_DELAY_READ; - data = LCD_READ; - LCD_CLR_E; - LCD_DELAY_READ; - -#endif /* !CONFIG_LCD_4BIT */ - - LCD_CLR_RD; - LCD_DB_OUT; /* Reset bus as output! */ - - return data; -} - -/* ___ __ - * RS \___________/ - * - * READ __________________ - * _______ - * ENA _____/ \____ - * - * DATA --<=============== - */ -INLINE void lcd_regWrite(uint8_t data) -{ - LCD_CLR_RS; - lcd_dataWrite(data); - LCD_SET_RS; -} - -/* __ _ - * RS \_____________/ - * ___________ - * READ ___/ \__ - * _______ - * ENA _____/ \____ - * ______ ____ - * DATA X/ \====/ - */ -INLINE uint8_t lcd_regRead(void) -{ - uint8_t data; - - LCD_CLR_RS; - data = lcd_dataRead(); - LCD_SET_RS; - return data; -} - -#if CONFIG_LCD_4BIT - -INLINE void lcd_mode4Bit(void) -{ - LCD_CLR_RS; - - LCD_WRITE_H(LCD_CMD_SETFUNC); - LCD_SET_E; - LCD_DELAY_WRITE; - LCD_CLR_E; - LCD_DELAY_WRITE; - - LCD_SET_RS; -} - -#endif /* CONFIG_LCD_4BIT */ - -#else /* ARCH_EMUL */ - -extern void Emul_LCDWriteReg(uint8_t d); -extern uint8_t Emul_LCDReadReg(void); -extern void Emul_LCDWriteData(uint8_t d); -extern uint8_t Emul_LCDReadData(void); - -#define lcd_regWrite(d) Emul_LCDWriteReg(d) -#define lcd_regRead(d) Emul_LCDReadReg() -#define lcd_dataWrite(d) Emul_LCDWriteData(d) -#define lcd_dataRead(d) Emul_LCDReadData() - -#endif /* ARCH_EMUL */ - - -/** - * Wait until the LCD busy flag clears. - */ -void lcd_waitBusy(void) -{ - for (;;) - { - uint8_t val = lcd_regRead(); - if (!(val & LCDF_BUSY)) - break; - } -} - - -/** - * Move the cursor to \a addr, only if not already there. - */ -void lcd_moveTo(uint8_t addr) -{ - if (addr != lcd_current_addr) - { - lcd_waitBusy(); - lcd_regWrite(lcd_address(addr)); - lcd_current_addr = addr; - } -} - - -/** - * Write a value in LCD data register, waiting for the busy flag. - */ -void lcd_setReg(uint8_t val) -{ - lcd_waitBusy(); - lcd_regWrite(val); -} - -#include -/** - * Write the character \a c on display address \a addr. - * - * NOTE: argh, the HD44 lcd type is a bad beast: our - * move/write -> write optimization requires this mess - * because display lines are interleaved! - */ -void lcd_putc(uint8_t addr, uint8_t c) -{ - if (addr != lcd_current_addr) - lcd_setReg(lcd_address(addr)); - - lcd_waitBusy(); - lcd_dataWrite(c); - lcd_current_addr = addr + 1; - - /* If we are at end of display wrap the address to 0 */ - if (lcd_current_addr == LCD_COLS * LCD_ROWS) - lcd_current_addr = 0; - - /* If we are at the end of a row put the cursor at the beginning of the next */ - if (!(lcd_current_addr % LCD_COLS)) - lcd_setReg(lcd_address(lcd_current_addr)); -} - - -/** - * Remap the glyph of a character. - * - * glyph - bitmap of 8x8 bits. - * code - must be 0-7 for the Hitachi LCD-II controller. - */ -void lcd_remapChar(const char *glyph, char code) -{ - int i; - - /* Set CG RAM address */ - lcd_setReg((uint8_t)((1<<6) | (code << 3))); - - /* Write bitmap data */ - for (i = 0; i < 8; i++) - { - lcd_waitBusy(); - lcd_dataWrite(glyph[i]); - } - - /* Move back to original address */ - lcd_setReg(lcd_address(lcd_current_addr)); -} - - -#if 0 /* unused */ -void lcd_remapfont(void) -{ - static const char lcd_glyphs[8] = - { - 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x04, 0x00 /* up arrow */ - }; - int i; - - for (i = 0; i < 15; i++) - lcd_remapChar(i, bernie_char); - - - lcd_setAddr(lcd_DefLayer, 0); - for (i = 0; i < 80; i++) - lcd_putCharUnlocked(i); -} -#endif /* unused */ - -void lcd_hw_init(void) -{ - lcd_bus_init(); - - timer_delay(50); - -#if CONFIG_LCD_4BIT - lcd_mode4Bit(); - timer_delay(2); -#endif /* CONFIG_LCD_4BIT */ - - lcd_regWrite(LCD_CMD_SETFUNC); - timer_delay(2); - - lcd_regWrite(LCD_CMD_DISPLAY_ON); - timer_delay(2); - - lcd_regWrite(LCD_CMD_CLEAR); - timer_delay(2); - -#if !CONFIG_LCD_4BIT - lcd_regWrite(LCD_CMD_RESET_DDRAM); // 4 bit mode doesn't allow char reprogramming -#endif - lcd_regWrite(LCD_CMD_DISPLAYMODE); - timer_delay(2); -} - -#if CONFIG_TEST - -void lcd_hw_test(void) -{ - lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 3); - timer_delay(1); - kprintf("3 -> %02X\n", lcd_regRead()); - timer_delay(1); - - for (int i = 0; i < 10; i++) - { - lcd_dataWrite('c'); - timer_delay(1); - kprintf("addr = %02X\n", lcd_regRead()); - timer_delay(1); - } - - lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x4a); - timer_delay(1); - kprintf("4A -> %02X\n", lcd_regRead()); - timer_delay(1); - - lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x52); - timer_delay(1); - kprintf("52 -> %02X\n", lcd_regRead()); - timer_delay(1); - - lcd_regWrite(LCD_CMD_SET_DDRAMADDR | 0x1F); - timer_delay(1); - kprintf("1F -> %02X\n", lcd_regRead()); - timer_delay(1); -} - -#endif /* CONFIG_TEST */ diff --git a/drv/lcd_hd44.h b/drv/lcd_hd44.h deleted file mode 100644 index 0ebba974..00000000 --- a/drv/lcd_hd44.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * \file - * - * - * \brief Hitachi HD44780 and clones LCD module (interface) - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#ifndef DRV_LCD_HD44_H -#define DRV_LCD_HD44_H - -#include -#include /* For stdint types */ - -/** - * \name Display dimensions (in chars) - * \{ - */ -#define LCD_ROWS 2 -#define LCD_COLS 16 -/* \} */ - -/** - * \name Hitachi HD44 commands. - * \{ - */ -#define LCD_CMD_DISPLAY_INI 0x30 - -#if CONFIG_LCD_4BIT - #define LCD_CMD_SETFUNC 0x28 /**< 4 bits, 2 lines, 5x7 dots */ -#else - #define LCD_CMD_SETFUNC 0x38 /**< 8 bits, 2 lines, 5x7 dots */ -#endif - -#define LCD_CMD_DISPLAY_ON 0x0F /**< Switch on display */ -#define LCD_CMD_DISPLAY_OFF 0x08 /**< Switch off display */ -#define LCD_CMD_CLEAR 0x01 /**< Clear display */ -#define LCD_CMD_CURSOR_BLOCK 0x0D /**< Show cursor (block) */ -#define LCD_CMD_CURSOR_LINE 0x0F /**< Show cursor (line) */ -#define LCD_CMD_CURSOR_OFF 0x0C /**< Hide cursor */ -#define LCD_CMD_DISPLAYMODE 0x06 -#define LCD_CMD_SET_CGRAMADDR 0x40 -#define LCD_CMD_RESET_DDRAM 0x80 -#define LCD_CMD_SET_DDRAMADDR 0x80 -#define LCD_CMD_DISPLAY_SHIFT 0x18 -#define LCD_CMD_MOVESHIFT_LEFT 0x00 -#define LCD_CMD_MOVESHIFT_RIGHT 0x04 -/*\}*/ - -/** Type for combined LCD cursor position (x,y). */ -typedef uint8_t lcdpos_t; - -void lcd_waitBusy(void); -void lcd_moveTo(uint8_t addr); -void lcd_setReg(uint8_t val); -void lcd_putc(uint8_t a, uint8_t c); -void lcd_remapChar(const char *glyph, char code); -void lcd_hw_init(void); -void lcd_hw_test(void); - -#endif /* DRV_LCD_HD44_H */ diff --git a/drv/lcd_lm44_qt.cpp b/drv/lcd_lm44_qt.cpp deleted file mode 100644 index a8942699..00000000 --- a/drv/lcd_lm44_qt.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Custom Qt widget for emulating a graphics LCD display (implementation) - */ - -/*#* - *#* $Log$ - *#* Revision 1.1 2006/01/16 03:51:35 bernie - *#* Add LCD Qt emulator. - *#* - *#*/ - -#include -#include -#include -#include -#include "EmulLCD.h" -#include "Emul.h" - - -// Display colors -#define LCD_FG_COLOR 0x0, 0x0, 0x0 -#define LCD_BG_COLOR 0xBB, 0xCC, 0xBB - - -EmulLCD::EmulLCD(QWidget *parent, const char *name) : - QFrame(parent, name, WRepaintNoErase | WResizeNoErase), - lcd_font("courier", 18), - fg_color(LCD_FG_COLOR), - bg_color(LCD_BG_COLOR), - cr_row(0), - cr_col(0), - cgramaddr(-1), - show_cursor(true) -{ - // initialize DDRAM - memcpy(ddram, - "01234567890123456789" - "abcdefghijhlmnopqrst" - "ABCDEFGHIJKLMNOPQRST" - "!@#$%^&*()_+|{}':?><", - sizeof(ddram)); - - // setup font - lcd_font.setFixedPitch(true); - setFont(lcd_font); - - // get exact font size - QFontMetrics fm(lcd_font); - font_width = fm.width(QChar(' ')); - font_height = fm.height(); - - // set widget frame - setFrameStyle(QFrame::Panel | QFrame::Sunken); -// setLineWidth(2); - frame_width = frameWidth(); -} - - -EmulLCD::~EmulLCD() -{ - // nop -} - - -QSizePolicy EmulLCD::sizePolicy() const -{ - return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, false); -} - - -QSize EmulLCD::sizeHint() const -{ - return QSize( - font_width * COLS + frame_width * 2, - font_height * ROWS + frame_width * 2); -} - - -void EmulLCD::drawContents(QPainter *p) -{ - RedrawText(*p); -} - - -void EmulLCD::SetPainter(QPainter & p) -{ - p.setBackgroundMode(OpaqueMode); - p.setPen(fg_color); - p.setBackgroundColor(bg_color); -} - - -void EmulLCD::RedrawText(QPainter & p) -{ - int r, c; - - SetPainter(p); - - for (r = 0; r < ROWS; r++) - for (c = 0; c < COLS; c++) - PrintChar(p, r, c); -} - - -void EmulLCD::PrintChar(QPainter & p, int row, int col) -{ - // Fetch char from DD RAM - unsigned char c = ddram[row][col]; - - // Map some Hitachi characters to ISO Latin1 - switch(c) - { - case 0xDF: - c = 0xBA; // "degrees" glyph - break; - - case 0xE4: - c = 0xB5; // "micro" glyph - break; - - default: // all others - break; - } - - // Draw char on display - int x = col * font_width + frame_width; - int y = row * font_height + frame_width; - bool restore_colors = false; - - if (show_cursor && (row == cr_row) && (col == cr_col)) - { - // Exchange FG/BG colors - p.setPen(bg_color); - p.setBackgroundColor(fg_color); - restore_colors = true; - } - - p.drawText(x, y, x + font_width, y + font_height, 0 /*tf*/, - QString(QChar(c)), 1); - - if (restore_colors) - { - // Restore FG/BG colors - p.setPen(fg_color); - p.setBackgroundColor(bg_color); - } -} - - -void EmulLCD::MoveCursor(int r, int c) -{ - // Save old cursor position - int old_row = cr_row; - int old_col = cr_col; - - // Move the cursor - cgramaddr = -1; - cr_row = r; - cr_col = c; - - if (show_cursor && (old_col != cr_col || old_row != cr_row)) - { - QPainter p(this); - SetPainter(p); - - // Draw new cursor - PrintChar(p, cr_row, cr_col); - - // Erase old cursor - PrintChar(p, old_row, old_col); - } -} - - -void EmulLCD::ShowCursor(bool show) -{ - show_cursor = show; - - // Draw (or erase) cursor - QPainter p(this); - SetPainter(p); - PrintChar(p, cr_row, cr_col); -} - - -void EmulLCD::AdvanceCursor() -{ - // Move the cursor - if (cr_col == COLS - 1) - { - if (cr_row == ROWS - 1) - MoveCursor(0, 0); - else - MoveCursor(cr_row + 1, 0); - } - else - MoveCursor(cr_row, cr_col + 1); -} - - -void EmulLCD::PutChar(unsigned char c) -{ - if (cgramaddr != -1) - { - // Write data in CGRAM - cgram[cgramaddr] = c; - - // Auto increment CGRAM address - cgramaddr = (cgramaddr + 1) & 0x3F; - } - else - { - // Writing in DDRAM - ddram[cr_row][cr_col] = c; - - // Update display - { - QPainter p(this); - SetPainter(p); - PrintChar(p, cr_row, cr_col); - } - AdvanceCursor(); - } -} - - -char EmulLCD::GetChar() -{ - char c = ddram[cr_row][cr_col]; - AdvanceCursor(); - return c; -} - - -void EmulLCD::Clear() -{ - memset(ddram, ' ', sizeof(ddram)); - cr_row = cr_col = 0; - - QPainter p(this); - RedrawText(p); -} - - -void EmulLCD::SetCGRamAddr(unsigned char addr) -{ - cgramaddr = addr & (sizeof(cgram) - 1); -} - - -// Hitachi LM044L register-level emulation - -#define INI_DISPLAY 0x30 -#define INI_OP_DISP 0x38 /* 8 bits, 2 lines, 5x7 dots */ -#define ON_DISPLAY 0x0F /* Switch on display */ -#define OFF_DISPLAY 0x08 /* Switch off display */ -#define CLR_DISPLAY 0x01 /* Clear display */ -#define CURSOR_BLOCK 0x0D /* Show cursor (block) */ -#define CURSOR_LINE 0x0F /* Show cursor (line) */ -#define CURSOR_OFF 0x0C /* Hide cursor */ -#define MODE_DISPL 0x06 -#define SHIFT_DISPLAY 0x18 -#define MOVESHIFT_LEFT 0x00 -#define MOVESHIFT_RIGHT 0x04 -#define LCD_CGRAMADDR (1<<6) -#define LCD_DDRAMADDR (1<<7) - - -extern "C" void Emul_LCDWriteReg(unsigned char d) -{ - static const unsigned char lcd_rowaddress[EmulLCD::ROWS] = { 0x80, 0xC0, 0x94, 0xD4 }; - - switch(d) - { - case CLR_DISPLAY: - emul->emulLCD->Clear(); - break; - - case CURSOR_BLOCK: - case CURSOR_LINE: - emul->emulLCD->ShowCursor(true); - break; - - case CURSOR_OFF: - emul->emulLCD->ShowCursor(false); - break; - - default: - // Set DDRAM address? - if (d & LCD_DDRAMADDR) - { - for (int i = 0; i < EmulLCD::ROWS; i++) - { - if ((d >= lcd_rowaddress[i]) && (d < lcd_rowaddress[i] + EmulLCD::COLS)) - { - emul->emulLCD->MoveCursor(i, d - lcd_rowaddress[i]); - break; - } - } - } - else if (d & LCD_CGRAMADDR) - emul->emulLCD->SetCGRamAddr(d); - break; - } -} - - -extern "C" unsigned char Emul_LCDReadReg(void) -{ - return 0; /* This LCD model is never busy ;-) */ -} - - -extern "C" void Emul_LCDWriteData(unsigned char d) -{ - emul->emulLCD->PutChar(d); -} - - -extern "C" unsigned char Emul_LCDReadData(void) -{ - return emul->emulLCD->GetChar(); -} - -#include "EmulLCD.moc" - diff --git a/drv/lcd_lm44_qt.h b/drv/lcd_lm44_qt.h deleted file mode 100644 index da01e62e..00000000 --- a/drv/lcd_lm44_qt.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Custom Qt widget for emulating a graphics LCD display (implementation) - */ - -/*#* - *#* $Log$ - *#* Revision 1.1 2006/01/16 03:51:35 bernie - *#* Add LCD Qt emulator. - *#* - *#*/ - -#ifndef EMULLCD_H -#define EMULLCD_H - -#include -#include -#include - -// fwd decls -class QSizePolicy; -class QPaintEvent; -class QResizeEvent; - -/** - * Qt widget to emulate a dot-matrix LCD display. - */ -class EmulLCD : public QFrame -{ - Q_OBJECT - -public: -// Attributes - enum { COLS = 20, ROWS = 4 }; - -// Construction - EmulLCD(QWidget *parent = 0, const char *name = 0); - virtual ~EmulLCD(); - -// Base class overrides -protected: - virtual QSizePolicy sizePolicy() const; - virtual QSize sizeHint() const; - virtual void drawContents(QPainter *p); - -// Operations -public: - void MoveCursor (int col, int row); - void ShowCursor (bool show = true); - void PutChar (unsigned char c); - char GetChar (); - void Clear (); - void SetCGRamAddr (unsigned char addr); - -// Implementation -protected: - void SetPainter(QPainter & p); - void RedrawText(QPainter & p); - void PrintChar(QPainter & p, int row, int col); - void AdvanceCursor(); - - QFont lcd_font; ///< Display character font - QColor fg_color, bg_color; ///< LCD colors - int font_width, font_height; ///< Font dimensions - int frame_width; ///< Frame width (and height) - int cr_row, cr_col; ///< Cursor position - int cgramaddr; ///< CGRAM Address (-1 disabled) - unsigned char ddram[ROWS][COLS];///< Display data RAM - unsigned char cgram[8*8]; ///< CGRAM - bool show_cursor; ///< Cursor enabled? -}; - -#endif // !defined(EMULLCD_H) - diff --git a/drv/lcd_text.c b/drv/lcd_text.c deleted file mode 100644 index 8e519280..00000000 --- a/drv/lcd_text.c +++ /dev/null @@ -1,499 +0,0 @@ -/** - * \file - * - * - * \brief Generic text LCD driver (impl.). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/09/20 20:02:43 marco - *#* Replaced ISLISTEMPTY with LIST_EMPTY - *#* - *#* Revision 1.3 2006/07/19 12:56:25 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.2 2006/02/24 00:27:14 bernie - *#* Use new naming convention for list macros. - *#* - *#* Revision 1.1 2005/11/04 18:00:42 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.11 2005/06/14 14:43:43 bernie - *#* Add DevLib headers. - *#* - *#* Revision 1.10 2005/06/06 17:41:57 batt - *#* Add lcd_layerSet function. - *#* - *#* Revision 1.9 2005/06/01 16:40:07 batt - *#* Remove debug string. - *#* - *#* Revision 1.8 2005/06/01 16:38:04 batt - *#* Adapt to changes in mware/list.h. - *#* - *#* Revision 1.7 2005/06/01 10:45:22 batt - *#* lcd_setAddr(): Bugfix boundary condition; Misc cleanup. - *#* - *#* Revision 1.6 2005/06/01 10:36:23 batt - *#* Layer: Rename member variables and Doxygenize. - *#* - *#* Revision 1.5 2005/05/27 11:05:58 batt - *#* Do not write on lcd if layer is hidden. - *#*/ - -#include "lcd_text.h" -#include "lcd_hd44.h" -#include // timer_delay() -#include // _formatted_write() -#include // LIST_EMPTY() -#include // BV() -#include - -#include // strlen() - - -/** Maximum number of layers. */ -#define LCD_LAYERS 6 - -#if CONFIG_KERNEL - /** Semaphore to arbitrate access to the display. */ - static struct Semaphore lcd_semaphore; - #define LOCK_LCD sem_obtain(&lcd_semaphore) - #define UNLOCK_LCD sem_release(&lcd_semaphore) -#else /* !CONFIG_KERNEL */ - #define LOCK_LCD do {} while (0) - #define UNLOCK_LCD do {} while (0) -#endif /* !CONFIG_KERNEL */ - -DECLARE_LIST_TYPE(Layer); - -Layer *lcd_DefLayer; -static Layer lcd_LayersPool[LCD_LAYERS]; -static LIST_TYPE(Layer) lcd_Layers; -static LIST_TYPE(Layer) lcd_FreeLayers; - -/** - * Current cursor status. - * - * One of LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK or LCD_CMD_CURSOR_LINE. - */ -static uint8_t lcd_CursorStatus; - -/** Current cursor position, encoded as a Cursor position and status. */ -static lcdpos_t lcd_CursorAddr; - - -void lcd_setAddr(Layer *layer, lcdpos_t addr) -{ - /* Sanity check: wrap around to display limits */ - while (addr >= LCD_ROWS * LCD_COLS) - addr -= LCD_ROWS * LCD_COLS; - - layer->addr = addr; -} - -#if CONFIG_KERNEL - -void lcd_lock(void) -{ - LOCK_LCD; -} - - -void lcd_unlock(void) -{ - UNLOCK_LCD; -} - -#endif /* CONFIG_KERNEL */ - - -/** - * Write one character to the display at the current - * cursor prosition, then move the cursor right. The - * cursor is wrapped to the next line when it moves - * beyond the end of the current line. - * - * \note Does _NOT_ lock the display semaphore. - */ -static void lcd_putCharUnlocked(char c, Layer *layer) -{ - Layer *l2; - lcdpos_t addr = layer->addr; - - /* Store character in layer buffer */ - layer->buf[addr] = c; - - /* Move to next character */ - if (++layer->addr >= LCD_COLS * LCD_ROWS) - layer->addr = 0; - - /* Do not write on LCD if layer is hidden. */ - if (layer->pri == LAYER_HIDDEN) - return; - - /* - * Check if this location is obscured by - * other layers above us. - */ - for (l2 = layer->pred; l2->pred; l2 = l2->pred) - { - if (l2->buf[addr]) - { - /* DB(kprintf("layer %04x obs %04x at %d\n", l2, layer, addr);) */ - return; - } - } - - /* Write character */ - if (c) - lcd_putc(addr, c); - else - /* FIXME: should look for layers beneath! */ - lcd_putc(addr, ' '); -} - - -void lcd_putChar(char c, Layer *layer) -{ - LOCK_LCD; - lcd_putCharUnlocked(c, layer); - UNLOCK_LCD; -} - -void lcd_layerSet(Layer *layer, char c) -{ - int i; - - LOCK_LCD; - lcd_setAddr(layer, 0); - for (i = 0; i < LCD_COLS * LCD_ROWS; i++) - lcd_putCharUnlocked(c, layer); - UNLOCK_LCD; -} - - -void lcd_clear(Layer *layer) -{ - lcd_layerSet(layer, 0); -} - - -void lcd_clearLine(Layer *layer, int y) -{ - int i; - - LOCK_LCD; - lcd_setAddr(layer, LCD_POS(0, y)); - for (i = 0; i < LCD_COLS; i++) - lcd_putCharUnlocked(0, layer); - UNLOCK_LCD; -} - - -void lcd_moveCursor(lcdpos_t addr) -{ - LOCK_LCD; - lcd_moveTo(addr); - UNLOCK_LCD; -} - - -char lcd_setCursor(char mode) -{ - static const char cursor_cmd[3] = - { - LCD_CMD_CURSOR_OFF, LCD_CMD_CURSOR_BLOCK, LCD_CMD_CURSOR_LINE - }; - char oldmode = lcd_CursorStatus; - - LOCK_LCD; - lcd_CursorStatus = mode; - lcd_setReg(cursor_cmd[(int)mode]); - if (mode) - lcd_moveCursor(lcd_CursorAddr); - UNLOCK_LCD; - - return oldmode; -} - - -int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap) -{ - int len; - - LOCK_LCD; - - /* - * Se il cursore era acceso, spegnilo durante - * l'output per evitare che salti alla posizione - * in cui si scrive. - */ - if (lcd_CursorStatus) - lcd_setReg(LCD_CMD_CURSOR_OFF); - - /* Spostamento del cursore */ - lcd_setAddr(layer, addr); - - if (mode & LCD_CENTER) - { - int pad; - - /* - * NOTE: calculating the string lenght BEFORE it gets - * printf()-formatted. Real lenght may differ. - */ - pad = (LCD_COLS - strlen(format)) / 2; - while (pad--) - lcd_putCharUnlocked(' ', layer); - } - - len = _formatted_write(format, (void (*)(char, void *))lcd_putCharUnlocked, layer, ap); - - if (mode & (LCD_FILL | LCD_CENTER)) - while (layer->addr % LCD_COLS) - lcd_putCharUnlocked(' ', layer); - - /* - * Riaccendi il cursore e riportalo alla - * vecchia posizione - */ - if (lcd_CursorStatus) - lcd_setCursor(lcd_CursorStatus); - - UNLOCK_LCD; - - return len; -} - - -int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...) -{ - int len; - va_list ap; - - va_start(ap, format); - len = lcd_vprintf(layer, addr, mode, format, ap); - va_end(ap); - - return len; -} - - -/** - * Internal function to move a layer between two positions. - * - * \note The layer must be *already* enqueued in some list. - * \note The display must be already locked! - */ -static void lcd_enqueueLayer(Layer *layer, char pri) -{ - Layer *l2; - - /* Remove layer from whatever list it was in before */ - REMOVE(layer); - - layer->pri = pri; - - /* - * Search for the first layer whose priority - * is less or equal to the layer we are adding. - */ - FOREACH_NODE(l2, &lcd_Layers) - if (l2->pri <= pri) - break; - - /* Enqueue layer */ - INSERT_BEFORE(layer, l2); -} - -Layer *lcd_newLayer(char pri) -{ - Layer *layer; - - LOCK_LCD; - - if (LIST_EMPTY(&lcd_FreeLayers)) - { - UNLOCK_LCD; - //ASSERT(false); - return NULL; - } - - layer = (Layer *)LIST_HEAD(&lcd_FreeLayers); - layer->addr = 0; - memset(layer->buf, 0, LCD_ROWS * LCD_COLS); - - lcd_enqueueLayer(layer, pri); - - UNLOCK_LCD; - return layer; -} - -/** - * Redraw the display (internal). - * - * \note The display must be already locked. - */ -static void lcd_refresh(void) -{ - lcdpos_t addr; - Layer *l; - - for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) - { - FOREACH_NODE(l, &lcd_Layers) - { - //kprintf("%d %x %p\n", addr, l->buf[0], l); - if (l->pri == LAYER_HIDDEN) - break; - - if (l->buf[addr]) - { - /* Refresh location */ - lcd_putc(addr, l->buf[addr]); - goto done; - } - } - - /* Draw background */ - lcd_putc(addr, ' '); - done: - ; - } -} - -/** - * Rearrange layer depth and refresh display accordingly. - * - * \note Setting a priority of LAYER_HIDDEN makes the layer invisible. - */ -void lcd_setLayerDepth(Layer *layer, char pri) -{ - if (pri != layer->pri) - { - LOCK_LCD; - lcd_enqueueLayer(layer, pri); - /* Vile but simple */ - lcd_refresh(); - UNLOCK_LCD; - } -} - -void lcd_deleteLayer(Layer *layer) -{ - LOCK_LCD; - -/* We use lcd_refresh() instead. Much simpler than this mess, but slower. */ -#if 0 - Layer *l2; - lcdpos_t addr; - - /* Repair damage on underlaying layers */ - for (addr = 0; addr < LCD_ROWS * LCD_COLS; ++addr) - { - /* If location was covered by us */ - if (layer->buf[addr]) - { - /* ...and it wasn't covered by others above us... */ - for (l2 = layer->pred; l2->pred; l2 = l2->pred) - if (l2->buf[addr]) - /* can't just break here! */ - goto not_visible; - - /* ...scan underlaying layers to repair damage */ - for (l2 = layer->succ; l2->succ; l2 = l2->succ) - if (l2->buf[addr]) - { - /* Refresh character */ - lcd_putc(addr, l2->buf[addr]); - - /* No need to search on deeper layers */ - break; - } - - not_visible: - ; - } - } -#endif - - // Remove layer from lcd_Layers list. - REMOVE(layer); - - /* Put layer back into free list */ - ADDHEAD(&lcd_FreeLayers, layer); - - lcd_refresh(); - - UNLOCK_LCD; -} - - -static void lcd_setDefLayer(Layer *layer) -{ - lcd_DefLayer = layer; -} - -#include -void lcd_init(void) -{ - int i; - - LIST_INIT(&lcd_Layers); - LIST_INIT(&lcd_FreeLayers); - for (i = 0; i < LCD_LAYERS; ++i) - ADDHEAD(&lcd_FreeLayers, &lcd_LayersPool[i]); - - lcd_setDefLayer(lcd_newLayer(0)); - - lcd_hw_init(); - - lcd_setCursor(0); -} - -#if CONFIG_TEST -void lcd_test(void) -{ - int i; - - for (i = 0; i < LCD_ROWS * LCD_COLS; ++i) - { - lcd_putCharUnlocked('0' + (i % 10), lcd_DefLayer); - timer_delay(100); - } -} -#endif /* CONFIG_TEST */ - diff --git a/drv/lcd_text.h b/drv/lcd_text.h deleted file mode 100644 index d05cfcd2..00000000 --- a/drv/lcd_text.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * \file - * - * - * \brief Generic text LCD driver (interface). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.3 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.2 2006/02/23 10:59:14 bernie - *#* Documentation fixes. - *#* - *#* Revision 1.1 2005/11/04 18:00:42 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.5 2005/06/14 14:43:43 bernie - *#* Add DevLib headers. - *#* - *#* Revision 1.4 2005/06/06 17:41:57 batt - *#* Add lcd_layerSet function. - *#* - *#* Revision 1.3 2005/06/01 10:36:23 batt - *#* Layer: Rename member variables and Doxygenize. - *#* - *#* Revision 1.2 2005/05/26 08:31:23 batt - *#* Add layer hiding/showing. - *#* - *#* Revision 1.1 2005/05/24 09:17:58 batt - *#* Move drivers to top-level. - *#*/ - -#ifndef DRV_LCD_H -#define DRV_LCD_H - -#include "lcd_hd44.h" - -#include -#include -#include - -#include // vprintf() - - -/* flags for lcd_printf() */ -#define LCD_NORMAL 0 /* Scrittura normale */ -#define LCD_FILL BV(0) /* Fill rest of line with spaces */ -#define LCD_CENTER BV(1) /* Center string in line */ -#define LCD_NOCURSOR BV(2) /* Scrittura senza spostamento cursore */ - -/** Special priority value for lcd_setLayerDepth(). */ -#define LAYER_HIDDEN -128 - -/* Compute LCD address from x/y coordinates */ -#define LCD_POS(x,y) ((lcdpos_t)((uint8_t)(x) + (uint8_t)(y) * (uint8_t)LCD_COLS)) -#define LCD_ROW0 (LCD_COLS * 0) -#define LCD_ROW1 (LCD_COLS * 1) -#define LCD_ROW2 (LCD_COLS * 2) -#define LCD_ROW3 (LCD_COLS * 3) - -/** - * Overwrapping layer context. - */ -typedef struct _Layer -{ - /** - * Active layers are linked together in a list - * sorted in top to bottom order. - */ - DECLARE_NODE_ANON(struct _Layer) - - /** Current XY address into this layer, for write operations. */ - lcdpos_t addr; - - /** Priority of this layer (greater in front of lesser). */ - char pri; - - /** - * Layer backing store buffer. - * - * All writes through the layer are copied into this buffer. - * Characters cells with value 0 are transparent with respect - * to other layers in the background. - */ - char buf[LCD_COLS * LCD_ROWS]; -} Layer; - - -/* Global variables */ -extern Layer *lcd_DefLayer; - -/* Function prototypes */ -extern void lcd_init(void); -extern void lcd_test(void); - -extern void lcd_moveCursor(lcdpos_t addr); -extern char lcd_setCursor(char state); - -extern void lcd_setAddr(Layer *layer, lcdpos_t addr); -extern void lcd_putChar(char c, Layer *layer); -extern int lcd_vprintf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, va_list ap) FORMAT(printf, 4, 0); -extern int lcd_printf(Layer *layer, lcdpos_t addr, uint8_t mode, const char *format, ...) FORMAT(printf, 4, 5); -extern void lcd_clear(Layer *layer); -extern void lcd_layerSet(Layer *layer, char c); -extern void lcd_clearLine(Layer *layer, int y); - -extern void lcd_setLayerDepth(Layer *layer, char pri); -extern Layer *lcd_newLayer(char pri); -extern void lcd_deleteLayer(Layer *layer); -extern void lcd_lock(void); -extern void lcd_unlock(void); - -#endif /* DRV_LCD_H */ diff --git a/drv/mcp41.c b/drv/mcp41.c deleted file mode 100644 index 12c566f5..00000000 --- a/drv/mcp41.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief MCP41xxx digital potentiomenter driver (implementation) - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#include - -#include -#include - -#include -#include -#include - -static Serial *spi_ser; - -/** - * Set resitance for digital pot \a dev - */ -void mcp41_setResistance(Mcp41Dev dev, mcp41_res_t res) -{ - MCP41_ON(dev); - /* send command byte */ - ser_putchar(MCP41_WRITE_DATA, spi_ser); - ser_putchar(((MCP41_HW_MAX * (uint32_t)res) + (MCP41_MAX / 2)) / MCP41_MAX, spi_ser); - ser_drain(spi_ser); - - MCP41_OFF(dev); -} - - -/** - * Initialize mcp41 potentiometer driver - */ -void mcp41_init(Serial *spi_port) -{ - Mcp41Dev dev; - - /* Init all potentiometer ports */ - for (dev = 0; dev < MCP41_CNT; dev++) - { - SET_MCP41_DDR(dev); - MCP41_OFF(dev); - } - - spi_ser = spi_port; -} diff --git a/drv/mcp41.h b/drv/mcp41.h deleted file mode 100644 index 266b539b..00000000 --- a/drv/mcp41.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief MCP41xxx digital potentiomenter driver (interface) - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#ifndef DRV_MCP41_H -#define DRV_MCP41_H - -#include -#include -#include - -#define MCP41_WRITE_DATA 0x11 -#define MCP41_HW_MAX 255 -#define MCP41_MAX 999 - -/** - * Type for digital potentiometer resistance. - */ -typedef uint16_t mcp41_res_t; - -void mcp41_setResistance(Mcp41Dev dev, mcp41_res_t res); -void mcp41_init(Serial *spi_port); - -#endif /* DRV_MCP41_H */ diff --git a/drv/ntc.c b/drv/ntc.c deleted file mode 100644 index 2469c88f..00000000 --- a/drv/ntc.c +++ /dev/null @@ -1,161 +0,0 @@ -/** - * \file - * - * - * \brief Driver for NTC (reads a temperature through an ADC) - * - * \version $Id$ - * - * \author Giovanni Bajo - * \author Francesco Sacchi - * - * - * This module handles an external NTC bound to an AD converter. As usual, - * it relies on a low-level API (ntc_hw_*) (see below): - * - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 17:59:47 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.1 2005/05/24 09:17:58 batt - *#* Move drivers to top-level. - *#*/ - -#include -#include -#include - -#include - -DB(bool ntc_initialized;) - -/** - * Find in a table of values \a orig_table of size \a size, the index which - * value is less or equal to \a val. - * - * \retval 0 When \a val is higher than the first table entry. - * \retval size When \a val is lower than the last table entry. - * \retval 1..size-1 When \a val is within the table. - */ -static size_t upper_bound(const res_t *orig_table, size_t size, res_t val) -{ - const res_t *table = orig_table; - - while (size) - { - size_t pos = size / 2; - if (val > table[pos]) - size = pos; - else - { - table += pos+1; - size -= pos+1; - } - } - - return table - orig_table; -} - - -/** - * Read the temperature for the NTC channel \a dev. - * First read the resistence of the NTC through ntc_hw_read(), then, - * for the conversion from resistance to temperature, since the formula - * varies from device to device, we implemented a generic system using - * a table of data which maps temperature (index) to resistance (data). - * The range of the table (min/max temperature) and the step - * (temperature difference between two consecutive elements of the table) - * is variable and can be specified. Notice that values inbetween the - * table elements are still possible as the library does a linear - * interpolation using the actual calculated resistance to find out - * the exact temperature. - * - * The low-level API provides a function to get access to a description - * of the NTC (ntc_hw_getInfo()), including the resistance table. - * - */ -deg_t ntc_read(NtcDev dev) -{ - const NtcHwInfo* hw = ntc_hw_getInfo(dev); - const res_t* r = hw->resistances; - - float rx; - size_t i; - deg_t degrees; - - rx = ntc_hw_read(dev); - - - i = upper_bound(r, hw->num_resistances, rx); - ASSERT(i <= hw->num_resistances); - - if (i >= hw->num_resistances) - return NTC_SHORT_CIRCUIT; - else if (i == 0) - return NTC_OPEN_CIRCUIT; - - /* - * Interpolated value in 0.1 degrees multiplied by 10: - * delta t step t - * ---------- = ---------------- - * (rx - r[i]) (r[i-1] - r [i]) - */ - float tmp; - tmp = 10 * hw->degrees_step * (rx - r[i]) / (r[i - 1] - r[i]); - - /* - * degrees = integer part corresponding to the superior index - * in the table multiplied by 10 - * - decimal part interpolated (already multiplied by 10) - */ - degrees = (i * hw->degrees_step + hw->degrees_min) * 10 - (int)(tmp); - - //kprintf("dev= %d, I=%d, degrees = %d\n", dev, i , degrees); - - return degrees; -} - - -/** - * Init NTC hardware. - */ -void ntc_init(void) -{ - NTC_HW_INIT; - DB(ntc_initialized = true;) -} - diff --git a/drv/ntc.h b/drv/ntc.h deleted file mode 100644 index 8267d51f..00000000 --- a/drv/ntc.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * \file - * - * - * \brief Driver for NTC (reads a temperature through an ADC) - * - * \version $Id$ - * - * \author Giovanni Bajo - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 17:59:47 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.3 2005/06/10 08:56:47 batt - *#* Avoid calling DEG_T_TO_DEG(). - *#* - *#* Revision 1.2 2005/06/10 08:54:58 batt - *#* Rename deg_t conversion macros to accomplish coding standard. - *#* - *#* Revision 1.1 2005/05/24 09:17:58 batt - *#* Move drivers to top-level. - *#*/ - -#ifndef DRV_NTC_H -#define DRV_NTC_H - -#include -#include -#include - -#define NTC_OPEN_CIRCUIT -32768 -#define NTC_SHORT_CIRCUIT 32767 - -typedef int16_t deg_t; /** type for celsius degrees deg_t = °C * 10 */ - -/** Macro for converting from deg to deg_t type */ -#define DEG_TO_DEG_T(x) ((deg_t)((x) * 10)) - -/** Macro for converting from deg_t to celsius degrees (returns only the integer part) */ -#define DEG_T_TO_INTDEG(x) ((x) / 10) - -/** Macro for converting from deg_t to celsius degrees (returns only the decimal part) */ -#define DEG_T_TO_DECIMALDEG(x) ((x) % 10) - -/** Macro for converting from deg_t to celsius degrees (returns type is float) */ -#define DEG_T_TO_FLOATDEG(x) ((x) / 10.0) - - -typedef uint32_t res_t; /** type for resistor res_t = Ohm * 100 */ -typedef float amp_t; /** type for defining amplifications amp_t = A, where A is a pure number */ - -DB(extern bool ntc_initialized;) - - -/** Describe a NTC chip */ -typedef struct NtcHwInfo -{ - const res_t *resistances; ///< resistances of the NTC (ohms * 100) - size_t num_resistances; ///< number of resistances - deg_t degrees_min; ///< degrees corresponding to the first entry in the table (celsius * 10) - deg_t degrees_step; ///< difference in degrees between two consecutive elements in the table (celsius * 10) -} NtcHwInfo; - -/** Initialize the NTC module */ -void ntc_init(void); - -/** Read a single temperature value from the NTC */ -deg_t ntc_read(NtcDev dev); - -#endif /* DRV_NTC_H */ diff --git a/drv/phase.c b/drv/phase.c deleted file mode 100644 index e30f4668..00000000 --- a/drv/phase.c +++ /dev/null @@ -1,192 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Phase control driver (implementation) - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#include - - -#include -#include -#include -#include - - -#include -#include - -#include - -/** Array of triacs */ -static Triac triacs[TRIAC_CNT]; - -DB(bool phase_initialized;) - -/** - * Zerocross interrupt, call when 220V cross zero. - * - * This function turn off all triacs that have duty < 100% - * and arm the triac timers for phase control. - * This function is frequency adaptive so can work both at 50 or 60Hz. - */ -DEFINE_ZEROCROSS_ISR() -{ - ticks_t period, now; - static ticks_t prev_time; - TriacDev dev; - - now = timer_clock_unlocked(); - period = now - prev_time; - - for (dev = 0; dev < TRIAC_CNT; dev++) - { - /* Only turn off triac if duty is != 100% */ - if (triacs[dev].duty != TRIAC_MAX_DUTY) - TRIAC_OFF(dev); - /* Compute delay from duty */ - timer_setDelay(&triacs[dev].timer, DIV_ROUND(period * (TRIAC_MAX_DUTY - triacs[dev].duty), TRIAC_MAX_DUTY)); - - /* This check avoids inserting the same timer twice - * in case of an intempestive zerocross or spike */ - if (triacs[dev].running) - { - timer_abort(&triacs[dev].timer); - //kprintf("[%lu]\n", timer_clock()); - } - - triacs[dev].running = true; - timer_add(&triacs[dev].timer); - } - prev_time = now; -} - - - -/** - * Set duty of the triac channel \a dev (interrupt safe). - */ -void phase_setDuty(TriacDev dev, triac_duty_t duty) -{ - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - phase_setDutyUnlock(dev,duty); - - IRQ_RESTORE(flags); -} - - - -/** - * Set duty of the triac channel \a dev (NOT INTERRUPT SAFE). - */ -void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty) -{ - triacs[dev].duty = MIN(duty, (triac_duty_t)TRIAC_MAX_DUTY); -} - - - -/** - * Set power of the triac channel \a dev (interrupt safe). - * - * This function approsimate the sine wave to a triangular wave to compute - * RMS power. - */ -void phase_setPower(TriacDev dev, triac_power_t power) -{ - bool greater_fifty = false; - triac_duty_t duty; - - power = MIN(power, (triac_power_t)TRIAC_MAX_POWER); - - if (power > TRIAC_MAX_POWER / 2) - { - greater_fifty = true; - power = TRIAC_MAX_POWER - power; - } - - duty = TRIAC_POWER_K * sqrt(power); - - if (greater_fifty) - duty = TRIAC_MAX_DUTY - duty; - phase_setDuty(dev, duty); -} - - - -/** - * Soft int for each \a _dev triac. - * - * The triacs are turned on at different time to achieve phase control. - */ -static void phase_softint(void *_dev) -{ - TriacDev dev = (TriacDev)_dev; - - /* Only turn on if duty is !=0 */ - if (triacs[dev].duty) - TRIAC_ON(dev); - triacs[dev].running = false; -} - - - -/** - * Initialize phase control driver - */ -void phase_init(void) -{ - cpuflags_t flags; - TriacDev dev; - - /* Init timers and ensure that all triac are off */ - for (dev = 0; dev < TRIAC_CNT; dev++) - { - triacs[dev].duty = 0; - triacs[dev].running = false; - SET_TRIAC_DDR(dev); - TRIAC_OFF(dev); - timer_set_event_softint(&triacs[dev].timer, (Hook)phase_softint, (void *)dev); - } - IRQ_SAVE_DISABLE(flags); - - /* Init zero cross interrupt */ - PHASE_HW_INIT; - DB(phase_initialized = true;) - IRQ_RESTORE(flags); -} diff --git a/drv/phase.h b/drv/phase.h deleted file mode 100644 index f4e760ea..00000000 --- a/drv/phase.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Phase control driver (interface) - * - * \version $Id$ - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:06:44 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.1 2005/05/24 09:17:58 batt - *#* Move drivers to top-level. - *#* - *#* Revision 1.9 2005/05/09 16:34:14 batt - *#* Change some function names to accomplish coding standard; Add debug phase_initialized; Change duty_t and power_t to uint16_t. - *#* - *#* Revision 1.8 2005/05/02 12:37:33 batt - *#* Split hw triac map in phase_map.h. - *#* - *#* Revision 1.7 2005/05/02 09:05:03 batt - *#* Rename duty_t and power_t in triac_duty_t and triac_power_t - *#* - *#* Revision 1.6 2005/04/28 15:10:11 batt - *#* Use timer API to add and set events. - *#* - *#* Revision 1.5 2005/04/28 12:04:46 batt - *#* Add some comments. - *#* - *#* Revision 1.4 2005/04/28 10:35:45 batt - *#* Complete phase_setpower. - *#* - *#* Revision 1.3 2005/04/27 19:23:40 batt - *#* Reformat. - *#* - *#* Revision 1.1 2005/04/27 17:13:56 batt - *#* Add triac phase control driver. - *#* - *#*/ - - -#ifndef DRV_PHASE_H -#define DRV_PHASE_H - -#include -#include -#include - -#define TRIAC_MAX_DUTY 100 -#define TRIAC_MAX_POWER 100 -#define TRIAC_POWER_K TRIAC_MAX_DUTY * (1 / sqrt(2 * TRIAC_MAX_POWER)) - -/** - * \name Types for duty and power. - * \{ - */ -typedef uint16_t triac_duty_t; -typedef uint16_t triac_power_t; -/* \} */ - - -DB(extern bool phase_initialized;) - -/** - * \name Type for triac control. - * \{ - */ -typedef struct Triac -{ - Timer timer; /**< Timer for phase control. */ - triac_duty_t duty; /**< Duty cycle of the channel. */ - bool running; /**< True when the timer is active. */ -} Triac; -/* \} */ - -void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty); -void phase_setDuty(TriacDev dev, triac_duty_t duty); -void phase_setPower(TriacDev dev, triac_power_t power); - -void phase_init(void); - - -#endif /* DRV_PHASE_H */ diff --git a/drv/pwm.c b/drv/pwm.c deleted file mode 100644 index 39461882..00000000 --- a/drv/pwm.c +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file - * - * - * - * \brief PWM driver (implementation) - * - * \version $Id$ - * - * \author Francesco Sacchi - * \author Daniele Basile - */ - -#include -#include - -#include -#include - -#include -#include - - -/** - * Set duty of pwm channel \p dev. - */ -void pwm_setDuty(PwmDev dev, pwm_duty_t duty) -{ - pwm_period_t period = 0; - pwm_duty_t real_duty = 0; - - duty = MIN(duty, (pwm_duty_t)PWM_MAX_DUTY); - - period = pwm_hw_getPeriod(dev); - - real_duty = (uint64_t)(duty * period) >> (uint64_t)PWM_MAX_PERIOD_LOG2; - -// kprintf("real_duty[%d] duty[%d], period[%d]\n", real_duty, duty, period); - pwm_hw_setDutyUnlock(dev, real_duty); -} - -/** - * Set frequency of pwm channel \p dev at \p freq in Hz. - */ -void pwm_setFrequency(PwmDev dev, pwm_freq_t freq) -{ - pwm_hw_setFrequency(dev, freq); -} - -/** - * Set duty of pwm channel \p dev. - */ -void pwm_enable(PwmDev dev, bool state) -{ - if (state) - pwm_hw_enable(dev); - else - pwm_hw_disable(dev); -} - -/** - * Initialize PWM hw. - */ -void pwm_init(void) -{ - cpuflags_t flags; - PwmDev dev; - - IRQ_SAVE_DISABLE(flags); - - /* set all pwm to 0 */ - for (dev = 0; dev < PWM_CNT; dev++) - pwm_setDuty(dev, 0); - - pwm_hw_init(); - - IRQ_RESTORE(flags); -} - - - - diff --git a/drv/pwm.h b/drv/pwm.h deleted file mode 100644 index 03d98453..00000000 --- a/drv/pwm.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief PWM driver (interface) - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#ifndef DRV_PWM_H -#define DRV_PWM_H - -#include -#include - -typedef uint16_t pwm_duty_t; - -void pwm_setDuty(PwmDev dev, pwm_duty_t duty); -void pwm_init(void); - -#define PWM_MAX_DUTY 100 - -#endif /* DRV_PWM_H */ diff --git a/drv/pwm_test.c b/drv/pwm_test.c deleted file mode 100644 index cb2dc84c..00000000 --- a/drv/pwm_test.c +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \file - * - * - * - * \brief Test for PWM driver (implementation) - * - * \version $Id$ - * - * \author Daniele Basile - */ - -#include -#include - -#include -#include - -#include -#include - -/* - * Esample of value for duty cycle" - * - * - 100% => 0xFFFFFFFF - * - 80% => 0xCCCCCCCC - * - 75% => 0xBFFFFFFF - * - 50% => 0x7FFFFFFF - * - 25% => 0x3FFFFFFF - * - 33% => 0x55555555 - * - 16% => 0x2AAAAAAA - */ - -#define PWM_TEST_CH0 0 -#define PWM_TEST_CH0_FREQ 100UL // 100Hz -#define PWM_TEST_CH0_DUTY 0xCCCC // 80% - -#define PWM_TEST_CH1 1 -#define PWM_TEST_CH1_FREQ 1000UL // 1000Hz -#define PWM_TEST_CH1_DUTY 0xBFFF // 75% - -#define PWM_TEST_CH2 2 -#define PWM_TEST_CH2_FREQ 12356 // 12356Hz -#define PWM_TEST_CH2_DUTY 0x7FFF // 50% - -#define PWM_TEST_CH3 3 -#define PWM_TEST_CH3_FREQ 100000UL // 100KHz -#define PWM_TEST_CH3_DUTY 0x5555 // 33% - -#define PWM_TEST_CH_SET(index) \ - do { \ - pwm_setFrequency(PWM_TEST_CH##index , PWM_TEST_CH##index##_FREQ); \ - pwm_setDuty(PWM_TEST_CH##index, PWM_TEST_CH##index##_DUTY); \ - pwm_enable(PWM_TEST_CH##index, true); \ - } while (0) - -/** - * Test suit for genation of pwm waveform. - * - */ -void pwm_test(void) -{ - - pwm_init(); - kputs("Init pwm..\n"); - - PWM_TEST_CH_SET(0); - kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH0, PWM_TEST_CH0_FREQ, PWM_TEST_CH0_DUTY); - PWM_TEST_CH_SET(1); - kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH1, PWM_TEST_CH1_FREQ, PWM_TEST_CH1_DUTY); - PWM_TEST_CH_SET(2); - kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH2, PWM_TEST_CH2_FREQ, PWM_TEST_CH2_DUTY); - PWM_TEST_CH_SET(3); - kprintf("Set pwm ch[%d] =>freq[%ld], duty[%d]\n", PWM_TEST_CH3, PWM_TEST_CH3_FREQ, PWM_TEST_CH3_DUTY); -} - - - - - - diff --git a/drv/ser.c b/drv/ser.c deleted file mode 100644 index 0838bc15..00000000 --- a/drv/ser.c +++ /dev/null @@ -1,529 +0,0 @@ -/** - * \file - * - * - * \brief Buffered serial I/O driver - * - * The serial rx interrupt buffers incoming data in a software FIFO - * to decouple the higher level protocols from the line speed. - * Outgoing data is buffered as well for better performance. - * This driver is not optimized for best performance, but it - * has proved to be fast enough to handle transfer rates up to - * 38400bps on a 16MHz 80196. - * - * MODULE CONFIGURATION - * - * \li \c CONFIG_SER_HWHANDSHAKE - set to 1 to enable RTS/CTS handshake. - * Support is incomplete/untested. - * \li \c CONFIG_SER_TXTIMEOUT - Enable software serial transmission timeouts - * - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "ser.h" -#include "wdt.h" -#include "ser_p.h" -#include -#include -#include - -#include /* memset */ - -/* - * Sanity check for config parameters required by this module. - */ -#if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1) - #error CONFIG_KERNEL must be set to either 0 or 1 in config.h -#endif -#if !defined(CONFIG_SER_RXTIMEOUT) - #error CONFIG_SER_TXTIMEOUT missing in config.h -#endif -#if !defined(CONFIG_SER_RXTIMEOUT) - #error CONFIG_SER_RXTIMEOUT missing in config.h -#endif -#if !defined(CONFIG_SER_DEFBAUDRATE) - #error CONFIG_SER_DEFBAUDRATE missing in config.h -#endif - -#if CONFIG_KERNEL - #include -#endif - -#if CONFIG_SER_TXTIMEOUT != -1 || CONFIG_SER_RXTIMEOUT != -1 - #include -#endif - - -struct Serial ser_handles[SER_CNT]; - -/** - * Insert \a c in tx FIFO buffer. - * \note This function will switch out the calling process - * if the tx buffer is full. If the buffer is full - * and \a port->txtimeout is 0 return EOF immediatly. - * - * \return EOF on error or timeout, \a c otherwise. - */ -static int ser_putchar(int c, struct Serial *port) -{ - if (fifo_isfull_locked(&port->txfifo)) - { -#if CONFIG_SER_TXTIMEOUT != -1 - /* If timeout == 0 we don't want to wait */ - if (port->txtimeout == 0) - return EOF; - - ticks_t start_time = timer_clock(); -#endif - - /* Wait while buffer is full... */ - do - { - wdt_reset(); -#if CONFIG_KERNEL && CONFIG_KERN_SCHED - /* Give up timeslice to other processes. */ - proc_switch(); -#endif -#if CONFIG_SER_TXTIMEOUT != -1 - if (timer_clock() - start_time >= port->txtimeout) - { - ATOMIC(port->status |= SERRF_TXTIMEOUT); - return EOF; - } -#endif /* CONFIG_SER_TXTIMEOUT */ - } - while (fifo_isfull_locked(&port->txfifo)); - } - - fifo_push_locked(&port->txfifo, (unsigned char)c); - - /* (re)trigger tx interrupt */ - port->hw->table->txStart(port->hw); - - /* Avoid returning signed extended char */ - return (int)((unsigned char)c); -} - - -/** - * Fetch a character from the rx FIFO buffer. - * \note This function will switch out the calling process - * if the rx buffer is empty. If the buffer is empty - * and \a port->rxtimeout is 0 return EOF immediatly. - * - * \return EOF on error or timeout, \a c otherwise. - */ -static int ser_getchar(struct Serial *port) -{ - if (fifo_isempty_locked(&port->rxfifo)) - { -#if CONFIG_SER_RXTIMEOUT != -1 - /* If timeout == 0 we don't want to wait for chars */ - if (port->rxtimeout == 0) - return EOF; - - ticks_t start_time = timer_clock(); -#endif - /* Wait while buffer is empty */ - do - { - wdt_reset(); -#if CONFIG_KERNEL && CONFIG_KERN_SCHED - /* Give up timeslice to other processes. */ - proc_switch(); -#endif -#if CONFIG_SER_RXTIMEOUT != -1 - if (timer_clock() - start_time >= port->rxtimeout) - { - ATOMIC(port->status |= SERRF_RXTIMEOUT); - return EOF; - } -#endif /* CONFIG_SER_RXTIMEOUT */ - } - while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0); - } - - /* - * Get a byte from the FIFO (avoiding sign-extension), - * re-enable RTS, then return result. - */ - if (ser_getstatus(port) & SERRF_RX) - return EOF; - return (int)(unsigned char)fifo_pop_locked(&port->rxfifo); -} - -/** - * Fetch a character from the rx FIFO buffer. - * If the buffer is empty, ser_getchar_nowait() returns - * EOF immediatly. - * \note Deprecated, use ser_getchar with rx_timeout set to 0. - */ -int ser_getchar_nowait(struct KFileSerial *fd) -{ - if (fifo_isempty_locked(&fd->ser->rxfifo)) - return EOF; - - /* NOTE: the double cast prevents unwanted sign extension */ - return (int)(unsigned char)fifo_pop_locked(&fd->ser->rxfifo); -} - - - -/** - * Read at most \a size bytes from \a port and put them in \a buf - * - * \return number of bytes actually read. - */ -static size_t ser_read(struct KFile *fd, void *_buf, size_t size) -{ - KFileSerial *fds = KFILESERIAL(fd); - - size_t i = 0; - char *buf = (char *)_buf; - int c; - - while (i < size) - { - if ((c = ser_getchar(fds->ser)) == EOF) - break; - buf[i++] = c; - } - - return i; -} - -/** - * \brief Write a buffer to serial. - * - * \return 0 if OK, EOF in case of error. - * - * \todo Optimize with fifo_pushblock() - */ -static size_t ser_write(struct KFile *fd, const void *_buf, size_t size) -{ - KFileSerial *fds = KFILESERIAL(fd); - const char *buf = (const char *)_buf; - size_t i = 0; - - while (size--) - { - if (ser_putchar(*buf++, fds->ser) == EOF) - break; - i++; - } - return i; -} - - -#if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1 -void ser_settimeouts(struct KFileSerial *fd, mtime_t rxtimeout, mtime_t txtimeout) -{ - fd->ser->rxtimeout = ms_to_ticks(rxtimeout); - fd->ser->txtimeout = ms_to_ticks(txtimeout); -} -#endif /* CONFIG_SER_RXTIMEOUT || CONFIG_SER_TXTIMEOUT */ - -#if CONFIG_SER_RXTIMEOUT != -1 -/** - * Discard input to resynchronize with remote end. - * - * Discard incoming data until the port stops receiving - * characters for at least \a delay milliseconds. - * - * \note Serial errors are reset before and after executing the purge. - */ -void ser_resync(struct KFileSerial *fd, mtime_t delay) -{ - mtime_t old_rxtimeout = ticks_to_ms(fd->ser->rxtimeout); - - ser_settimeouts(fd, delay, ticks_to_ms(fd->ser->txtimeout)); - do - { - ser_setstatus(fd->ser, 0); - ser_getchar(fd->ser); - } - while (!(ser_getstatus(fd->ser) & SERRF_RXTIMEOUT)); - - /* Restore port to an usable status */ - ser_setstatus(fd->ser, 0); - ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->ser->txtimeout)); -} -#endif /* CONFIG_SER_RXTIMEOUT */ - - -void ser_setbaudrate(struct KFileSerial *fd, unsigned long rate) -{ - fd->ser->hw->table->setBaudrate(fd->ser->hw, rate); -} - - -void ser_setparity(struct KFileSerial *fd, int parity) -{ - fd->ser->hw->table->setParity(fd->ser->hw, parity); -} - -static int ser_error(struct KFile *fd) -{ - KFileSerial *fds = KFILESERIAL(fd); - return ser_getstatus(fds->ser); -} - -static void ser_clearerr(struct KFile *fd) -{ - KFileSerial *fds = KFILESERIAL(fd); - ser_setstatus(fds->ser, 0); -} - - - -/** - * Flush both the RX and TX buffers. - */ -void ser_purge(struct KFileSerial *fd) -{ - ser_purgeRx(fd); - ser_purgeTx(fd); -} - -/** - * Flush RX buffer. - */ -void ser_purgeRx(struct KFileSerial *fd) -{ - fifo_flush_locked(&fd->ser->rxfifo); -} - -/** - * Flush TX buffer. - */ -void ser_purgeTx(struct KFileSerial *fd) -{ - fifo_flush_locked(&fd->ser->txfifo); -} - - -/** - * Wait until all pending output is completely - * transmitted to the other end. - * - * \note The current implementation only checks the - * software transmission queue. Any hardware - * FIFOs are ignored. - */ -static int ser_flush(struct KFile *fd) -{ - KFileSerial *fds = KFILESERIAL(fd); - - /* - * Wait until the FIFO becomes empty, and then until the byte currently in - * the hardware register gets shifted out. - */ - while (!fifo_isempty(&fds->ser->txfifo) - || fds->ser->hw->table->txSending(fds->ser->hw)) - { - #if CONFIG_KERNEL && CONFIG_KERN_SCHED - /* Give up timeslice to other processes. */ - proc_switch(); - #endif - wdt_reset(); - } - return 0; -} - - -/** - * Initialize a serial port. - * - * \param fd KFile Serial struct interface. - * \param unit Serial unit to open. Possible values are architecture dependant. - */ -static struct Serial *ser_open(struct KFileSerial *fd, unsigned int unit) -{ - struct Serial *port; - - ASSERT(unit < countof(ser_handles)); - port = &ser_handles[unit]; - - ASSERT(!port->is_open); - DB(port->is_open = true); - - port->unit = unit; - - port->hw = ser_hw_getdesc(unit); - - /* Initialize circular buffers */ - ASSERT(port->hw->txbuffer); - ASSERT(port->hw->rxbuffer); - fifo_init(&port->txfifo, port->hw->txbuffer, port->hw->txbuffer_size); - fifo_init(&port->rxfifo, port->hw->rxbuffer, port->hw->rxbuffer_size); - - port->hw->table->init(port->hw, port); - - fd->ser = port; - /* Set default values */ -#if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1 - ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT); -#endif -#if CONFIG_SER_DEFBAUDRATE - ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE); -#endif - - /* Clear error flags */ - ser_setstatus(port, 0); - - return port; -} - - -/** - * Clean up serial port, disabling the associated hardware. - */ -static int ser_close(struct KFile *fd) -{ - KFileSerial *fds = KFILESERIAL(fd); - Serial *port = fds->ser; - - ASSERT(port->is_open); - DB(port->is_open = false); - - // Wait until we finish sending everything - ser_flush(fd); - - port->hw->table->cleanup(port->hw); - DB(port->hw = NULL); - - /* - * We purge the FIFO buffer only after the low-level cleanup, so that - * we are sure that there are no more interrupts. - */ - ser_purge(fds); - return 0; -} - -/** - * Reopen serial port. - */ -static struct KFile *ser_reopen(struct KFile *fd) -{ - KFileSerial *fds = KFILESERIAL(fd); - - ser_close(fd); - ser_open(fds, fds->ser->unit); - return (KFile *)fds; -} - -/** - * Init serial driver for \a unit. - */ -void ser_init(struct KFileSerial *fds, unsigned int unit) -{ - memset(fds, 0, sizeof(*fds)); - - DB(fds->fd._type = KFT_SERIAL); - fds->fd.reopen = ser_reopen; - fds->fd.close = ser_close; - fds->fd.read = ser_read; - fds->fd.write = ser_write; - fds->fd.flush = ser_flush; - fds->fd.error = ser_error; - fds->fd.clearerr = ser_clearerr; - ser_open(fds, unit); -} - - -/** - * Read data from SPI bus. - * Since we are master, we have to trigger slave by sending - * fake chars on the bus. - */ -static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size) -{ - KFileSerial *fd_spi = KFILESERIAL(fd); - - ser_flush(&fd_spi->fd); - ser_purgeRx(fd_spi); - - size_t total_rd = 0; - uint8_t *buf = (uint8_t *)_buf; - int c; - - while (size--) - { - /* - * Send and receive chars 1 by 1, otherwise the rxfifo - * will overrun. - */ - ser_putchar(0, fd_spi->ser); - - if ((c = ser_getchar(fd_spi->ser)) == EOF) - break; - - *buf++ = c; - total_rd++; - } - return total_rd; -} - -/** - * Write data to SPI bus. - */ -static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size) -{ - KFileSerial *fd_spi = KFILESERIAL(fd); - - ser_purgeRx(fd_spi); - - return ser_write(&fd_spi->fd, buf, size); -} - - -/** - * Init SPI serial driver \a unit in master mode. - * - * This interface implements the SPI master protocol over a serial SPI - * driver. This is needed because normal serial driver send/receive data - * at the same time. SPI slaves like memories and other peripherals - * first receive and *then* send response back instead. - * To achieve this, when we are master and we are *sending*, - * we have to discard all incoming data. Then, when we want to - * receive, we must write fake data to SPI to trigger slave devices. - */ -void spimaster_init(KFileSerial *fds, unsigned int unit) -{ - ser_init(fds, unit); - fds->fd.read = spimaster_read; - fds->fd.write = spimaster_write; -} - - diff --git a/drv/ser.h b/drv/ser.h deleted file mode 100644 index c0f7b8bb..00000000 --- a/drv/ser.h +++ /dev/null @@ -1,198 +0,0 @@ -/** - * \file - * - * - * \brief High level serial I/O API - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#ifndef DRV_SER_H -#define DRV_SER_H - -#include -#include -#include - -#if OS_HOSTED - #include /* BV() */ - - typedef uint16_t serstatus_t; - - /* Software errors */ - #define SERRF_RXFIFOOVERRUN BV(0) /**< Rx FIFO buffer overrun */ - #define SERRF_RXTIMEOUT BV(1) /**< Receive timeout */ - #define SERRF_TXTIMEOUT BV(2) /**< Transmit timeout */ - - /* Hardware errors */ - #define SERRF_RXSROVERRUN 0 /**< Unsupported in emulated serial port. */ - #define SERRF_FRAMEERROR 0 /**< Unsupported in emulated serial port. */ - #define SERRF_PARITYERROR 0 /**< Unsupported in emulated serial port. */ - #define SERRF_NOISEERROR 0 /**< Unsupported in emulated serial port. */ - - enum - { - SER_UART0, - SER_UART1, - - SER_CNT /**< Number of serial ports */ - }; - -#else - #include CPU_HEADER(ser) -#endif - -#include - - - -/** - * \name Masks to group TX/RX errors. - * \{ - */ -#define SERRF_RX \ - ( SERRF_RXFIFOOVERRUN \ - | SERRF_RXTIMEOUT \ - | SERRF_RXSROVERRUN \ - | SERRF_PARITYERROR \ - | SERRF_FRAMEERROR \ - | SERRF_NOISEERROR) -#define SERRF_TX (SERRF_TXTIMEOUT) -/*\}*/ - -/** - * \name LSB or MSB first data order for SPI driver. - * \{ - */ -#define SER_MSB_FIRST 0 -#define SER_LSB_FIRST 1 -/*\}*/ - -/** - * \name Parity settings for ser_setparity(). - * - * \note Values are AVR-specific for performance reasons. - * Other processors should either decode them or - * redefine these macros. - * \{ - */ -#define SER_PARITY_NONE 0 -#define SER_PARITY_EVEN 2 -#define SER_PARITY_ODD 3 -/*\}*/ - - -struct SerialHardware; - -/** Human-readable serial error descriptions */ -extern const char * const serial_errors[8]; - -/** Serial handle structure */ -typedef struct Serial -{ - /** Physical port number */ - unsigned int unit; - -#ifdef _DEBUG - bool is_open; -#endif - - /** - * \name Transmit and receive FIFOs. - * - * Declared volatile because handled asinchronously by interrupts. - * - * \{ - */ - FIFOBuffer txfifo; - FIFOBuffer rxfifo; - /* \} */ - -#if CONFIG_SER_RXTIMEOUT != -1 - ticks_t rxtimeout; -#endif -#if CONFIG_SER_TXTIMEOUT != -1 - ticks_t txtimeout; -#endif - - /** Holds the flags defined above. Will be 0 when no errors have occurred. */ - volatile serstatus_t status; - - /** Low-level interface to hardware. */ - struct SerialHardware* hw; -} Serial; - -typedef struct KFileSerial -{ - KFile fd; - Serial *ser; -} KFileSerial; - -/** - * ID for serial. - */ -#define KFT_SERIAL MAKE_ID('S', 'E', 'R', 'L') - - -INLINE KFileSerial * KFILESERIAL(KFile *fd) -{ - ASSERT(fd->_type == KFT_SERIAL); - return (KFileSerial *)fd; -} - -/* Function prototypes */ -//extern int ser_getchar_nowait(struct Serial *port); - -void ser_setbaudrate(struct KFileSerial *fd, unsigned long rate); -void ser_setparity(struct KFileSerial *fd, int parity); -void ser_settimeouts(struct KFileSerial *fd, mtime_t rxtimeout, mtime_t txtimeout); -void ser_resync(struct KFileSerial *fd, mtime_t delay); -int ser_getchar_nowait(struct KFileSerial *fd); - -void ser_purgeRx(struct KFileSerial *fd); -void ser_purgeTx(struct KFileSerial *fd); -void ser_purge(struct KFileSerial *fd); -void ser_init(struct KFileSerial *fds, unsigned int unit); -void spimaster_init(KFileSerial *fds, unsigned int unit); - - -/** - * \name Additional functions implemented as macros - * - * \{ - */ -#define ser_getstatus(h) ((h)->status) -#define ser_setstatus(h, x) ((h)->status = (x)) -/* \} */ - -#endif /* DRV_SER_H */ diff --git a/drv/ser_p.h b/drv/ser_p.h deleted file mode 100644 index d0071feb..00000000 --- a/drv/ser_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * \file - * - * - * \brief Hardware dependent serial driver (interface) - * - * \version $Id$ - * - * \author Stefano Fedrigo - * \author Giovanni Bajo - */ - - -#ifndef DRV_SER_P_H -#define DRV_SER_P_H - -#include /* size_t */ - -struct SerialHardware; -struct Serial; - -struct SerialHardwareVT -{ - void (*init)(struct SerialHardware *ctx, struct Serial *ser); - void (*cleanup)(struct SerialHardware *ctx); - void (*setBaudrate)(struct SerialHardware *ctx, unsigned long rate); - void (*setParity)(struct SerialHardware *ctx, int parity); - void (*txStart)(struct SerialHardware *ctx); - bool (*txSending)(struct SerialHardware *ctx); -}; - -struct SerialHardware -{ - const struct SerialHardwareVT *table; - unsigned char *txbuffer; - unsigned char *rxbuffer; - size_t txbuffer_size; - size_t rxbuffer_size; -}; - -struct SerialHardware *ser_hw_getdesc(int unit); - -#endif /* DRV_SER_P_H */ diff --git a/drv/ser_posix.c b/drv/ser_posix.c deleted file mode 100644 index 5306e58d..00000000 --- a/drv/ser_posix.c +++ /dev/null @@ -1,199 +0,0 @@ -/** - * \file - * - * - * \brief Serial port emulator for hosted environments. - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/02/17 22:28:00 bernie - *#* Rename ser_emul.c to ser_posix.c. - *#* - *#* Revision 1.4 2006/02/17 22:23:06 bernie - *#* Update POSIX serial emulator. - *#* - *#* Revision 1.3 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.2 2005/04/11 19:10:27 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.1 2004/12/31 17:40:00 bernie - *#* Add a simple serial emulation driver. - *#* - *#*/ - -#include "ser.h" -#include "ser_p.h" - -#include -#include -#include - -#include - -#include -#include -#include /* open() */ -#include /* read(), write() */ - - -/* From the high-level serial driver */ -extern struct Serial ser_handles[SER_CNT]; - -/* TX and RX buffers */ -static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; -static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; -static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; -static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; - - -/** - * Internal state structure - */ -struct EmulSerial -{ - struct SerialHardware hw; - struct Serial *ser; - int fd; -}; - - -/* - * Callbacks - */ -static void uart_init(struct SerialHardware *_hw, struct Serial *ser) -{ - struct EmulSerial *hw = (struct EmulSerial *)_hw; - - hw->ser = ser; - hw->fd = open("/dev/ttyS0", O_RDWR); -} - -static void uart_cleanup(UNUSED_ARG(struct SerialHardware *, _hw)) -{ - struct EmulSerial *hw = (struct EmulSerial *)_hw; - - close(hw->fd); - hw->fd = -1; -} - -static void uart_txStart(struct SerialHardware * _hw) -{ - struct EmulSerial *hw = (struct EmulSerial *)_hw; - - while(!fifo_isempty(&hw->ser->txfifo)) - { - char c = fifo_pop(&hw->ser->txfifo); - write(hw->fd, &c, 1); - } -} - -static bool uart_txSending(UNUSED_ARG(struct SerialHardware *, _hw)) -{ - return false; -} - - -static void uart_setBaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate) -{ - TRACEMSG("rate=%lu", rate); - // TODO - -} - -static void uart_setParity(UNUSED_ARG(struct SerialHardware *, _hw), int parity) -{ - TRACEMSG("parity=%d", parity); - // TODO -} - -// FIXME: move into compiler.h? Ditch? -#if COMPILER_C99 - #define C99INIT(name,val) .name = val -#elif defined(__GNUC__) - #define C99INIT(name,val) name: val -#else - #warning No designated initializers, double check your code - #define C99INIT(name,val) (val) -#endif - -/* - * High-level interface data structures. - */ -static const struct SerialHardwareVT uart_vtable = -{ - C99INIT(init, uart_init), - C99INIT(cleanup, uart_cleanup), - C99INIT(setBaudrate, uart_setBaudrate), - C99INIT(setParity, uart_setParity), - C99INIT(txStart, uart_txStart), - C99INIT(txSending, uart_txSending), -}; - -static struct EmulSerial UARTDescs[SER_CNT] = -{ - { - C99INIT(hw, /**/) { - C99INIT(table, &uart_vtable), - C99INIT(txbuffer, uart0_txbuffer), - C99INIT(rxbuffer, uart0_rxbuffer), - C99INIT(txbuffer_size, sizeof(uart0_txbuffer)), - C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)), - }, - C99INIT(ser, NULL), - C99INIT(fd, -1), - }, - { - C99INIT(hw, /**/) { - C99INIT(table, &uart_vtable), - C99INIT(txbuffer, uart1_txbuffer), - C99INIT(rxbuffer, uart1_rxbuffer), - C99INIT(txbuffer_size, sizeof(uart1_txbuffer)), - C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)), - }, - C99INIT(ser, NULL), - C99INIT(fd, -1), - }, -}; - -struct SerialHardware *ser_hw_getdesc(int unit) -{ - ASSERT(unit < SER_CNT); - return &UARTDescs[unit].hw; -} diff --git a/drv/spi_bitbang.c b/drv/spi_bitbang.c deleted file mode 100644 index 90e959d8..00000000 --- a/drv/spi_bitbang.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * \file - * - * - * \brief Emulated SPI Master for DSP firmware download (impl.) - * - * \version $Id: spi.c 15328 2007-03-21 15:07:04Z batt $ - * - * \author Francesco Sacchi - * \author Daniele Basile - */ - - -#include -#include -#include -#include "hw_spi.h" - -void spi_assertSS(void) -{ - ATOMIC(SS_ACTIVE()); -} - -void spi_deassertSS(void) -{ - ATOMIC(SS_INACTIVE()); -} - -/** - * Send byte \c c over MOSI line, CONFIG_SPI_DATAORDER first. - * SS pin state is left unchanged. - */ -uint8_t spi_sendRecv(uint8_t c) -{ - uint8_t data = 0; - uint8_t shift = SPI_DATAORDER_START; - - - ATOMIC( - for (int i = 0; i < 8; i++) - { - /* Shift the i-th bit to MOSI */ - if (c & shift) - MOSI_HIGH(); - else - MOSI_LOW(); - /* Assert clock */ - SCK_ACTIVE(); - data |= IS_MISO_HIGH() ? shift : 0; - /* De-assert clock */ - SCK_INACTIVE(); - SPI_DATAORDER_SHIFT(shift); - } - ); - return data; -} - -MOD_DEFINE(spi); -void spi_init(void) -{ - ATOMIC(SPI_HW_INIT()); - MOD_INIT(spi); -} - -/** - * Read \param len from spi, and put it in \param _buff . - */ -void spi_read(void *_buff, size_t len) -{ - uint8_t *buff = (uint8_t *)_buff; - - while (len--) - /* Read byte from spi and put it in buffer. */ - *buff++ = spi_sendRecv(0); - -} - -/** - * Write \param len to spi, and take it from \param _buff . - */ -void spi_write(const void *_buff, size_t len) -{ - const uint8_t *buff = (const uint8_t *)_buff; - - while (len--) - /* Write byte pointed at by *buff to spi */ - spi_sendRecv(*buff++); - -} diff --git a/drv/spi_bitbang.h b/drv/spi_bitbang.h deleted file mode 100644 index ff716906..00000000 --- a/drv/spi_bitbang.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * \file - * - * - * \brief Emulated SPI Master for DSP firmware download (interface) - * - * \version $Id: spi.h 15321 2007-03-21 14:45:12Z asterix $ - * - * \author Francesco Sacchi - * \author Daniele Basile - */ - - -#ifndef DRV_SPI_EMU_H -#define DRV_SPI_EMU_H - -#include -#include - -/** - * Define send and receive order bit. - * \{ - */ -#define SPI_LSB_FIRST 1 -#define SPI_MSB_FIRST 2 -/* \} */ - -#if CONFIG_SPI_DATAORDER == SPI_LSB_FIRST - #define SPI_DATAORDER_START 1 - #define SPI_DATAORDER_SHIFT(i) ((i) <<= 1) -#elif CONFIG_SPI_DATAORDER == SPI_MSB_FIRST - #define SPI_DATAORDER_START 0x80 - #define SPI_DATAORDER_SHIFT(i) ((i) >>= 1) -#endif - -void spi_write(const void *buf, size_t len); -void spi_read(void *buf, size_t len); -uint8_t spi_sendRecv(uint8_t c); -void spi_init(void); -void spi_assertSS(void); -void spi_deassertSS(void); - -#endif /* DRV_SPI_EMU_H */ diff --git a/drv/tc520.c b/drv/tc520.c deleted file mode 100644 index 615a94e0..00000000 --- a/drv/tc520.c +++ /dev/null @@ -1,162 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief TC520 ADC driver (implementation) - * - * \version $Id$ - * \author Francesco Sacchi - * \author Marco Benelli - */ - -#include -#include - -#include - -#include -#include - -#include - -static Serial *spi_ser; - -#define TC520_CONVERSION_TIMEOUT ms_to_ticks(1000) -#define INIT_LOAD_VALUE 0x00 - -/** - * Start an AD conversion and return result. - * - * To start a conversion first we must pull down CE pin. - * The ADC starts a convertion and keeps the DV pin high until the end. - * At this point, we can read the conversion value by SPI. - * The convertion result is yield in 3 bytes. - * - * \verbatim - * - * First byte: - * bit | Value - * ----|------- - * 7 | Overrange - * 6 | Polarity - * 5:0 | data bits 15:10 - * - * Second byte: data 9:2 - * - * Third byte: - * bit | Value - * ----|------- - * 7 | data bit 1 - * 6 | data bit 0 - * 5:0 | '0' - * - * \endverbatim - * - * So, to get the result we must shift and recompose the bits. - * \note Overrange bit is handled as the 17th data bit. - */ -tc520_data_t tc520_read(void) -{ - /* Start convertion and wait */ - CE_LOW(); - ticks_t start = timer_clock(); - do - { - /* timeout check */ - if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) - { - ASSERT(0); - CE_HIGH(); - return TC520_MAX_VALUE; - } - } - while(DV_LOW()); - - start = timer_clock(); - do - { - /* timeout check */ - if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) - { - ASSERT(0); - CE_HIGH(); - return TC520_MAX_VALUE; - } - } - while(DV_HIGH()); - - /* Ok, convertion finished, read result */ - CE_HIGH(); - READ_LOW(); - - /* RX buffer could be dirty...*/ - ser_purge(spi_ser); - - /* I/O buffer */ - uint8_t buf[3] = "\x0\x0\x0"; - - /* Dummy write to activate recv */ - ser_write(spi_ser, buf, sizeof(buf)); - ser_drain(spi_ser); - READ_HIGH(); - - /* recv */ - ASSERT(ser_read(spi_ser, buf, sizeof(buf)) == sizeof(buf)); - - tc520_data_t res; - - /* Recompose data */ - res = (((tc520_data_t)(buf[0] & 0x3F)) << 10) | (((tc520_data_t)buf[1]) << 2) | (((tc520_data_t)buf[2]) >> 6); - - #define OVERRANGE_BIT BV(7) - /* Handle overrange bit as 17th bit */ - if (buf[0] & OVERRANGE_BIT) - res |= BV32(16); - - return res; -} - - -/** - * Initialize tc520 A/D converter driver - */ -void tc520_init(Serial *spi_port) -{ - spi_ser = spi_port; - /* init io ports */ - TC520_HW_INIT; - /* Send initial load value */ - LOAD_LOW(); - ser_putchar(INIT_LOAD_VALUE, spi_ser); - ser_drain(spi_ser); - LOAD_HIGH(); -} diff --git a/drv/tc520.h b/drv/tc520.h deleted file mode 100644 index c36238f7..00000000 --- a/drv/tc520.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief TC520 ADC driver (intercace) - * - * \version $Id$ - * \author Francesco Sacchi - * \author Marco Benelli - */ - -#ifndef DRV_TC520_H -#define DRV_TC520_H - -#include -#include - -typedef uint32_t tc520_data_t; - -/* 17 bit max value */ -#define TC520_MAX_VALUE 0x1FFFFUL - -tc520_data_t tc520_read(void); -void tc520_init(Serial *spi_port); - -#endif /* DRV_TC520_H */ diff --git a/drv/thermo.c b/drv/thermo.c deleted file mode 100644 index fb8cbb79..00000000 --- a/drv/thermo.c +++ /dev/null @@ -1,274 +0,0 @@ -/** - * \file - * - * - * \brief Thermo-control driver - * - * \version $Id$ - * - * \author Giovanni Bajo - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.3 2006/09/20 20:12:41 marco - *#* Names convention, MOD_* macros. - *#* - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 17:59:47 bernie - *#* Import into DevLib. - *#* - *#*/ -#include -#include - -#include -#include -#include - -#include -#include - - -/** Interval at which thermo control is performed. */ -#define THERMO_INTERVAL_MS 100 - -/** Number of different samples we interpolate over to get the hifi temperature. */ -#define THERMO_HIFI_NUM_SAMPLES 10 - -/** Timer for thermo-regulation. */ -static Timer thermo_timer; - -typedef struct ThermoControlDev -{ - deg_t hifi_samples[THERMO_HIFI_NUM_SAMPLES]; - deg_t cur_hifi_sample; - deg_t target; - thermostatus_t status; - ticks_t expire; -} ThermoControlDev; - -/** Array of thermo-devices. */ -ThermoControlDev devs[THERMO_CNT]; - - -/** - * Return the status of the specific \a dev thermo-device. - */ -thermostatus_t thermo_status(ThermoDev dev) -{ - return devs[dev].status; -} - - -/** - * Do a single thermo control for device \a dev. - */ -static void thermo_do(ThermoDev index) -{ - ThermoControlDev* dev = &devs[index]; - deg_t cur_temp; - deg_t tolerance = thermo_hw_tolerance(index); - - cur_temp = thermo_hw_read(index); - - // Store the sample into the hifi FIFO buffer for later interpolation - dev->hifi_samples[dev->cur_hifi_sample] = cur_temp; - if (++dev->cur_hifi_sample == THERMO_HIFI_NUM_SAMPLES) - dev->cur_hifi_sample = 0; - - cur_temp = thermo_readTemperature(index); - - if (cur_temp == NTC_SHORT_CIRCUIT || cur_temp == NTC_OPEN_CIRCUIT) - { - if (cur_temp == NTC_SHORT_CIRCUIT) - { - #ifdef _DEBUG - if (!(dev->status & THERMOERRF_NTCSHORT)) - kprintf("dev[%d], thermo_do: NTC_SHORT\n",index); - #endif - dev->status |= THERMOERRF_NTCSHORT; - } - else - { - #ifdef _DEBUG - if (!(dev->status & THERMOERRF_NTCOPEN)) - kprintf("dev[%d], thermo_do: NTC_OPEN\n", index); - #endif - dev->status |= THERMOERRF_NTCOPEN; - } - - /* Reset timeout when there is an ntc error */ - dev->expire = thermo_hw_timeout(index) + timer_clock(); - thermo_hw_off(index); - return; - } - dev->status &= ~(THERMOERRF_NTCOPEN | THERMOERRF_NTCSHORT); - - if ((cur_temp < dev->target - tolerance) || (cur_temp > dev->target + tolerance)) - { - dev->status &= ~THERMO_TGT_REACH; - - /* Check for timeout */ - if (timer_clock() - dev->expire > 0) - { - dev->status |= THERMOERRF_TIMEOUT; - kprintf("dev[%d], thermo_do: TIMEOUT\n", index); - } - } - else /* In target */ - { - /* Clear errors */ - dev->status &= ~THERMO_ERRMASK; - dev->status |= THERMO_TGT_REACH; - - /* Reset timeout in case we go out of target in the future */ - dev->expire = thermo_hw_timeout(index) + timer_clock(); - } - - if (cur_temp < dev->target) - dev->status = (dev->status | THERMO_HEATING) & ~THERMO_FREEZING; - else - dev->status = (dev->status & ~THERMO_HEATING) | THERMO_FREEZING; - - thermo_hw_set(index, dev->target, cur_temp); - -} - - -/** - * Thermo soft interrupt. - */ -static void thermo_softint(void) -{ - int i; - for (i = 0; i < THERMO_CNT; ++i) - if (devs[i].status & THERMO_ACTIVE) - thermo_do((ThermoDev)i); - - timer_add(&thermo_timer); -} - - -/** - * Set the target temperature \a temperature for a specific \a dev thermo-device. - */ -void thermo_setTarget(ThermoDev dev, deg_t temperature) -{ - ASSERT(dev < THERMO_CNT); - devs[dev].target = temperature; - devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); - - kprintf("setTarget dev[%d], T[%d.%d]\n", dev, temperature / 10, temperature % 10); -} - -/** - * Starts a thermo-regulation for channel \a dev. - */ -void thermo_start(ThermoDev dev) -{ - int i; - deg_t temp; - - ASSERT(dev < THERMO_CNT); - - devs[dev].status |= THERMO_ACTIVE; - - /* Initialize the hifi FIFO with a constant value (the current temperature) */ - temp = thermo_hw_read(dev); - for (i = 0; i < THERMO_HIFI_NUM_SAMPLES; ++i) - devs[dev].hifi_samples[i] = temp; - devs[dev].cur_hifi_sample = 0; - - /* Reset timeout */ - devs[dev].expire = timer_clock() + thermo_hw_timeout(dev); -} - -/** - * Stops a thermo-regulation for channel \a dev. - */ -void thermo_stop(ThermoDev dev) -{ - ASSERT(dev < THERMO_CNT); - - devs[dev].status &= ~THERMO_ACTIVE; - thermo_hw_off(dev); -} - - -/** - * Clear errors for channel \a dev. - */ -void thermo_clearErrors(ThermoDev dev) -{ - ASSERT(dev < THERMO_CNT); - devs[dev].status &= ~(THERMO_ERRMASK); -} - - -/** - * Read the temperature of the thermo-device \a dev using mobile mean. - */ -deg_t thermo_readTemperature(ThermoDev dev) -{ - int i; - long accum = 0; - - MOD_CHECK(thermo); - - for (i = 0; i < THERMO_HIFI_NUM_SAMPLES; i++) - accum += devs[dev].hifi_samples[i]; - - return (deg_t)(accum / THERMO_HIFI_NUM_SAMPLES); -} - -MOD_DEFINE(thermo) - -/** - * Init thermo-control and associated hw. - */ -void thermo_init(void) -{ - THERMO_HW_INIT; - - /* Set all status to off */ - for (int i = 0; i < THERMO_CNT; i++) - devs[i].status = THERMO_OFF; - - MOD_INIT(thermo); - - timer_setDelay(&thermo_timer, ms_to_ticks(THERMO_INTERVAL_MS)); - timer_set_event_softint(&thermo_timer, (Hook)thermo_softint, 0); - timer_add(&thermo_timer); -} diff --git a/drv/thermo.h b/drv/thermo.h deleted file mode 100644 index 693c086d..00000000 --- a/drv/thermo.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * \file - * - * - * \brief Thermo-control driver - * - * \version $Id$ - * - * \author Giovanni Bajo - * \author Francesco Sacchi - * - * This module implements multiple thermo controls, which is the logic needed to try - * keeping the temperature of a device constant. For this module, a "device" is a black box - * whose temperature can be measured, and which has a mean to make it hotter or colder. - * For instance, a device could be the combination of a NTC (analog temperature reader) and - * a Peltier connected to the same physic block. - * - * This module relies on a low-level driver to communicate with the device (implementation - * of the black box). This low-level driver also controls the units in which the temperature - * is expressed: thermo control treats it just as a number. - * - */ - -/*#* - *#* $Log$ - *#* Revision 1.3 2006/09/20 20:12:41 marco - *#* Names convention, MOD_* macros. - *#* - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 17:59:47 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.2 2005/06/14 10:13:36 batt - *#* Better thermo errors handling. - *#* - *#* Revision 1.1 2005/05/24 09:17:58 batt - *#* Move drivers to top-level. - *#* - *#* Revision 1.4 2005/05/10 16:55:10 batt - *#* Add timeout to thermo-regulator; better thermo control handling; change thermo_getStatus() to thermo_status(). - *#* - *#* Revision 1.3 2005/05/10 09:26:54 batt - *#* Add thermo_getStatus for getting status/errors of thermo control. - *#* - *#* Revision 1.2 2005/05/09 19:18:40 batt - *#* Remove old logs. - *#* - *#* Revision 1.1 2005/05/09 16:40:44 batt - *#* Add thermo-control driver - *#*/ - - -#ifndef DRV_THERMO_H -#define DRV_THERMO_H - -#include -#include - -void thermo_init(void); - - -/** - * Set the target temperature at which a given device should be kept. - * - * \param dev Device - * \param temperature Target temperature - */ -void thermo_setTarget(ThermoDev dev, deg_t temperature); - -/** Start thermo control for a certain device \a dev */ -void thermo_start(ThermoDev dev); - -/** Stop thermo control for a certain device \a dev */ -void thermo_stop(ThermoDev dev); - -/** Clear errors for channel \a dev */ -void thermo_clearErrors(ThermoDev dev); - -/** Return the status of the specific \a dev thermo-device. */ -thermostatus_t thermo_status(ThermoDev dev); - -/** - * Return the current temperature of a device currently under thermo - * control. - * - * \param dev Device - * \return Current temperature (Celsius degrees * 10) - */ -deg_t thermo_readTemperature(ThermoDev dev); - - -#endif /* DRV_THERMO_H */ diff --git a/drv/timer.c b/drv/timer.c deleted file mode 100644 index 0e756dbb..00000000 --- a/drv/timer.c +++ /dev/null @@ -1,339 +0,0 @@ -/** - * \file - * - * - * \brief Hardware independent timer driver (implementation) - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "timer.h" - -#include -#include -#include - -#include -#include -#include -#include - -/* - * Include platform-specific binding code if we're hosted. - * Try the CPU specific one for bare-metal environments. - */ -#if OS_HOSTED - #include OS_CSOURCE(timer) -#else - #include CPU_CSOURCE(timer) -#endif - -/* - * Sanity check for config parameters required by this module. - */ -#if !defined(CONFIG_KERNEL) || ((CONFIG_KERNEL != 0) && CONFIG_KERNEL != 1) - #error CONFIG_KERNEL must be set to either 0 or 1 in config.h -#endif -#if !defined(CONFIG_WATCHDOG) || ((CONFIG_WATCHDOG != 0) && CONFIG_WATCHDOG != 1) - #error CONFIG_WATCHDOG must be set to either 0 or 1 in config.h -#endif - -#if CONFIG_WATCHDOG - #include -#endif - -#if CONFIG_KERNEL - #include - #if CONFIG_KERN_PREEMPTIVE - #include - #endif - #if CONFIG_KERN_SIGNALS - #include /* sig_wait(), sig_check() */ - #include /* proc_current() */ - #include /* BV() */ - #endif -#endif - - -/** - * \def CONFIG_TIMER_STROBE - * - * This is a debug facility that can be used to - * monitor timer interrupt activity on an external pin. - * - * To use strobes, redefine the macros TIMER_STROBE_ON, - * TIMER_STROBE_OFF and TIMER_STROBE_INIT and set - * CONFIG_TIMER_STROBE to 1. - */ -#if !defined(CONFIG_TIMER_STROBE) || !CONFIG_TIMER_STROBE - #define TIMER_STROBE_ON do {/*nop*/} while(0) - #define TIMER_STROBE_OFF do {/*nop*/} while(0) - #define TIMER_STROBE_INIT do {/*nop*/} while(0) -#endif - - -/// Master system clock (1 tick accuracy) -volatile ticks_t _clock; - - -#ifndef CONFIG_TIMER_DISABLE_EVENTS - -/** - * List of active asynchronous timers. - */ -REGISTER static List timers_queue; - - -/** - * Add the specified timer to the software timer service queue. - * When the delay indicated by the timer expires, the timer - * device will execute the event associated with it. - * - * \note Interrupt safe - */ -void timer_add(Timer *timer) -{ - Timer *node; - cpuflags_t flags; - - - /* Inserting timers twice causes mayhem. */ - ASSERT(timer->magic != TIMER_MAGIC_ACTIVE); - DB(timer->magic = TIMER_MAGIC_ACTIVE;) - - IRQ_SAVE_DISABLE(flags); - - /* Calculate expiration time for this timer */ - timer->tick = _clock + timer->_delay; - - /* - * Search for the first node whose expiration time is - * greater than the timer we want to add. - */ - node = (Timer *)LIST_HEAD(&timers_queue); - while (node->link.succ) - { - /* - * Stop just after the insertion point. - * (this fancy compare takes care of wrap-arounds). - */ - if (node->tick - timer->tick > 0) - break; - - /* Go to next node */ - node = (Timer *)node->link.succ; - } - - /* Enqueue timer request into the list */ - INSERT_BEFORE(&timer->link, &node->link); - - IRQ_RESTORE(flags); -} - - -/** - * Remove a timer from the timer queue before it has expired. - */ -Timer *timer_abort(Timer *timer) -{ - ATOMIC(REMOVE(&timer->link)); - DB(timer->magic = TIMER_MAGIC_INACTIVE;) - - return timer; -} - -#endif /* CONFIG_TIMER_DISABLE_EVENTS */ - - -/** - * Wait for the specified amount of timer ticks. - */ -void timer_delayTicks(ticks_t delay) -{ -#if defined(IRQ_ENABLED) - /* We shouldn't sleep with interrupts disabled */ - ASSERT(IRQ_ENABLED()); -#endif - -#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS - Timer t; - - ASSERT(!sig_check(SIG_SINGLE)); - timer_set_event_signal(&t, proc_current(), SIG_SINGLE); - timer_setDelay(&t, delay); - timer_add(&t); - sig_wait(SIG_SINGLE); - -#else /* !CONFIG_KERN_SIGNALS */ - - ticks_t start = timer_clock(); - - /* Busy wait */ - while (timer_clock() - start < delay) - { -#if CONFIG_WATCHDOG - wdt_reset(); -#endif - } - -#endif /* !CONFIG_KERN_SIGNALS */ -} - - -#ifndef CONFIG_TIMER_DISABLE_UDELAY - -/** - * Busy wait until the specified amount of high-precision ticks have elapsed. - * - * \note This function is interrupt safe, the only - * requirement is a running hardware timer. - */ -void timer_busyWait(hptime_t delay) -{ - hptime_t now, prev = timer_hw_hpread(); - hptime_t delta; - - for(;;) - { - now = timer_hw_hpread(); - /* - * We rely on hptime_t being unsigned here to - * reduce the modulo to an AND in the common - * case of TIMER_HW_CNT. - */ - delta = (now - prev) % TIMER_HW_CNT; - if (delta >= delay) - break; - delay -= delta; - prev = now; - } -} - -/** - * Wait for the specified amount of time (expressed in microseconds). - * - * \bug In AVR arch the maximum amount of time that can be used as - * delay could be very limited, depending on the hardware timer - * used. Check timer_avr.h, and what register is used as hptime_t. - */ -void timer_delayHp(hptime_t delay) -{ - if (UNLIKELY(delay > us_to_hptime(1000))) - { - timer_delayTicks(delay / (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC)); - delay %= (TIMER_HW_HPTICKS_PER_SEC / TIMER_TICKS_PER_SEC); - } - - timer_busyWait(delay); -} -#endif /* CONFIG_TIMER_DISABLE_UDELAY */ - - -/** - * Timer interrupt handler. Find soft timers expired and - * trigger corresponding events. - */ -DEFINE_TIMER_ISR -{ - /* - * With the Metrowerks compiler, the only way to force the compiler generate - * an interrupt service routine is to put a pragma directive within the function - * body. - */ - #ifdef __MWERKS__ - #pragma interrupt saveall - #endif - -#ifndef CONFIG_TIMER_DISABLE_EVENTS - Timer *timer; -#endif - /* - * On systems sharing IRQ line and vector, this check is needed - * to ensure that IRQ is generated by timer source. - */ - if (!timer_hw_triggered()) - return; - - TIMER_STROBE_ON; - - /* Perform hw IRQ handling */ - timer_hw_irq(); - - /* Update the master ms counter */ - ++_clock; - -#ifndef CONFIG_TIMER_DISABLE_EVENTS - /* - * Check the first timer request in the list and process - * it when it has expired. Repeat this check until the - * first node has not yet expired. Since the list is sorted - * by expiry time, all the following requests are guaranteed - * to expire later. - */ - while ((timer = (Timer *)LIST_HEAD(&timers_queue))->link.succ) - { - /* This request in list has not yet expired? */ - if (_clock - timer->tick < 0) - break; - - /* Retreat the expired timer */ - REMOVE(&timer->link); - DB(timer->magic = TIMER_MAGIC_INACTIVE;) - - /* Execute the associated event */ - event_do(&timer->expire); - } -#endif /* CONFIG_TIMER_DISABLE_EVENTS */ - - TIMER_STROBE_OFF; -} - -MOD_DEFINE(timer) - -/** - * Initialize timer - */ -void timer_init(void) -{ - TIMER_STROBE_INIT; - -#ifndef CONFIG_TIMER_DISABLE_EVENTS - LIST_INIT(&timers_queue); -#endif - - _clock = 0; - - timer_hw_init(); - - MOD_INIT(timer); -} diff --git a/drv/timer.h b/drv/timer.h deleted file mode 100644 index cd7aa1b4..00000000 --- a/drv/timer.h +++ /dev/null @@ -1,247 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Hardware independent timer driver (interface) - */ - -#ifndef DRV_TIMER_H -#define DRV_TIMER_H - -#include -#include -#include -#include - - -/* - * Include platform-specific binding header if we're hosted. - * Try the CPU specific one for bare-metal environments. - */ -#if OS_HOSTED - #include OS_HEADER(timer) -#else - #include CPU_HEADER(timer) -#endif - -#include -#include -#include -#include - - -extern volatile ticks_t _clock; - -/** - * \brief Return the system tick counter (expressed in ticks) - * - * The result is guaranteed to increment monotonically, - * but client code must be tolerant with respect to overflows. - * - * The following code is safe: - * - * \code - * ticks_t tea_start_time = timer_clock(); - * - * boil_water(); - * - * if (timer_clock() - tea_start_time > TEAPOT_DELAY) - * printf("Your tea, Sir.\n"); - * \endcode - * - * \note This function must disable interrupts on 8/16bit CPUs because the - * clock variable is larger than the processor word size and can't - * be copied atomically. - */ -INLINE ticks_t timer_clock(void) -{ - ticks_t result; - - ATOMIC(result = _clock); - - return result; -} - -/** - * Faster version of timer_clock(), to be called only when the timer - * interrupt is disabled (DISABLE_INTS) or overridden by a - * higher-priority or non-nesting interrupt. - * - * \sa timer_clock - */ -INLINE ticks_t timer_clock_unlocked(void) -{ - return _clock; -} - -/** Convert \a ms [ms] to ticks. */ -INLINE ticks_t ms_to_ticks(mtime_t ms) -{ -#if TIMER_TICKS_PER_SEC < 1000 - /* Slow timer: avoid rounding down too much. */ - return (ms * TIMER_TICKS_PER_SEC) / 1000; -#else - /* Fast timer: don't overflow ticks_t. */ - return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000); -#endif -} - -/** Convert \a us [us] to ticks. */ -INLINE ticks_t us_to_ticks(utime_t us) -{ -#if TIMER_TICKS_PER_SEC < 1000 - /* Slow timer: avoid rounding down too much. */ - return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000; -#else - /* Fast timer: don't overflow ticks_t. */ - return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000; -#endif -} - -/** Convert \a ticks [ticks] to ms. */ -INLINE mtime_t ticks_to_ms(ticks_t ticks) -{ -#if TIMER_TICKS_PER_SEC < 1000 - /* Slow timer: avoid rounding down too much. */ - return (ticks * 1000) / TIMER_TICKS_PER_SEC; -#else - /* Fast timer: avoid overflowing ticks_t. */ - return ticks / (TIMER_TICKS_PER_SEC / 1000); -#endif -} - -/** Convert \a ticks [ticks] to us. */ -INLINE utime_t ticks_to_us(ticks_t ticks) -{ -#if TIMER_TICKS_PER_SEC < 1000 - /* Slow timer: avoid rounding down too much. */ - return ((ticks * 1000) / TIMER_TICKS_PER_SEC) * 1000; -#else - /* Fast timer: avoid overflowing ticks_t. */ - return (ticks / (TIMER_TICKS_PER_SEC / 1000)) * 1000; -#endif -} - -/** Convert \a us [us] to hpticks */ -INLINE hptime_t us_to_hptime(utime_t us) -{ -#if TIMER_HW_HPTICKS_PER_SEC > 10000000UL - return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL); -#else - return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL; -#endif -} - -/** Convert \a hpticks [hptime] to usec */ -INLINE utime_t hptime_to_us(hptime_t hpticks) -{ -#if TIMER_HW_HPTICKS_PER_SEC < 100000UL - return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC); -#else - return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL); -#endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */ -} - - -void timer_init(void); -void timer_delayTicks(ticks_t delay); -INLINE void timer_delay(mtime_t delay) -{ - timer_delayTicks(ms_to_ticks(delay)); -} - -#if !defined(CONFIG_TIMER_DISABLE_UDELAY) -void timer_busyWait(hptime_t delay); -void timer_delayHp(hptime_t delay); -INLINE void timer_udelay(utime_t delay) -{ - timer_delayHp(us_to_hptime(delay)); -} -#endif - -#ifndef CONFIG_TIMER_DISABLE_EVENTS - -#include - -/** - * The timer driver supports multiple synchronous timers - * that can trigger an event when they expire. - * - * \sa timer_add() - * \sa timer_abort() - */ -typedef struct Timer -{ - Node link; /**< Link into timers queue */ - ticks_t _delay; /**< Timer delay in ms */ - ticks_t tick; /**< Timer will expire at this tick */ - Event expire; /**< Event to execute when the timer expires */ - DB(uint16_t magic;) -} Timer; - -/** Timer is active when Timer.magic contains this value (for debugging purposes). */ -#define TIMER_MAGIC_ACTIVE 0xABBA -#define TIMER_MAGIC_INACTIVE 0xBAAB - -extern void timer_add(Timer *timer); -extern Timer *timer_abort(Timer *timer); - -/** Set the timer so that it calls an user hook when it expires */ -INLINE void timer_set_event_softint(Timer *timer, Hook func, iptr_t user_data) -{ - event_initSoftInt(&timer->expire, func, user_data); -} - -/** Set the timer delay (the time before the event will be triggered) */ -INLINE void timer_setDelay(Timer *timer, ticks_t delay) -{ - timer->_delay = delay; -} - -#endif /* CONFIG_TIMER_DISABLE_EVENTS */ - -#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS - -/** Set the timer so that it sends a signal when it expires */ -INLINE void timer_set_event_signal(Timer *timer, struct Process *proc, sigmask_t sigs) -{ - event_initSignal(&timer->expire, proc, sigs); -} - -#endif /* CONFIG_KERN_SIGNALS */ - - -#endif /* DRV_TIMER_H */ diff --git a/drv/timer_posix.c b/drv/timer_posix.c deleted file mode 100644 index e6149cea..00000000 --- a/drv/timer_posix.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Low-level timer module for Qt emulator (implementation). - */ -#include // hptime.t -#include - -#include // sigaction() -#include // setitimer() -#include // memset() - - -// Forward declaration for the user interrupt server routine. -void timer_isr(int); - -/// HW dependent timer initialization. -static void timer_hw_init(void) -{ - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - - // Setup interrupt callback - sa.sa_handler = timer_isr; - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGALRM); - sa.sa_flags = SA_RESTART; - sigaction(SIGALRM, &sa, NULL); - - // Setup POSIX realtime timer to interrupt every 1/TIMER_TICKS_PER_SEC. - static struct itimerval itv = - { - { 0, 1000000 / TIMER_TICKS_PER_SEC }, /* it_interval */ - { 0, 1000000 / TIMER_TICKS_PER_SEC } /* it_value */ - }; - setitimer(ITIMER_REAL, &itv, NULL); -} - -INLINE hptime_t timer_hw_hpread(void) -{ - return hptime_get(); -} diff --git a/drv/timer_posix.h b/drv/timer_posix.h deleted file mode 100644 index fd2e9c60..00000000 --- a/drv/timer_posix.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Low-level timer module for POSIX systems (interface). - */ -#ifndef DRV_TIMER_POSIX_H -#define DRV_TIMER_POSIX_H - -// HW dependent timer initialization - -#define DEFINE_TIMER_ISR void timer_isr(UNUSED_ARG(int, arg)) - -/** Most Linux kernels can't do better than this (CONFIG_HZ=250). */ -#define TIMER_TICKS_PER_SEC 250 - -#define TIMER_HW_CNT (1<<31) /* We assume 32bit integers here */ - -#include - -/// Frequency of the hardware high-precision timer. -#define TIMER_HW_HPTICKS_PER_SEC HPTIME_TICKS_PER_SECOND - -/// Not needed. -#define timer_hw_irq() do {} while (0) - -#endif /* DRV_TIMER_POSIX_H */ diff --git a/drv/timer_qt.c b/drv/timer_qt.c deleted file mode 100644 index 6f96da64..00000000 --- a/drv/timer_qt.c +++ /dev/null @@ -1,129 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Low-level timer module for Qt emulator (implementation). - */ -#include /* hptime.t */ - -// Qt headers -#include -#include - - -// The user interrupt server routine -void timer_isr(void); - - -/** - * Singleton class for Qt-based hardware timer emulation. - */ -class EmulTimer : public QObject -{ -private: - Q_OBJECT; - - /// System timer (counts ms since application startup) - QTime system_time; - - /// The 1ms "hardware" tick counter. - QTimer timer; - - /** - * We deliberately don't use RAII because the real hardware - * we're simulating needs to be initialized manually. - */ - bool initialized; - - /// Private ctor (singleton) - EmulTimer() : initialized(false) { } - -public: - /// Return singleton instance - static EmulTimer &instance() - { - static EmulTimer et; - return et; - } - - /// Start timer emulator. - void init() - { - // Timer initialized twice? - ASSERT(!initialized); - - // Record initial time - system_time.start(); - - // Activate timer interrupt - timer.connect(&timer, SIGNAL(timeout()), this, SLOT(timerInterrupt())); - timer.start(1000 / TIMER_TICKS_PER_SEC); - - initialized = true; - } - - /// Return current time in high-precision format. - hptime_t hpread() - { - ASSERT(initialized); - return system_time.elapsed(); - } - -public slots: - void timerInterrupt(void) - { - // Just call user interrupt server, timer restarts automatically. - timer_isr(); - } - -}; - -#include "timer_qt_moc.cpp" - - -/// HW dependent timer initialization. -static void timer_hw_init(void) -{ - // Kick EmulTimer initialization - EmulTimer::instance().init(); -} - -INLINE hptime_t timer_hw_hpread(void) -{ - return EmulTimer::instance().hpread(); -} - -/** Not needed, timer IRQ handler called only for timer source */ -#define timer_hw_triggered() (true) diff --git a/drv/timer_qt.h b/drv/timer_qt.h deleted file mode 100644 index 76268fd4..00000000 --- a/drv/timer_qt.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Low-level timer module for Qt emulator (interface). - */ -#ifndef DRV_TIMER_QT_H -#define DRV_TIMER_QT_H - -// HW dependent timer initialization - -#define DEFINE_TIMER_ISR void timer_isr(void) -#define TIMER_TICKS_PER_SEC 250 -#define TIMER_HW_CNT (1<<31) /* We assume 32bit integers here */ - -/// Type of time expressed in ticks of the hardware high-precision timer. -typedef unsigned int hptime_t; - -/// Frequency of the hardware high-precision timer. -#define TIMER_HW_HPTICKS_PER_SEC 1000 - -/// Not needed. -#define timer_hw_irq() do {} while (0) - -#endif /* DRV_TIMER_QT_H */ diff --git a/drv/timer_test.c b/drv/timer_test.c deleted file mode 100644 index 170105de..00000000 --- a/drv/timer_test.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - * \file - * - * - * \brief Hardware independent timer driver (implementation) - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "timer.c" -#include "mware/event.c" -#include "os/hptime.c" - -static void timer_test_constants(void) -{ - kprintf("TIMER_HW_HPTICKS_PER_SEC=%lu\n", TIMER_HW_HPTICKS_PER_SEC); - #ifdef TIMER_PRESCALER - kprintf("TIMER_PRESCALER=%d\n", TIMER_PRESCALER); - #endif - #ifdef TIMER1_OVF_COUNT - kprintf("TIMER1_OVF_COUNT=%d\n", (int)TIMER1_OVF_COUNT); - #endif - kprintf("TIMER_TICKS_PER_SEC=%d\n", (int)TIMER_TICKS_PER_SEC); - kprintf("\n"); - kprintf("ms_to_ticks(100)=%lu\n", ms_to_ticks(100)); - kprintf("ms_to_ticks(10000)=%lu\n", ms_to_ticks(10000)); - kprintf("us_to_ticks(100)=%lu\n", us_to_ticks(100)); - kprintf("us_to_ticks(10000)=%lu\n", us_to_ticks(10000)); - kprintf("\n"); - kprintf("ticks_to_ms(100)=%lu\n", ticks_to_ms(100)); - kprintf("ticks_to_ms(10000)=%lu\n", ticks_to_ms(10000)); - kprintf("ticks_to_us(100)=%lu\n", ticks_to_us(100)); - kprintf("ticks_to_us(10000)=%lu\n", ticks_to_us(10000)); - kprintf("\n"); - kprintf("hptime_to_us(100)=%lu\n", hptime_to_us(100)); - kprintf("hptime_to_us(10000)=%lu\n", hptime_to_us(10000)); - kprintf("us_to_hptime(100)=%lu\n", us_to_hptime(100)); - kprintf("us_to_hptime(10000)=%lu\n", us_to_hptime(10000)); -} - -static void timer_test_delay(void) -{ - int i; - - kputs("Delay test\n"); - for (i = 0; i < 1000; i += 100) - { - kprintf("delay %d...", i); - timer_delay(i); - kputs("done\n"); - } -} - -static void timer_test_hook(iptr_t _timer) -{ - Timer *timer = (Timer *)(void *)_timer; - - kprintf("Timer %ld expired\n", ticks_to_ms(timer->_delay)); - timer_add(timer); -} - -static void timer_test_async(void) -{ - static Timer test_timers[5]; - static const mtime_t test_delays[5] = { 170, 50, 310, 1500, 310 }; - size_t i; - - for (i = 0; i < countof(test_timers); ++i) - { - Timer *timer = &test_timers[i]; - timer_setDelay(timer, ms_to_ticks(test_delays[i])); - timer_set_event_softint(timer, timer_test_hook, (iptr_t)timer); - timer_add(timer); - } -} - -static void timer_test_poll(void) -{ - int secs = 0; - mtime_t start_time = ticks_to_ms(timer_clock()); - mtime_t now; - - while (secs <= 10) - { - now = ticks_to_ms(timer_clock()); - if (now - start_time >= 1000) - { - ++secs; - start_time += 1000; - kprintf("seconds = %d, ticks=%ld\n", secs, now); - } - wdt_reset(); - } -} - -int main(void) -{ - wdt_init(7); - timer_init(); - timer_test_constants(); - timer_test_delay(); - timer_test_async(); - timer_test_poll(); - return 0; -} diff --git a/drv/wdt.h b/drv/wdt.h deleted file mode 100644 index 1db10538..00000000 --- a/drv/wdt.h +++ /dev/null @@ -1,166 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Watchdog interface - */ - -#ifndef DRV_WDT_H -#define DRV_WDT_H - -#include -#include // INLINE -#include - -/* Configury sanity check */ -#if !defined(CONFIG_WATCHDOG) || (CONFIG_WATCHDOG != 0 && CONFIG_WATCHDOG != 1) - #error CONFIG_WATCHDOG must be defined to either 0 or 1 -#endif - -#if CONFIG_WATCHDOG - #include - #include - - #if OS_QT - #if _QT < 4 - #include - #else - #include - #endif - #elif OS_POSIX - #include - #elif CPU_AVR - #include - #include // BV() - #if CPU_AVR_ATMEGA1281 // Name is different in atmega1281 - #define WDTCR WDTCSR - #endif - #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) - #include /* taskYIELD() */ - #else - #error unknown CPU - #endif -#endif /* CONFIG_WATCHDOG */ - -/** - * Reset the watchdog timer. - */ -INLINE void wdt_reset(void) -{ -#if CONFIG_WATCHDOG - #if OS_QT - // Let Qt handle events - ASSERT(qApp); - qApp->processEvents(); - #elif OS_POSIX - static struct timeval tv = { 0, 0 }; - select(0, NULL, NULL, NULL, &tv); - #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) - vTaskDelay(1); - #elif CPU_AVR - __asm__ __volatile__ ("wdr"); - #else - #error unknown CPU - #endif -#endif /* CONFIG_WATCHDOG */ -} - -/** - * Set watchdog timer timeout. - * - * \param timeout 0: 16.3ms, 7: 2.1s - */ -INLINE void wdt_init(uint8_t timeout) -{ -#if CONFIG_WATCHDOG - #if OS_QT - // Create a dummy QApplication object - if (!qApp) - { - int argc; - new QApplication(argc, (char **)NULL); - } - (void)timeout; - #elif OS_POSIX - (void)timeout; // NOP - #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) - /* nop */ - #elif CPU_AVR - WDTCR |= BV(WDCE) | BV(WDE); - WDTCR = timeout; - #else - #error unknown CPU - #endif -#else - (void)timeout; -#endif /* CONFIG_WATCHDOG */ -} - -INLINE void wdt_start(void) -{ -#if CONFIG_WATCHDOG - #if OS_QT - // NOP - #elif OS_POSIX - // NOP - #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) - /* nop */ - #elif CPU_AVR - WDTCR |= BV(WDE); - #else - #error unknown CPU - #endif -#endif /* CONFIG_WATCHDOG */ -} - -INLINE void wdt_stop(void) -{ -#if CONFIG_WATCHDOG - #if OS_QT - // NOP - #elif OS_POSIX - // NOP - #elif defined(ARCH_FREERTOS) && (ARCH & ARCH_FREERTOS) - /* nop */ - #elif CPU_AVR - WDTCR |= BV(WDCE) | BV(WDE); - WDTCR &= ~BV(WDE); - #else - #error unknown CPU - #endif -#endif /* CONFIG_WATCHDOG */ -} - -#endif /* DRV_WDT_H */ diff --git a/dt/dnotifier.c b/dt/dnotifier.c deleted file mode 100644 index 502ce284..00000000 --- a/dt/dnotifier.c +++ /dev/null @@ -1,188 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Notifier obj (implementation). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.5 2005/06/09 13:49:22 batt - *#* Reformat; correct some comments. - *#* - *#* Revision 1.4 2005/06/09 13:23:58 batt - *#* Add some comments. - *#* - *#* Revision 1.3 2005/06/08 17:32:33 batt - *#* Switch to new messaging system. - *#* - *#* Revision 1.2 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#include - -#include
-#include
-#include - -/** - * Default update used to notify target: notify all trasparently all - * targets in the list. - */ -static void notifier_update(DNotifier *n, dtag_t tag, dval_t val) -{ - dnotify_targets(n, tag, val); -} - -/** - * Init. - */ -void notifier_init(DNotifier *n) -{ - // Init instance - n->update = notifier_update; - LIST_INIT(&n->targets); -} - -/** - * Search in the map a tag and a val corresponding to the ones supplied. - * If a match is found change them to the corresponding ones in the map. - * If map is NULL the filter is trasparent and all messages sent to filter - * will be forwarded to its target. - */ -void filter_update(DFilter *f, dtag_t tag, dval_t val) -{ - - const DFilterMap *map = f->map; - - if (map) - { - while (map->src.tag != TAG_END) - { - if ((map->src.tag == tag) && (map->src.val == val)) - { - tag = map->dst.tag; - val = map->dst.val; - break; - } - /* TAG_ANY matches anything */ - if (map->src.tag == TAG_ANY) - break; - map++; - } - - if (map->src.tag != TAG_END) - dnotify(f->target, tag, val); - } - else - dnotify(f->target, tag, val); -} - - -/** - * Search in the table a tag corresponding to the one supplied and a val - * that has at least the mask map supplied bits to one. - * If a match is found change them to the corresponding ones in the map. - * If map is NULL the filter is trasparent and all messages sent to filter - * will be forwarded to its target. - */ -void filter_mask_update(DFilter *f, dtag_t tag, dval_t val) -{ - - const DFilterMap *map = f->map; - dfilter_mask_t mask; - - if (map) - { - while (map->src.tag != TAG_END) - { - mask = (dfilter_mask_t) map->src.val; - if ((map->src.tag == tag) && ((mask & (dfilter_mask_t)val) == mask)) - { - tag = map->dst.tag; - val = map->dst.val; - break; - } - /* TAG_ANY matches anything */ - if (map->src.tag == TAG_ANY) - break; - map++; - } - - - if (map->src.tag != TAG_END) - dnotify(f->target, tag, val); - } - else - dnotify(f->target, tag, val); -} - - -#define FILTER_MAGIC_ACTIVE 0xAA -/** - * Init filter. - * If \a masked is true, all the fields value in \a map must be interpreted as a mask of bits. - */ -void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target) -{ - // Init instance - if (masked) - f->update = (update_filter_ptr)filter_mask_update; - else - f->update = (update_filter_ptr)filter_update; - - /* set filter map and target */ - f->map = map; - f->target = target; - - /* these ensure that the filter is not inserted in more than one list */ - ASSERT(f->magic != FILTER_MAGIC_ACTIVE); - DB(f->magic = FILTER_MAGIC_ACTIVE;) - - /* Add the filter to source filter list */ - ADDTAIL(&source->targets, &f->link); -} diff --git a/dt/dnotifier.h b/dt/dnotifier.h deleted file mode 100644 index 118a2f4c..00000000 --- a/dt/dnotifier.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Notifier obj (interface). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.4 2005/06/09 13:23:58 batt - *#* Add some comments. - *#* - *#* Revision 1.3 2005/06/08 17:32:33 batt - *#* Switch to new messaging system. - *#* - *#* Revision 1.2 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ -#ifndef DT_DNOTIFIER_H -#define DT_DNOTIFIER_H - -#include -#include
-#include - -//Fwd declaretion. -struct DNotifier; -struct DFilter; - -typedef void (* update_func_ptr)(struct DNotifier *, dtag_t, dval_t); -typedef void (* update_filter_ptr)(struct DFilter *, dtag_t, dval_t); - -/** - * Base object for receive and forward messages. - * It contains an update function used to update itslef and a list to - * notify other DNotifer eventually connected. - */ -typedef struct DNotifier -{ - /// Receive new attributes from other notifiers. - update_func_ptr update; - - /// List of target notifiers to set new attributes to. - List targets; -} DNotifier; - -/** - * Map for messages. - * Used to translate src message to dst message. - */ -typedef struct DFilterMap -{ - DTagItem src; - DTagItem dst; -} DFilterMap; - - -/** - * A filter is an interface between two notifier. - * It can translate messages between them through a map (if it is not null). - */ -typedef struct DFilter -{ - /// Allow creating a list of dfilter objects. - Node link; - - /// Target of the filter - DNotifier *target; - - /// Update function called by the source dnotifier - update_filter_ptr update; - - ///Map for translating messages for target - const DFilterMap *map; - - ///Used in debug to prevent inserting this filter in more than one list - DB(uint8_t magic;) -} DFilter; - -/// Type for filter-mask checking -typedef uint16_t dfilter_mask_t; - -/// Filter init -void filter_init(DFilter *f, const DFilterMap *map, bool masked, DNotifier *source, DNotifier *target); - -/// Filter update function without masking capabilities. -void filter_update(DFilter *f, dtag_t tag, dval_t val); - -/// Filter update function with masking capabilities. -void filter_mask_update(DFilter *f, dtag_t tag, dval_t val); - -/// Notifier init -void notifier_init(DNotifier *n); - - -/** - * Macro to notify the target object. - */ -INLINE void dnotify(DNotifier *target, dtag_t tag, dval_t val) -{ - if (target) - target->update(target, tag, val); -} - -/** - * Macro to notify all the targets of \a target object. - */ -INLINE void dnotify_targets(DNotifier *target, dtag_t tag, dval_t val) -{ - DFilter *f; - if (!ISLISTEMPTY(&target->targets)) - FOREACHNODE(f, &target->targets) - f->update(f, tag, val); -} - - -/** - * Macro that connect \a src notifier to \a tgt using \a map and passing \a opt for filtering option. - * It declares a static filter to achieve connection and messages translation. - * \note Due its static filter declaration, DCONNECT MUST NOT be used inside loops or in functions called multiple times. - * Failing to do so will lead to unpredictable connections between notifiers. - */ -#define DCONNECT(src, tgt, map, opt) \ - do { \ - static DFilter _filter_; /* Declare a filter */ \ - filter_init(&(_filter_), map, opt, src, tgt); /* Init it. */ \ - } while (0) - - -#endif /* DT_DNOTIFIER_H */ diff --git a/dt/dtag.h b/dt/dtag.h deleted file mode 100644 index 5ecbfa75..00000000 --- a/dt/dtag.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Tags interface. - * This module contains the base message definitions and the list of all available tags. - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.8 2005/06/07 15:22:29 batt - *#* Add const_dval_t. - *#* - *#* Revision 1.7 2005/06/06 17:42:23 batt - *#* Add error tag TAG_ERROR. - *#* - *#* Revision 1.6 2005/06/06 12:45:33 batt - *#* Add TAG_NONE tag. - *#* - *#* Revision 1.5 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.4 2005/05/31 11:09:52 batt - *#* Add some tags. - *#* - *#* Revision 1.3 2005/05/26 14:55:12 batt - *#* Add form_processTime; change form_kbdProcess to form_processKey. - *#* - *#* Revision 1.2 2005/05/26 14:43:33 batt - *#* Add new message filter interface. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#ifndef DT_DTAG_H -#define DT_DTAG_H - -#include - -/** Type for values associated with tags. */ -typedef iptr_t dval_t; - -/** Type for constant values associated with tags. */ -typedef const_iptr_t const_dval_t; - -/** Type for tag */ -typedef enum dtag_t -{ - TAG_END = 0, - TAG_NONE, - TAG_ANY, - TAG_SETVALUE, - TAG_UP, - TAG_DOWN, - TAG_START, - TAG_STOP, - TAG_TOGGLE, - TAG_KEY, - TAG_TIME, - TAG_ERROR, -} dtag_t; - -/** This is the basic message structure used by all dnotifiers. */ -typedef struct DTagItem -{ - dtag_t tag; - dval_t val; -} DTagItem; - -/** Marker to indicate the end of a map for message filtering/translating */ -#define TAG_END_MARKER {{TAG_END, 0}, {TAG_END, 0}} -#endif diff --git a/dt/dwidget.c b/dt/dwidget.c deleted file mode 100644 index 096f84d2..00000000 --- a/dt/dwidget.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Widget (implementation). - * A widget is typically a graphic object on a device. - * Its proproperties are the position, the size and a context on which the widget is drawn. - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.3 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.2 2005/05/26 14:44:10 batt - *#* Abstract widget from layer: use context. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#include
-#include
- -/** - * Init the widget of \a pos and \a size on the drawing \a context. - */ -void widget_init(DWidget *w, dpos_t pos, dpos_t size, dcontext_t *context) -{ - // Init superclass - notifier_init(&w->notifier); - - // Init instance - w->pos = pos; - w->size = size; - w->context = context; -} diff --git a/dt/dwidget.h b/dt/dwidget.h deleted file mode 100644 index 8c240dd4..00000000 --- a/dt/dwidget.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Widget (interface). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.3 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.2 2005/05/26 14:44:10 batt - *#* Abstract widget from layer: use context. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#ifndef DT_DWIDGET_H -#define DT_DWIDGET_H - -#include
-#include - -/** Widget position. */ -typedef uint8_t dpos_t; - -/** Widget drawing context. */ -typedef iptr_t dcontext_t; - -/** Widget definition. */ -typedef struct DWidget -{ - DNotifier notifier; - - dpos_t pos; - dpos_t size; - dcontext_t *context; -} DWidget; - - -void widget_init(DWidget *w, dpos_t pos, dpos_t size, dcontext_t *context); - -#endif diff --git a/dt/editbool.c b/dt/editbool.c deleted file mode 100644 index 55e94480..00000000 --- a/dt/editbool.c +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Edit bool widget (implementation). - * This widget handles boolean editing. - * The boolean value will be displayed using two strings: - * one when the bool is false and one when it's true. - * - * \version $Id$ - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.3 2005/06/08 17:32:33 batt - *#* Switch to new messaging system. - *#* - *#* Revision 1.2 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.1 2005/05/31 11:11:37 batt - *#* Edit bool: first release. - *#* - *#*/ - -#include -#include
- -#include - -/** - * Init widget. - */ -void editbool_init(DEditBool *e, dpos_t pos, dpos_t size, dcontext_t *context, bool *value, const char *true_string, const char *false_string) -{ - // Initialize superclass - widget_init(&e->widget, pos, size, context); - - // Override superclass methods - e->widget.notifier.update = (update_func_ptr)editbool_update; - - // Init instance - e->value = value; - e->true_string = true_string; - e->false_string = false_string; - e->draw = editbool_draw; -} - -/** - * Handle the messages (edit the bool). - */ -void editbool_update(DEditBool *e, dtag_t tag, dval_t _val) -{ - bool changed = false; - - switch (tag) - { - case TAG_SETVALUE: - *e->value = (bool)_val; - changed = true; - break; - - case TAG_TOGGLE: - *e->value = !*e->value; - changed = true; - break; - default: - break; - } - - if (changed) - { - e->draw(e); - dnotify_targets(&e->widget.notifier, TAG_SETVALUE, (dval_t)*e->value); - } -} - -/** - * Draw the string on the context. - */ -void editbool_draw(DEditBool *e) -{ - lcd_printf((Layer *)e->widget.context, (lcdpos_t)e->widget.pos, LCD_NORMAL, "%*s", (int)e->widget.size , *e->value? e->true_string: e->false_string); -} diff --git a/dt/editbool.h b/dt/editbool.h deleted file mode 100644 index 360484a5..00000000 --- a/dt/editbool.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Edit bool widget (interface). - * - * \version $Id$ - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.2 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.1 2005/05/31 11:11:37 batt - *#* Edit bool: first release. - *#* - *#*/ - -#ifndef DT_EDITBOOL_H -#define DT_EDITBOOL_H - -#include
-#include
- -typedef struct DEditBool -{ - DWidget widget; - bool *value; - const char *true_string; - const char *false_string; - void (*draw)(struct DEditBool *); -} DEditBool; - -void editbool_init(DEditBool *e, dpos_t pos, dpos_t size, dcontext_t *context, bool *val, const char *true_str, const char *false_str); -void editbool_update(DEditBool *e, dtag_t tag, dval_t val); -void editbool_draw(DEditBool *e); - - -#endif diff --git a/dt/editint.c b/dt/editint.c deleted file mode 100644 index 8ddcb7ed..00000000 --- a/dt/editint.c +++ /dev/null @@ -1,159 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Integer edit widget (implementation). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.7 2005/06/10 15:46:09 batt - *#* Add EDIS_WRAP style that wrap around min and max. - *#* - *#* Revision 1.6 2005/06/08 17:32:33 batt - *#* Switch to new messaging system. - *#* - *#* Revision 1.5 2005/06/06 11:04:12 batt - *#* Add some comments. - *#* - *#* Revision 1.4 2005/05/31 11:09:34 batt - *#* Fix sending pointer instead of value bug. - *#* - *#* Revision 1.3 2005/05/26 14:46:20 batt - *#* Use correct tag; remove warning. - *#* - *#* Revision 1.2 2005/05/26 14:44:10 batt - *#* Abstract widget from layer: use context. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#include -#include
-#include
-#include
- -#include - -#include - -/** - * Init. - */ -void editint_init(DEditInt *e, dpos_t pos, dpos_t size, dcontext_t *context, int *value, int min, int max) -{ - // Initialize superclass - widget_init(&e->widget, pos, size, context); - - // Override superclass methods - e->widget.notifier.update = (update_func_ptr)editint_update; - - // Init instance - e->value = value; - e->min = min; - e->max = max; - e->style = EDIS_DEFAULT; - e->draw = editint_draw; -} - -/** - * Handle the messages (edit the int). - */ -void editint_update(DEditInt *e, dtag_t tag, dval_t _val) -{ - bool changed = false; - int val = (int)_val; - - switch (tag) - { - case TAG_SETVALUE: - *e->value = MINMAX(e->min, val, e->max); - changed = true; - break; - - /* Increments the integer by val */ - case TAG_UP: - if (e->style & EDIS_WRAP) - { - if (*e->value + val > e->max) - *e->value = (*e->value + val - e->min) % (e->max - e->min + 1) + e->min; - else - *e->value += val; - } - else - *e->value = MIN(*e->value + val, e->max); - changed = true; - break; - /* Decrements the integer by val */ - case TAG_DOWN: - if (e->style & EDIS_WRAP) - { - if (*e->value - val < e->min) - *e->value = e->max - (e->max - (*e->value - val)) % (e->max - e->min + 1); - else - *e->value -= val; - } - else - *e->value = MAX(*e->value - val, e->min); - changed = true; - break; - - default: - break; - } - - if (changed) - { - e->draw(e); - dnotify_targets(&e->widget.notifier, TAG_SETVALUE, (dval_t)*e->value); - } -} - -/** - * Draw the integer on the context. - */ -void editint_draw(DEditInt *e) -{ - lcd_printf((Layer *)e->widget.context, (lcdpos_t)e->widget.pos, LCD_NORMAL,"%*d", (int)e->widget.size, *e->value); -} diff --git a/dt/editint.h b/dt/editint.h deleted file mode 100644 index 1b707696..00000000 --- a/dt/editint.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Integer edit (interface). - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/11/04 18:26:38 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.3 2005/06/10 15:46:09 batt - *#* Add EDIS_WRAP style that wrap around min and max. - *#* - *#* Revision 1.2 2005/05/26 14:44:10 batt - *#* Abstract widget from layer: use context. - *#* - *#* Revision 1.1 2005/05/26 08:32:53 batt - *#* Add new Develer widget system :) - *#* - *#*/ - -#ifndef DT_EDITINT_H -#define DT_EDITINT_H - -#include
-#include
-#include - -#include -#include - - -#define EDIS_DEFAULT 0 -#define EDIS_CURSORLEFT BV(0) -#define EDIS_WRAP BV(1) - -/** Type for edit style */ -typedef uint16_t dstyle_t; - -typedef struct DEditInt -{ - DWidget widget; - - int *value; - int min; - int max; - dstyle_t style; - void (*draw)(struct DEditInt *); - -} DEditInt; - -void editint_init(DEditInt *e, dpos_t pos, dpos_t size, dcontext_t *context, int *value, int min, int max); -void editint_update(DEditInt *e, dtag_t tag, dval_t val); -void editint_draw(DEditInt *e); - -#endif diff --git a/emul/emul.cpp b/emul/emul.cpp deleted file mode 100644 index ad081db1..00000000 --- a/emul/emul.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Qt-based emulator framework for embedded applications (implementation) - */ - -/*#* - *#* $Log$ - *#* Revision 1.6 2006/05/28 12:17:57 bernie - *#* Drop almost all the Qt3 cruft. - *#* - *#* Revision 1.5 2006/05/27 22:30:56 bernie - *#* Add some delay to slow things down. - *#* - *#* Revision 1.4 2006/02/24 01:35:40 bernie - *#* Update for new emulator. - *#* - *#* Revision 1.3 2006/02/20 02:00:40 bernie - *#* Port to Qt 4.1. - *#* - *#* Revision 1.2 2006/01/16 03:51:51 bernie - *#* Fix boilerplate. - *#* - *#* Revision 1.1 2006/01/16 03:37:12 bernie - *#* Add emulator skeleton. - *#* - *#*/ - -#include "emul.h" -#include "emulwin.h" -#include - -#include -#if CONFIG_KERNEL - #include -#endif - - -#include // std::exit() - -#include - - -/// The global emulator instance. -Emulator *emul; - -#if CONFIG_KERNEL - #include - - /// List of process stacks - List StackFreeList; - - // HACK: Reserve 64KB of stack space for kernel processes - const int NPROC = 8; - int stacks[NPROC][(64 * 1024) / sizeof(int)]; -#endif - -Emulator::Emulator(int &argc, char **argv) : - emulApp(new QApplication(argc, argv)), - emulWin(new EmulWin(this)) -{ - emulWin->show(); -} - - -Emulator::~Emulator() -{ - // we don't delete emulWin because it automatically - // deletes itself when closed - delete emulApp; -} - - -NORETURN void Emulator::quit() -{ - // WHAT A KLUDGE! - this->~Emulator(); - emul = NULL; - - // do we have a better way to shut down the emulation? - exit(0); -} - -MOD_DEFINE(emul) - -/// Main emulator entry point. -extern "C" void emul_init(int *argc, char *argv[]) -{ - // setup global emulator pointer - emul = new Emulator(*argc, argv); - -#if CONFIG_KERNEL - LIST_INIT(&StackFreeList); - for (int i = 0; i < NPROC; i++) - ADDTAIL(&StackFreeList, (Node *)stacks[i]); -#endif - - MOD_INIT(emul); -} - -extern "C" void emul_cleanup() -{ - MOD_CLEANUP(emul); - - delete emul; - emul = NULL; -} - -extern "C" void emul_idle() -{ - // We process GUI events when the application is idle. - emul->emulApp->processEvents(); - usleep(1000); -} - diff --git a/emul/emul.h b/emul/emul.h deleted file mode 100644 index 80d3ecc2..00000000 --- a/emul/emul.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Qt-based emulator framework for embedded applications (interface) - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/02/15 09:11:17 bernie - *#* Add keyboard emulator. - *#* - *#* Revision 1.3 2006/01/23 23:12:08 bernie - *#* Let Doxygen see through C++ protected section. - *#* - *#* Revision 1.2 2006/01/16 03:51:51 bernie - *#* Fix boilerplate. - *#* - *#* Revision 1.1 2006/01/16 03:37:12 bernie - *#* Add emulator skeleton. - *#* - *#*/ - -#ifndef EMUL_EMUL_H -#define EMUL_EMUL_H - -#include - -#if defined(__cplusplus) || defined(__doxygen__) - -// fwd decls -class QApplication; -class EmulWin; -class EmulPRT; -class EmulLCD; -class EmulKbd; -class QCheckBox; -class QSlider; -class QLabel; - -class Emulator -{ -// data members -public: - QApplication *emulApp; ///< QT Application. - EmulWin *emulWin; ///< Main window. - - EmulLCD *emulLCD; ///< Display emulator. - EmulKbd *emulKbd; ///< Keyboard emulator. - -// construction - Emulator(int &argc, char **argv); - ~Emulator(); - -// public methods - void quit(); -}; - -extern Emulator *emul; - -#endif /* __cplusplus */ - -EXTERN_C void emul_init(int *argc, char *argv[]); -EXTERN_C void emul_cleanup(); -EXTERN_C void emul_idle(); - -#endif /* EMUL_EMUL_H */ - diff --git a/emul/emul.mk b/emul/emul.mk deleted file mode 100644 index b7ddf358..00000000 --- a/emul/emul.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright 2007 Bernardo Innocenti (http://www.codewiz.org/) -# All rights reserved. -# -# Author: Bernardo Innocenti -# -# Qt configuration for devlib emulator demo. Include it from -# your app Makefile fragment - -EMUL_CFLAGS = $(shell pkg-config QtCore QtGui --cflags) -DQT_CLEAN_NAMESPACE -DQT3_SUPPORT -EMUL_LDFLAGS = $(shell pkg-config QtCore QtGui --libs) -QT_MOC = $(shell pkg-config QtCore --variable=moc_location) -#QT_UIC = $(shell pkg-config QtCore --variable=uic_location) diff --git a/emul/emulkbd.cpp b/emul/emulkbd.cpp deleted file mode 100644 index 19c6d880..00000000 --- a/emul/emulkbd.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief QT-based widget for keyboard emulation (implementation) - */ - -#include "emulkbd.h" -#include "emul.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -EmulKey::EmulKey(EmulKbd *kbd, const char *label, int _keycode, int _row, int _col) : - QPushButton(label, kbd), - row(_row), col(_col), - keycode(_keycode) -{ - // don't let the widget get focus - setFocusPolicy(Qt::NoFocus); - - // unused - connect(this, SIGNAL(pressed()), this, SLOT(keyPressed())); - connect(this, SIGNAL(released()), this, SLOT(keyReleased())); -} - - -EmulKey::~EmulKey() -{ - // nop -} - - -/** - * Override standad QButton behaviour: we must also emit the signals. - */ -// unused -void EmulKey::setDown(bool enable) -{ - // let our superclass do everything else - QPushButton::setDown(enable); - - if (enable) - emit pressed(); - else - emit released(); -} - - -// unused -void EmulKey::keyPressed(void) -{ - static_cast(parent())->setKey(row, col, true); -} - - -// unused -void EmulKey::keyReleased(void) -{ - static_cast(parent())->setKey(row, col, false); -} - - -EmulKbd::EmulKbd(QWidget *parent, Qt::WFlags f) : - QFrame(parent, f), - layout(new QGridLayout(this)), - active_row(0) -{ - setFrameStyle(QFrame::Box | QFrame::Sunken); - setLineWidth(1); - setFocusPolicy(Qt::StrongFocus); - frame_width = frameWidth(); -} - - -EmulKbd::~EmulKbd() -{ - delete layout; -} - - -QSizePolicy EmulKbd::sizePolicy() const -{ - return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); -} - - -void EmulKbd::resizeEvent(QResizeEvent *event) -{ - // Let our superclass process the event first - QFrame::resizeEvent(event); -} - - -// handle key presses for all keys in keyboard -bool EmulKbd::event(QEvent *_e) -{ - switch (_e->type()) - { - case QEvent::KeyPress: - case QEvent::KeyRelease: - { - QKeyEvent *e = static_cast(_e); - int keycode = e->key(); - EmulKey *key; - - // ignore repeated keys - if (!e->isAutoRepeat()) - { - // scan all children - for (QObjectList::const_iterator it(children().begin()); it != children().end(); ++it) - { - // only keys, not other children! - if ((*it)->metaObject() == &EmulKey::staticMetaObject) - // if ((key = dynamic_cast(*it))) - { - key = static_cast(*it); - - // same key? - if (key->keycode == keycode) - { - // yes, tell key to go down (or up) - key->setDown(_e->type() == QEvent::KeyPress); - break; - } - } - } - } - return true; - } - - default: - // let superclass process this event - return QFrame::event(_e); - - } // end switch(_e->type()) -} - - -void EmulKbd::addKey(const char *label, int keycode, int row, int col, int matrix_row, int matrix_col) -{ - if (matrix_row == -1) - matrix_row = row; - if (matrix_col == -1) - matrix_col = col; - - layout->addWidget(new EmulKey(this, label, keycode, matrix_row, matrix_col), row, col); -} - - -// unused -void EmulKbd::setKey(int /*row*/, int /*col*/, bool /*on*/) -{ -} - - -void EmulKbd::setRow(int r) -{ - active_row = r; -} - -int EmulKbd::readCols(void) -{ - QLayoutItem *item; - EmulKey *key; - int cols = 0; - - // FIXME: QLayoutIterator is obsolete in Qt4 - for(QLayoutIterator it(layout->iterator()); (item = it.current()); ++it) - { - key = static_cast(item->widget()); - if (key->row == active_row) - { - if (key->isDown()) - cols |= (1<col); - } - } - return cols; -} - -extern "C" void emul_kbdSetRows(int r) -{ - emul->emulKbd->setRow(r); -} - - -extern "C" int emul_kbdReadCols(void) -{ - return emul->emulKbd->readCols(); -} - -#include "emulkbd_moc.cpp" diff --git a/emul/emulkbd.h b/emul/emulkbd.h deleted file mode 100644 index 82048367..00000000 --- a/emul/emulkbd.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief QT-based widget for leyboard emulation (interface) - */ - -#if !defined(EMULKBD_H) -#define EMULKBD_H - -#if defined (_MSC_VER) && (_MSC_VER > 1000) -#pragma once -#endif // _MSC_VER > 1000 - -#include - -// fwd decl -class QGridLayout; -class EmulKey; - -class EmulKbd : public QFrame -{ - Q_OBJECT - -// Data members -protected: - QGridLayout *layout; - int frame_width; - int active_row; - -// Construction -public: - EmulKbd(QWidget *parent = 0, Qt::WFlags f = 0); - virtual ~EmulKbd(); - -// Public methods - void addKey(const char *label, int keycode, int row, int col, int matrix_row = -1, int matrix_col = -1); - void setRow(int row); - int readCols(void); - -// Protected methods -protected: - void setKey(int row, int col, bool on); - -// Base class overrides -protected: - virtual QSizePolicy sizePolicy() const; - virtual void resizeEvent(QResizeEvent *e); - virtual bool event(QEvent *e); - -// Friends - friend class EmulKey; -}; - - -// Private helper class for EmulKbd -// NOTE: with protected inheritance, dynamic_cast<> does not work (gcc 2.96) -#include -class EmulKey : public QPushButton -{ - Q_OBJECT - -// Data members -protected: - int row, col; - int keycode; - -// Construction -public: - EmulKey(EmulKbd *parent, const char *label, int keycode, int _row, int _col); - virtual ~EmulKey(); - -// superclass overrides - void setDown(bool enable); - -protected slots: - void keyPressed(void); - void keyReleased(void); - -// Friends -public: - friend class EmulKbd; -}; - -#endif // !defined(EMULKBD_H) - diff --git a/emul/emulwin.cpp b/emul/emulwin.cpp deleted file mode 100644 index b5f57cd4..00000000 --- a/emul/emulwin.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Main Qt window for embedded applications emulator (implementation) - */ - -#include "emulwin.h" - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace Qt; - -EmulWin::EmulWin(Emulator *e) -{ - setWindowTitle(tr("BeRTOS Emul Demo")); - setAttribute(Qt::WA_DeleteOnClose); - - // Create the menu bar - QMenu *file_menu = menuBar()->addMenu(tr("&File")); - file_menu->addAction(tr("&Quit"), - e->emulApp, SLOT(closeAllWindows()), CTRL+Key_Q); - - menuBar()->addSeparator(); - - QMenu *help_menu = menuBar()->addMenu(tr("&Help")); - help_menu->addAction(tr("&About"), - this, SLOT(about()), Key_F1); - - // Make a central widget to contain the other widgets - QWidget *central = new QWidget(this); - setCentralWidget(central); - - // Create a layout to position the widgets - QHBoxLayout *box_main = new QHBoxLayout(central); - - // Main layout - QVBoxLayout *box_right = new QVBoxLayout(); - box_main->addLayout(box_right); - - // LCD - QHBoxLayout *lay_lcd = new QHBoxLayout(); - box_right->addLayout(lay_lcd); - lay_lcd->addStretch(); - lay_lcd->addWidget(e->emulLCD = new EmulLCD(central)); - lay_lcd->addStretch(); - - // Keyboard - box_right->addWidget(e->emulKbd = new EmulKbd(central)); - - // Setup keyboard: Label Keycode Row Col MRow MCol - e->emulKbd->addKey("^", Key_Up, 0, 0, 0, 0); - e->emulKbd->addKey("v", Key_Down, 1, 0, 0, 1); - e->emulKbd->addKey("OK", Key_Return, 0, 1, 0, 2); - e->emulKbd->addKey("ESC", Key_Escape, 1, 1, 0, 3); -} - - -EmulWin::~EmulWin() -{ - emul->quit(); -} - - -void EmulWin::closeEvent(QCloseEvent *ce) -{ - emul->quit(); - ce->accept(); -} - - -void EmulWin::about() -{ - QMessageBox::about(this, - "BeRTOS Embedded Application Emulator", - "Version 0.1\n" - "Copyright 2006, 2008 Develer S.r.l. (http://www.develer.com/)\n" - "Copyright 2001, 2002, 2003, 2005 Bernardo Innocenti \n" - "All rights reserved." - ); -} - -#include "emulwin_moc.cpp" diff --git a/emul/emulwin.h b/emul/emulwin.h deleted file mode 100644 index 8ce6c8bf..00000000 --- a/emul/emulwin.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Main Qt window for embedded applications emulator (interface) - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/05/28 12:17:56 bernie - *#* Drop almost all the Qt3 cruft. - *#* - *#* Revision 1.3 2006/02/20 02:00:39 bernie - *#* Port to Qt 4.1. - *#* - *#* Revision 1.2 2006/01/16 03:51:51 bernie - *#* Fix boilerplate. - *#* - *#* Revision 1.1 2006/01/16 03:37:12 bernie - *#* Add emulator skeleton. - *#* - *#*/ - -#ifndef EMUL_EMULWIN_H -#define EMUL_EMULWIN_H - -#include - -// fwd decls -class Emulator; - -class EmulWin : public QMainWindow -{ - Q_OBJECT - -// construction -public: - EmulWin(Emulator *emul); - ~EmulWin(); - -protected: - void closeEvent(QCloseEvent *); - -private slots: - void about(); -}; - -#endif // EMUL_EMULWIN_H - diff --git a/fonts/convbdf b/fonts/convbdf deleted file mode 100755 index 61307cd8..00000000 --- a/fonts/convbdf +++ /dev/null @@ -1,209 +0,0 @@ -#! /usr/bin/perl -w -# -# Convert BDF files to nano-X font files -# modified by G Haerr from bdftobogl for 16 bit MWIMAGEBITS -# modified on 2/10/00 by K Harris to accept any size input character -# modified on 3/26/00 by G Haerr added ascent field, fixed $IMAGE_BITS -# modified on 2/15/06 by for DevLib. -# originally from BOGL - Ben's Own Graphics Library . -# - -use POSIX; - -if ($#ARGV < 0) { - print "Usage: convbdf font.bdf > font.c\n"; - exit -1; -} - -$LAST_CHAR = 0xff; -$IMAGE_BITS = 8; -$IMAGE_NIBBLES = $IMAGE_BITS/4; -$IMAGE_MASK = 0xff; -$IMAGE_VERTICAL = 1; - -$file = $ARGV[0]; - -$font = $file; -$font =~ s#.*/##; # remove path name -$font =~ s/\.bdf//; -$font =~ tr/a-zA-Z0-9_/_/cs; - -print "/* Generated by convbdf on ", substr(`date`, 0, -1), ". */\n"; -print "#include \n\n"; - -open BDF, "<$file" || die; -while () { - chop; - $pixel_size = $1 if /^PIXEL_SIZE (\d+)$/; - $font_ascent = $1 if /^FONT_ASCENT (\d+)$/; - $font_descent = $1 if /^FONT_DESCENT (\d+)$/; - $font_name = $1 if /^FONT (.*)$/; - $default_char = $1 if /^DEFAULT_CHAR (\d+)$/; - - last if /^CHARS /; -} - -print "/* Font information:\n\n"; -print " name: $font_name\n"; -print " pixel size: $pixel_size\n"; -print " ascent: $font_ascent\n"; -print " descent: $font_descent\n"; -print "*/\n\n"; - -print "/* Font character bitmap data. */\n"; -print "static const PROGMEM uint8_t font_${font}_glyphs[] = {\n"; - -$ch_height = $font_ascent + $font_descent; -$ofs = 0; -$maxwidth = 0; -$proportional = 0; -$firstchar = -1; -while () { - chop; - undef $encoding, undef $width, undef $bbx, undef $bby, undef $bbw, undef $bbh if /^STARTCHAR /; - $encoding = $1 if /^ENCODING (\d+)/; - last if defined $encoding && $encoding > $LAST_CHAR; - $width = $1 if /^DWIDTH (-?\d+)/; - ($bbw, $bbh, $bbx, $bby) = ($1, $2, $3, $4) if /^BBX (-?\d+) (-?\d+) (-?\d+) (-?\d+)/; - - if (/^BITMAP$/) { - next if !defined $encoding; - $firstchar = $encoding if $firstchar < 0; - $encoding_tab[$encoding] = $ofs; - $width -= $bbx, $bbx = 0 if $bbx < 0; - $width[$encoding] = $width; - $maxwidth != 0 and $width != $maxwidth and $proportional = 1; - $maxwidth = $width if $width > $maxwidth; - $ch_words = int (($width+$IMAGE_BITS-1)/$IMAGE_BITS); - $ch_bits = $ch_words*$IMAGE_BITS; - for (my $i = 0; $i < $ch_height; $i++) { - for (my $k = 0; $k < $ch_words; $k++) { - $bm[$i][$k] = 0; - } - } - for (my $i = 0; ; $i++) { - $_ = ; - chop; - last if /^ENDCHAR$/; - - @hexnibbles = split //,$_; - for (my $k=0; $k<$ch_words; $k++) { - $ndx = $k*$IMAGE_NIBBLES; - $padnibbles = @hexnibbles - $ndx; - # if bbx pushes bits into next word - # and no more bits from bdf file - last if $padnibbles <= 0; - $padnibbles = 0 if $padnibbles >= $IMAGE_NIBBLES; - $value = hex join '',@hexnibbles[$ndx..($ndx+$IMAGE_NIBBLES-1-$padnibbles)]; - $value = $value << ($padnibbles*$IMAGE_NIBBLES); - $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k] |= - $value >> ($bbx); - if ($bbx) { # handle overflow into next image_word - $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k+1] = - ($value << ($IMAGE_BITS - $bbx)) & $IMAGE_MASK; - } - } - } - - # GLYPH PREVIEW -### printf "\n/* Character %c (0x%02x): ", $encoding, $encoding; - printf "\n/* Character (0x%02x): ", $encoding; - print "bbw=$bbw, bbh=$bbh, bbx=$bbx, bby=$bby, width=$width */\n"; - - # GLYPH DATA - if ($IMAGE_VERTICAL) { - my $bitstring = ""; - for (my $k = 0; $k < int(($ch_height + $IMAGE_BITS - 1) / $IMAGE_BITS); $k++) { - for (my $x = 0; $x < $width; $x++) { - my $v = 0; - for (my $y = 0; $y < $IMAGE_BITS && ($y + $k * $IMAGE_BITS < $ch_height); ++$y) { - my $bit = ($bm[$k * $IMAGE_BITS + $y][int($x / $IMAGE_BITS)] & (1 << ($IMAGE_BITS - ($x % $IMAGE_BITS) - 1))) ? 1 : 0; - $bitstring .= $bit ? '*' : ' '; - $v |= $bit << $y; - } - $ofs++; - printf "0x%02x, ", $v; - } - # Preview - printf "/* $bitstring */\n"; - } - - } - else { # IMAGE_HORIZONTAL - - # Preview - print " +", ("-" x $ch_bits), "+\n"; - for (my $i = 0; $i < $ch_height; $i++) { - print " |"; - for (my $k = 0; $k < $ch_words; $k++) { - for (my $j = $IMAGE_BITS - 1; $j >= 0; $j--) { - print $bm[$i][$k] & (1 << $j) ? "*" : " "; - } - } - print "|\n"; - } - print " +", ("-" x $ch_bits), "+ */\n"; - - for (my $i = 0; $i < $ch_height; $i++) { - for (my $k=0; $k<$ch_words; $k++) { - $ofs++; - printf "0x%02x, ", $bm[$i][$k]; - } - printf "\n"; - } - } - } -} - -print "};\n\n"; - -#print STDERR "Maximum character width=$maxwidth\n"; - -if ($proportional) { - print "/* Character->glyph data. */\n"; - print "static const PROGMEM uint16_t ${font}_offset[] = {\n"; - for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) { - my $char = $i; - my $ofs = $encoding_tab[$i]; - $ofs = $encoding_tab[$default_char], $char = $default_char if !defined $ofs; - ### printf " $ofs,\t/* %c (0x%02x) */\n", $char, $i; - printf " $ofs,\t/* (0x%02x) */\n", $i; - } - print "};\n\n"; - - print "/* Character width data. */\n"; - print "static const PROGMEM uint8_t ${font}_width[] = {\n"; - for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) { - my $char = $i; - my $width = $width[$i]; - $width = $width[$default_char], $char = $default_char if !defined $encoding_tab[$i]; - ### printf " $width,\t/* %c (0x%02x) */\n", $char, $i; - printf " $width,\t/* (0x%02x) */\n", $i; - } - print "};\n\n"; - - $font_offset = "${font}_offset"; - $font_width = "${font}_width"; -} else { - $font_offset = "NULL"; - $font_width = "NULL"; -} - -$lastchar = $LAST_CHAR; -#$size = $lastchar - $firstchar + 1; - -print < - * - * --> - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Font 8x6 IBM-PC 8bit - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/05/27 22:30:22 bernie - *#* Move 6x8 font to fonts/. - *#* - *#* Revision 1.3 2006/02/10 12:29:05 bernie - *#* Add multiple font support in bitmaps. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.6 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.5 2005/01/08 09:20:38 bernie - *#* Add missing type in declaration. - *#* - *#* Revision 1.4 2004/12/31 16:42:55 bernie - *#* Sanitize for non-Harvard processors. - *#* - *#* Revision 1.3 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 15:43:16 bernie - *#* Import mware modules. - *#*/ - -#include "font.h" - -static const PROGMEM uint8_t default_font_glyphs[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, /*  */ -/* 0x80 */ - 0x38, 0xC4, 0xC4, 0x44, 0x28, 0x00, /* € */ - 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x00, /*  */ - 0x38, 0x54, 0x54, 0x55, 0x19, 0x00, /* ‚ */ - 0x22, 0x55, 0x55, 0x55, 0x78, 0x00, /* ƒ */ - 0x20, 0x55, 0x54, 0x54, 0x79, 0x00, /* „ */ - 0x21, 0x75, 0x55, 0x54, 0x78, 0x00, /* … */ - 0x20, 0x74, 0x57, 0x54, 0x78, 0x00, /* † */ - 0x08, 0x54, 0x54, 0x74, 0x14, 0x00, /* ‡ */ -/* 0x88 */ - 0x3A, 0x55, 0x55, 0x55, 0x1A, 0x00, /* ˆ */ - 0x39, 0x54, 0x54, 0x55, 0x18, 0x00, /* ‰ */ - 0x39, 0x55, 0x55, 0x54, 0x18, 0x00, /* Š */ - 0x00, 0x45, 0x7C, 0x41, 0x00, 0x00, /* ‹ */ - 0x02, 0x45, 0x7D, 0x42, 0x00, 0x00, /* Œ */ - 0x01, 0x45, 0x7D, 0x40, 0x00, 0x00, /*  */ - 0x79, 0x14, 0x12, 0x14, 0x79, 0x00, /* Ž */ - 0x70, 0x2B, 0x2B, 0x2B, 0x70, 0x00, /*  */ -/* 0x90 */ - 0x7C, 0x54, 0x55, 0x55, 0x45, 0x00, /*  */ - 0x20, 0x54, 0x38, 0x54, 0x48, 0x00, /* ‘ */ - 0x7E, 0x09, 0x7F, 0x49, 0x49, 0x00, /* ’ */ - 0x32, 0x49, 0x49, 0x49, 0x32, 0x00, /* “ */ - 0x32, 0x48, 0x48, 0x48, 0x32, 0x00, /* ” */ - 0x32, 0x4A, 0x4A, 0x48, 0x30, 0x00, /* • */ - 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x00, /* – */ - 0x3A, 0x42, 0x42, 0x20, 0x78, 0x00, /* — */ -/* 0x98 */ - 0x0D, 0x50, 0x50, 0x50, 0x3D, 0x00, /* ˜ */ - 0x19, 0x24, 0x42, 0x24, 0x19, 0x00, /* ™ */ - 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x00, /* š */ - 0x18, 0x24, 0x7E, 0x24, 0x24, 0x00, /* › */ - 0x28, 0x5E, 0x29, 0x42, 0x20, 0x00, /* œ */ - 0x09, 0x2A, 0x7C, 0x2A, 0x09, 0x00, /*  */ - 0x7F, 0x05, 0x15, 0x3D, 0x52, 0x00, /* ž */ - 0x20, 0x48, 0x3E, 0x09, 0x02, 0x00, /* Ÿ */ -/* 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 /* ÿ */ -}; - -struct Font default_font = -{ - /* .glyph = */ default_font_glyphs, - /* .width = */ 6, - /* .height = */ 8 -}; - diff --git a/fonts/fonts.mk b/fonts/fonts.mk deleted file mode 100644 index dfc1baf1..00000000 --- a/fonts/fonts.mk +++ /dev/null @@ -1,12 +0,0 @@ -# -# $Id$ -# Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/) -# All rights reserved. -# -# Makefile fragment for DevLib demo application. -# -# Author: Bernardo Innocenti -# - -%.c: %.bdf - fonts/convbdf $< > $@ diff --git a/fonts/helvB10.bdf b/fonts/helvB10.bdf deleted file mode 100644 index fe548f54..00000000 --- a/fonts/helvB10.bdf +++ /dev/null @@ -1,3305 +0,0 @@ -STARTFONT 2.1 -FONT -Adobe-Helvetica-Bold-R-Normal--10-100-75-75-P-60-ISO8859-1 -SIZE 10 75 75 -FONTBOUNDINGBOX 11 13 -1 -2 -COMMENT $XConsortium: helvB10.bdf,v 1.13 95/01/26 18:01:30 gildea Exp $ -COMMENT -COMMENT + -COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. -COMMENT Copyright 1988, 1994 Digital Equipment Corporation. -COMMENT -COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be -COMMENT registered in certain jurisdictions. -COMMENT Permission to use these trademarks is hereby granted only in -COMMENT association with the images described in this file. -COMMENT -COMMENT Permission to use, copy, modify, distribute and sell this software -COMMENT and its documentation for any purpose and without fee is hereby -COMMENT granted, provided that the above copyright notices appear in all -COMMENT copies and that both those copyright notices and this permission -COMMENT notice appear in supporting documentation, and that the names of -COMMENT Adobe Systems and Digital Equipment Corporation not be used in -COMMENT advertising or publicity pertaining to distribution of the software -COMMENT without specific, written prior permission. Adobe Systems and -COMMENT Digital Equipment Corporation make no representations about the -COMMENT suitability of this software for any purpose. It is provided "as -COMMENT is" without express or implied warranty. -COMMENT - -STARTPROPERTIES 28 -FOUNDRY "Adobe" -FAMILY_NAME "Helvetica" -WEIGHT_NAME "Bold" -SLANT "R" -SETWIDTH_NAME "Normal" -ADD_STYLE_NAME "" -PIXEL_SIZE 10 -POINT_SIZE 100 -RESOLUTION_X 75 -RESOLUTION_Y 75 -SPACING "P" -AVERAGE_WIDTH 60 -CHARSET_REGISTRY "ISO8859" -CHARSET_ENCODING "1" -CAP_HEIGHT 8 -X_HEIGHT 6 -FONT_ASCENT 10 -FONT_DESCENT 2 -FACE_NAME "Helvetica Bold" -COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." -NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " -_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" -_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" -DEFAULT_CHAR 32 -RELATIVE_SETWIDTH 50 -RELATIVE_WEIGHT 70 -CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" -FULL_NAME "Helvetica Bold" -ENDPROPERTIES -CHARS 229 -STARTCHAR space -ENCODING 32 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclam -ENCODING 33 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 2 8 1 0 -BITMAP -C0 -C0 -C0 -C0 -80 -80 -00 -C0 -ENDCHAR -STARTCHAR quotedbl -ENCODING 34 -SWIDTH 474 0 -DWIDTH 5 0 -BBX 3 3 1 5 -BITMAP -A0 -A0 -A0 -ENDCHAR -STARTCHAR numbersign -ENCODING 35 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 7 0 0 -BITMAP -50 -50 -FC -50 -F8 -A0 -A0 -ENDCHAR -STARTCHAR dollar -ENCODING 36 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 -1 -BITMAP -20 -70 -A8 -E0 -70 -38 -A8 -70 -20 -ENDCHAR -STARTCHAR percent -ENCODING 37 -SWIDTH 889 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -62 -B4 -68 -10 -10 -2C -56 -8C -ENDCHAR -STARTCHAR ampersand -ENCODING 38 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -70 -D8 -D8 -70 -DE -CC -DC -76 -ENDCHAR -STARTCHAR quoteright -ENCODING 39 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 3 0 5 -BITMAP -C0 -40 -80 -ENDCHAR -STARTCHAR parenleft -ENCODING 40 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 10 0 -2 -BITMAP -20 -60 -40 -C0 -C0 -C0 -C0 -40 -60 -20 -ENDCHAR -STARTCHAR parenright -ENCODING 41 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 10 0 -2 -BITMAP -80 -C0 -40 -60 -60 -60 -60 -40 -C0 -80 -ENDCHAR -STARTCHAR asterisk -ENCODING 42 -SWIDTH 389 0 -DWIDTH 4 0 -BBX 3 3 0 5 -BITMAP -A0 -40 -A0 -ENDCHAR -STARTCHAR plus -ENCODING 43 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 6 5 0 1 -BITMAP -30 -30 -FC -30 -30 -ENDCHAR -STARTCHAR comma -ENCODING 44 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 4 0 -2 -BITMAP -40 -40 -40 -80 -ENDCHAR -STARTCHAR minus -ENCODING 45 -SWIDTH 584 0 -DWIDTH 7 0 -BBX 5 1 1 3 -BITMAP -F8 -ENDCHAR -STARTCHAR period -ENCODING 46 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 1 2 1 0 -BITMAP -80 -80 -ENDCHAR -STARTCHAR slash -ENCODING 47 -SWIDTH 278 0 -DWIDTH 4 0 -BBX 4 8 0 0 -BITMAP -10 -10 -20 -20 -40 -40 -80 -80 -ENDCHAR -STARTCHAR zero -ENCODING 48 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -D8 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR one -ENCODING 49 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 4 8 0 0 -BITMAP -30 -F0 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR two -ENCODING 50 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -18 -18 -30 -60 -C0 -F8 -ENDCHAR -STARTCHAR three -ENCODING 51 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -18 -30 -18 -18 -D8 -70 -ENDCHAR -STARTCHAR four -ENCODING 52 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 8 0 0 -BITMAP -18 -38 -58 -58 -98 -FC -18 -18 -ENDCHAR -STARTCHAR five -ENCODING 53 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -F8 -C0 -C0 -F0 -18 -98 -D8 -70 -ENDCHAR -STARTCHAR six -ENCODING 54 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -C0 -F0 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR seven -ENCODING 55 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -F8 -18 -18 -30 -30 -30 -60 -60 -ENDCHAR -STARTCHAR eight -ENCODING 56 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -D8 -70 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR nine -ENCODING 57 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -D8 -D8 -78 -18 -D8 -70 -ENDCHAR -STARTCHAR colon -ENCODING 58 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 1 6 1 0 -BITMAP -80 -80 -00 -00 -80 -80 -ENDCHAR -STARTCHAR semicolon -ENCODING 59 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 8 0 -2 -BITMAP -40 -40 -00 -00 -40 -40 -40 -80 -ENDCHAR -STARTCHAR less -ENCODING 60 -SWIDTH 584 0 -DWIDTH 5 0 -BBX 4 5 0 1 -BITMAP -30 -60 -C0 -60 -30 -ENDCHAR -STARTCHAR equal -ENCODING 61 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 5 3 0 2 -BITMAP -F8 -00 -F8 -ENDCHAR -STARTCHAR greater -ENCODING 62 -SWIDTH 584 0 -DWIDTH 5 0 -BBX 4 5 0 1 -BITMAP -C0 -60 -30 -60 -C0 -ENDCHAR -STARTCHAR question -ENCODING 63 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -D8 -18 -30 -60 -60 -00 -60 -ENDCHAR -STARTCHAR at -ENCODING 64 -SWIDTH 975 0 -DWIDTH 11 0 -BBX 10 9 0 -2 -BITMAP -1F00 -6080 -4D40 -9240 -A240 -A480 -9B00 -4000 -3E00 -ENDCHAR -STARTCHAR A -ENCODING 65 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR B -ENCODING 66 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -F8 -CC -CC -F8 -CC -CC -CC -F8 -ENDCHAR -STARTCHAR C -ENCODING 67 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -3C -66 -C2 -C0 -C0 -C2 -66 -3C -ENDCHAR -STARTCHAR D -ENCODING 68 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -F0 -D8 -CC -CC -CC -CC -D8 -F0 -ENDCHAR -STARTCHAR E -ENCODING 69 -SWIDTH 667 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -F8 -C0 -C0 -F8 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR F -ENCODING 70 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -F8 -C0 -C0 -F0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR G -ENCODING 71 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -3C -66 -C2 -C0 -CE -C6 -66 -3A -ENDCHAR -STARTCHAR H -ENCODING 72 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -CC -CC -CC -FC -CC -CC -CC -CC -ENDCHAR -STARTCHAR I -ENCODING 73 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 8 0 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR J -ENCODING 74 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -18 -18 -18 -18 -18 -18 -D8 -70 -ENDCHAR -STARTCHAR K -ENCODING 75 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 7 8 0 0 -BITMAP -CC -D8 -F0 -E0 -F0 -D8 -CC -C6 -ENDCHAR -STARTCHAR L -ENCODING 76 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR M -ENCODING 77 -SWIDTH 833 0 -DWIDTH 10 0 -BBX 9 8 0 0 -BITMAP -C180 -E380 -E380 -F780 -D580 -DD80 -C980 -C980 -ENDCHAR -STARTCHAR N -ENCODING 78 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -C6 -E6 -E6 -D6 -D6 -CE -CE -C6 -ENDCHAR -STARTCHAR O -ENCODING 79 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR P -ENCODING 80 -SWIDTH 667 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -F8 -CC -CC -CC -F8 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Q -ENCODING 81 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 9 0 -1 -BITMAP -38 -6C -C6 -C6 -C6 -D6 -6C -3C -02 -ENDCHAR -STARTCHAR R -ENCODING 82 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -F8 -CC -CC -CC -F8 -CC -CC -CC -ENDCHAR -STARTCHAR S -ENCODING 83 -SWIDTH 667 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -78 -CC -E0 -78 -1C -8C -CC -78 -ENDCHAR -STARTCHAR T -ENCODING 84 -SWIDTH 611 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -FC -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR U -ENCODING 85 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -CC -CC -CC -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR V -ENCODING 86 -SWIDTH 667 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -C6 -C6 -6C -6C -6C -38 -38 -10 -ENDCHAR -STARTCHAR W -ENCODING 87 -SWIDTH 944 0 -DWIDTH 11 0 -BBX 10 8 0 0 -BITMAP -CCC0 -CCC0 -CCC0 -6D80 -6D80 -7F80 -3300 -2100 -ENDCHAR -STARTCHAR X -ENCODING 88 -SWIDTH 667 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -C6 -C6 -6C -38 -38 -6C -C6 -C6 -ENDCHAR -STARTCHAR Y -ENCODING 89 -SWIDTH 667 0 -DWIDTH 9 0 -BBX 8 8 0 0 -BITMAP -C3 -C3 -66 -66 -3C -18 -18 -18 -ENDCHAR -STARTCHAR Z -ENCODING 90 -SWIDTH 611 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -FC -0C -18 -30 -70 -60 -C0 -FC -ENDCHAR -STARTCHAR bracketleft -ENCODING 91 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 10 0 -2 -BITMAP -E0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -E0 -ENDCHAR -STARTCHAR backslash -ENCODING 92 -SWIDTH 278 0 -DWIDTH 4 0 -BBX 4 8 0 0 -BITMAP -80 -80 -40 -40 -20 -20 -10 -10 -ENDCHAR -STARTCHAR bracketright -ENCODING 93 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 10 0 -2 -BITMAP -E0 -60 -60 -60 -60 -60 -60 -60 -60 -E0 -ENDCHAR -STARTCHAR asciicircum -ENCODING 94 -SWIDTH 584 0 -DWIDTH 5 0 -BBX 5 4 0 4 -BITMAP -20 -70 -D8 -88 -ENDCHAR -STARTCHAR underscore -ENCODING 95 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 1 0 -2 -BITMAP -FC -ENDCHAR -STARTCHAR quoteleft -ENCODING 96 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 3 0 5 -BITMAP -40 -80 -C0 -ENDCHAR -STARTCHAR a -ENCODING 97 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 6 0 0 -BITMAP -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR b -ENCODING 98 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -C0 -C0 -F0 -D8 -C8 -C8 -D8 -F0 -ENDCHAR -STARTCHAR c -ENCODING 99 -SWIDTH 556 0 -DWIDTH 5 0 -BBX 4 6 0 0 -BITMAP -70 -D0 -C0 -C0 -D0 -70 -ENDCHAR -STARTCHAR d -ENCODING 100 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -18 -18 -78 -D8 -98 -98 -D8 -78 -ENDCHAR -STARTCHAR e -ENCODING 101 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -70 -D8 -F8 -C0 -D8 -70 -ENDCHAR -STARTCHAR f -ENCODING 102 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 4 8 0 0 -BITMAP -70 -C0 -E0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR g -ENCODING 103 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -68 -D8 -98 -98 -D8 -78 -18 -70 -ENDCHAR -STARTCHAR h -ENCODING 104 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -C0 -C0 -F0 -D8 -D8 -D8 -D8 -D8 -ENDCHAR -STARTCHAR i -ENCODING 105 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 8 0 0 -BITMAP -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR j -ENCODING 106 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 10 0 -2 -BITMAP -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -80 -ENDCHAR -STARTCHAR k -ENCODING 107 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 8 0 0 -BITMAP -C0 -C0 -D8 -F0 -E0 -F0 -D8 -CC -ENDCHAR -STARTCHAR l -ENCODING 108 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 8 0 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR m -ENCODING 109 -SWIDTH 889 0 -DWIDTH 9 0 -BBX 8 6 0 0 -BITMAP -B6 -DB -DB -DB -DB -DB -ENDCHAR -STARTCHAR n -ENCODING 110 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -B0 -D8 -D8 -D8 -D8 -D8 -ENDCHAR -STARTCHAR o -ENCODING 111 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR p -ENCODING 112 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -B0 -D8 -C8 -C8 -D8 -F0 -C0 -C0 -ENDCHAR -STARTCHAR q -ENCODING 113 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -68 -D8 -98 -98 -D8 -78 -18 -18 -ENDCHAR -STARTCHAR r -ENCODING 114 -SWIDTH 389 0 -DWIDTH 4 0 -BBX 4 6 0 0 -BITMAP -B0 -E0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR s -ENCODING 115 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -70 -D8 -70 -18 -D8 -70 -ENDCHAR -STARTCHAR t -ENCODING 116 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 8 0 0 -BITMAP -C0 -C0 -E0 -C0 -C0 -C0 -C0 -60 -ENDCHAR -STARTCHAR u -ENCODING 117 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -D8 -D8 -D8 -D8 -D8 -68 -ENDCHAR -STARTCHAR v -ENCODING 118 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -D8 -D8 -D8 -50 -70 -20 -ENDCHAR -STARTCHAR w -ENCODING 119 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 6 0 0 -BITMAP -D6 -D6 -D6 -6C -6C -6C -ENDCHAR -STARTCHAR x -ENCODING 120 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 6 0 0 -BITMAP -CC -78 -30 -78 -CC -CC -ENDCHAR -STARTCHAR y -ENCODING 121 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -D8 -D8 -D8 -D8 -78 -30 -30 -60 -ENDCHAR -STARTCHAR z -ENCODING 122 -SWIDTH 500 0 -DWIDTH 6 0 -BBX 5 6 0 0 -BITMAP -F8 -18 -30 -60 -C0 -F8 -ENDCHAR -STARTCHAR braceleft -ENCODING 123 -SWIDTH 389 0 -DWIDTH 5 0 -BBX 4 10 0 -2 -BITMAP -30 -60 -60 -60 -C0 -60 -60 -60 -60 -30 -ENDCHAR -STARTCHAR bar -ENCODING 124 -SWIDTH 280 0 -DWIDTH 3 0 -BBX 1 10 1 -2 -BITMAP -80 -80 -80 -80 -80 -80 -80 -80 -80 -80 -ENDCHAR -STARTCHAR braceright -ENCODING 125 -SWIDTH 389 0 -DWIDTH 5 0 -BBX 4 10 0 -2 -BITMAP -C0 -60 -60 -60 -30 -60 -60 -60 -60 -C0 -ENDCHAR -STARTCHAR asciitilde -ENCODING 126 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 6 2 0 2 -BITMAP -6C -D8 -ENDCHAR -STARTCHAR space -ENCODING 160 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclamdown -ENCODING 161 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 2 8 1 -2 -BITMAP -C0 -00 -40 -40 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR cent -ENCODING 162 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 -1 -BITMAP -10 -70 -D8 -A0 -A0 -D8 -70 -40 -ENDCHAR -STARTCHAR sterling -ENCODING 163 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -38 -68 -60 -F0 -60 -60 -68 -D8 -ENDCHAR -STARTCHAR currency -ENCODING 164 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 6 0 1 -BITMAP -D8 -70 -D8 -D8 -70 -D8 -ENDCHAR -STARTCHAR yen -ENCODING 165 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -84 -CC -48 -78 -FC -30 -FC -30 -ENDCHAR -STARTCHAR brokenbar -ENCODING 166 -SWIDTH 280 0 -DWIDTH 3 0 -BBX 1 10 1 -2 -BITMAP -80 -80 -80 -80 -00 -00 -80 -80 -80 -80 -ENDCHAR -STARTCHAR section -ENCODING 167 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 10 0 -2 -BITMAP -70 -C8 -E0 -70 -98 -C8 -70 -38 -98 -70 -ENDCHAR -STARTCHAR dieresis -ENCODING 168 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 3 1 0 7 -BITMAP -A0 -ENDCHAR -STARTCHAR copyright -ENCODING 169 -SWIDTH 737 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -3C -42 -99 -A5 -A1 -9D -42 -3C -ENDCHAR -STARTCHAR ordfeminine -ENCODING 170 -SWIDTH 370 0 -DWIDTH 5 0 -BBX 3 5 1 3 -BITMAP -E0 -20 -A0 -00 -E0 -ENDCHAR -STARTCHAR guillemotleft -ENCODING 171 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 3 0 1 -BITMAP -6C -D8 -6C -ENDCHAR -STARTCHAR logicalnot -ENCODING 172 -SWIDTH 584 0 -DWIDTH 7 0 -BBX 5 3 1 2 -BITMAP -F8 -08 -08 -ENDCHAR -STARTCHAR hyphen -ENCODING 173 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 4 1 0 3 -BITMAP -F0 -ENDCHAR -STARTCHAR registered -ENCODING 174 -SWIDTH 737 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -3C -42 -BD -A5 -B9 -A5 -42 -3C -ENDCHAR -STARTCHAR macron -ENCODING 175 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 3 1 0 7 -BITMAP -E0 -ENDCHAR -STARTCHAR degree -ENCODING 176 -SWIDTH 400 0 -DWIDTH 4 0 -BBX 3 3 1 4 -BITMAP -60 -A0 -C0 -ENDCHAR -STARTCHAR plusminus -ENCODING 177 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 6 7 0 0 -BITMAP -30 -30 -FC -30 -30 -00 -FC -ENDCHAR -STARTCHAR twosuperior -ENCODING 178 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 3 4 0 3 -BITMAP -60 -A0 -40 -E0 -ENDCHAR -STARTCHAR threesuperior -ENCODING 179 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 3 4 0 3 -BITMAP -E0 -40 -20 -C0 -ENDCHAR -STARTCHAR acute -ENCODING 180 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 2 0 7 -BITMAP -40 -80 -ENDCHAR -STARTCHAR mu -ENCODING 181 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -D8 -D8 -D8 -D8 -D8 -E8 -C0 -C0 -ENDCHAR -STARTCHAR paragraph -ENCODING 182 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 10 0 -2 -BITMAP -7C -E8 -E8 -E8 -68 -28 -28 -28 -28 -28 -ENDCHAR -STARTCHAR periodcentered -ENCODING 183 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 1 0 3 -BITMAP -C0 -ENDCHAR -STARTCHAR cedilla -ENCODING 184 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 2 0 -2 -BITMAP -40 -C0 -ENDCHAR -STARTCHAR onesuperior -ENCODING 185 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 4 0 3 -BITMAP -40 -C0 -40 -40 -ENDCHAR -STARTCHAR ordmasculine -ENCODING 186 -SWIDTH 365 0 -DWIDTH 5 0 -BBX 3 5 1 3 -BITMAP -E0 -A0 -E0 -00 -E0 -ENDCHAR -STARTCHAR guillemotright -ENCODING 187 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 3 0 1 -BITMAP -D8 -6C -D8 -ENDCHAR -STARTCHAR onequarter -ENCODING 188 -SWIDTH 834 0 -DWIDTH 9 0 -BBX 8 8 0 0 -BITMAP -42 -C4 -48 -48 -12 -26 -2F -42 -ENDCHAR -STARTCHAR onehalf -ENCODING 189 -SWIDTH 834 0 -DWIDTH 9 0 -BBX 7 8 0 0 -BITMAP -42 -C4 -48 -48 -16 -2A -24 -4E -ENDCHAR -STARTCHAR threequarters -ENCODING 190 -SWIDTH 834 0 -DWIDTH 9 0 -BBX 8 8 0 0 -BITMAP -E2 -44 -28 -C8 -12 -26 -2F -42 -ENDCHAR -STARTCHAR questiondown -ENCODING 191 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 -2 -BITMAP -30 -00 -30 -30 -60 -C0 -D8 -70 -ENDCHAR -STARTCHAR Agrave -ENCODING 192 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -20 -10 -00 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR Aacute -ENCODING 193 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -08 -10 -00 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR Acircumflex -ENCODING 194 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -10 -28 -00 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR Atilde -ENCODING 195 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -14 -28 -00 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR Adieresis -ENCODING 196 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 10 0 0 -BITMAP -28 -00 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR Aring -ENCODING 197 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -10 -28 -10 -38 -38 -6C -6C -6C -FE -C6 -C6 -ENDCHAR -STARTCHAR AE -ENCODING 198 -SWIDTH 1000 0 -DWIDTH 10 0 -BBX 9 8 0 0 -BITMAP -3F80 -3C00 -6C00 -6F80 -6C00 -FC00 -CC00 -CF80 -ENDCHAR -STARTCHAR Ccedilla -ENCODING 199 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 10 0 -2 -BITMAP -3C -66 -C2 -C0 -C0 -C2 -66 -3C -10 -30 -ENDCHAR -STARTCHAR Egrave -ENCODING 200 -SWIDTH 667 0 -DWIDTH 6 0 -BBX 5 11 0 0 -BITMAP -40 -20 -00 -F8 -C0 -C0 -F8 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR Eacute -ENCODING 201 -SWIDTH 667 0 -DWIDTH 6 0 -BBX 5 11 0 0 -BITMAP -10 -20 -00 -F8 -C0 -C0 -F8 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR Ecircumflex -ENCODING 202 -SWIDTH 667 0 -DWIDTH 6 0 -BBX 5 11 0 0 -BITMAP -20 -50 -00 -F8 -C0 -C0 -F8 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR Edieresis -ENCODING 203 -SWIDTH 667 0 -DWIDTH 6 0 -BBX 5 10 0 0 -BITMAP -50 -00 -F8 -C0 -C0 -F8 -C0 -C0 -C0 -F8 -ENDCHAR -STARTCHAR Igrave -ENCODING 204 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 11 0 0 -BITMAP -80 -40 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Iacute -ENCODING 205 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 11 0 0 -BITMAP -40 -80 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Icircumflex -ENCODING 206 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 3 11 0 0 -BITMAP -40 -A0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Idieresis -ENCODING 207 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 3 10 0 0 -BITMAP -A0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Eth -ENCODING 208 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -F0 -D8 -CC -EC -CC -CC -D8 -F0 -ENDCHAR -STARTCHAR Ntilde -ENCODING 209 -SWIDTH 722 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -14 -28 -00 -C6 -C6 -E6 -D6 -D6 -CE -CE -C6 -ENDCHAR -STARTCHAR Ograve -ENCODING 210 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -20 -10 -00 -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR Oacute -ENCODING 211 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -04 -08 -00 -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR Ocircumflex -ENCODING 212 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -10 -28 -00 -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR Otilde -ENCODING 213 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 11 0 0 -BITMAP -14 -28 -00 -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR Odieresis -ENCODING 214 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 10 0 0 -BITMAP -28 -00 -38 -6C -C6 -C6 -C6 -C6 -6C -38 -ENDCHAR -STARTCHAR multiply -ENCODING 215 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 6 5 0 1 -BITMAP -CC -78 -30 -78 -CC -ENDCHAR -STARTCHAR Oslash -ENCODING 216 -SWIDTH 778 0 -DWIDTH 8 0 -BBX 7 8 0 0 -BITMAP -3A -6C -CE -D6 -D6 -E6 -6C -B8 -ENDCHAR -STARTCHAR Ugrave -ENCODING 217 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 11 0 0 -BITMAP -20 -10 -00 -CC -CC -CC -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR Uacute -ENCODING 218 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 11 0 0 -BITMAP -08 -10 -00 -CC -CC -CC -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR Ucircumflex -ENCODING 219 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 11 0 0 -BITMAP -10 -28 -00 -CC -CC -CC -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR Udieresis -ENCODING 220 -SWIDTH 722 0 -DWIDTH 7 0 -BBX 6 10 0 0 -BITMAP -28 -00 -CC -CC -CC -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR Yacute -ENCODING 221 -SWIDTH 667 0 -DWIDTH 9 0 -BBX 8 11 0 0 -BITMAP -04 -08 -00 -C3 -C3 -66 -66 -3C -18 -18 -18 -ENDCHAR -STARTCHAR Thorn -ENCODING 222 -SWIDTH 667 0 -DWIDTH 7 0 -BBX 6 8 0 0 -BITMAP -C0 -F8 -CC -CC -CC -F8 -C0 -C0 -ENDCHAR -STARTCHAR germandbls -ENCODING 223 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 8 0 0 -BITMAP -70 -C8 -C8 -D0 -C8 -C8 -C8 -D0 -ENDCHAR -STARTCHAR agrave -ENCODING 224 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -40 -20 -00 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR aacute -ENCODING 225 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -08 -10 -00 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR acircumflex -ENCODING 226 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -30 -68 -00 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR atilde -ENCODING 227 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -28 -50 -00 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR adieresis -ENCODING 228 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -50 -50 -00 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR aring -ENCODING 229 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 9 0 0 -BITMAP -20 -50 -20 -70 -98 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR ae -ENCODING 230 -SWIDTH 889 0 -DWIDTH 9 0 -BBX 8 6 0 0 -BITMAP -7E -9B -7F -D8 -DB -6E -ENDCHAR -STARTCHAR ccedilla -ENCODING 231 -SWIDTH 556 0 -DWIDTH 5 0 -BBX 4 8 0 -2 -BITMAP -70 -D0 -C0 -C0 -D0 -70 -20 -60 -ENDCHAR -STARTCHAR egrave -ENCODING 232 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -40 -20 -00 -70 -D8 -F8 -C0 -D8 -70 -ENDCHAR -STARTCHAR eacute -ENCODING 233 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -10 -20 -00 -70 -D8 -F8 -C0 -D8 -70 -ENDCHAR -STARTCHAR ecircumflex -ENCODING 234 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -20 -50 -00 -70 -D8 -F8 -C0 -D8 -70 -ENDCHAR -STARTCHAR edieresis -ENCODING 235 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -50 -00 -70 -D8 -F8 -C0 -D8 -70 -ENDCHAR -STARTCHAR igrave -ENCODING 236 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 9 0 0 -BITMAP -80 -40 -00 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR iacute -ENCODING 237 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 3 9 0 0 -BITMAP -20 -40 -00 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR icircumflex -ENCODING 238 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 3 9 -1 0 -BITMAP -40 -A0 -00 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR idieresis -ENCODING 239 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 3 9 0 0 -BITMAP -A0 -A0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR eth -ENCODING 240 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -60 -A0 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR ntilde -ENCODING 241 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -28 -50 -00 -B0 -D8 -D8 -D8 -D8 -D8 -ENDCHAR -STARTCHAR ograve -ENCODING 242 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -40 -20 -00 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR oacute -ENCODING 243 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -10 -20 -00 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR ocircumflex -ENCODING 244 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -20 -50 -00 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR otilde -ENCODING 245 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -A0 -00 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR odieresis -ENCODING 246 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -50 -00 -70 -D8 -D8 -D8 -D8 -70 -ENDCHAR -STARTCHAR divide -ENCODING 247 -SWIDTH 584 0 -DWIDTH 6 0 -BBX 6 5 0 1 -BITMAP -30 -00 -FC -00 -30 -ENDCHAR -STARTCHAR oslash -ENCODING 248 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 6 6 0 0 -BITMAP -74 -D8 -F8 -D8 -D8 -70 -ENDCHAR -STARTCHAR ugrave -ENCODING 249 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -40 -20 -00 -D8 -D8 -D8 -D8 -D8 -68 -ENDCHAR -STARTCHAR uacute -ENCODING 250 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -10 -20 -00 -D8 -D8 -D8 -D8 -D8 -68 -ENDCHAR -STARTCHAR ucircumflex -ENCODING 251 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -20 -50 -00 -D8 -D8 -D8 -D8 -D8 -68 -ENDCHAR -STARTCHAR udieresis -ENCODING 252 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -50 -00 -D8 -D8 -D8 -D8 -D8 -68 -ENDCHAR -STARTCHAR yacute -ENCODING 253 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 11 0 -2 -BITMAP -10 -20 -00 -D8 -D8 -D8 -D8 -78 -30 -30 -60 -ENDCHAR -STARTCHAR thorn -ENCODING 254 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 5 10 0 -2 -BITMAP -C0 -C0 -F0 -D8 -C8 -C8 -D8 -F0 -C0 -C0 -ENDCHAR -STARTCHAR ydieresis -ENCODING 255 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 11 0 -2 -BITMAP -50 -50 -00 -D8 -D8 -D8 -D8 -78 -30 -30 -60 -ENDCHAR -STARTCHAR Lslash -ENCODING -1 -SWIDTH 611 0 -DWIDTH 6 0 -BBX 6 8 -1 0 -BITMAP -60 -60 -60 -70 -E0 -60 -60 -7C -ENDCHAR -STARTCHAR OE -ENCODING -1 -SWIDTH 1000 0 -DWIDTH 10 0 -BBX 9 8 0 0 -BITMAP -3F80 -6C00 -CC00 -CF80 -CC00 -CC00 -6C00 -3F80 -ENDCHAR -STARTCHAR Scaron -ENCODING -1 -SWIDTH 667 0 -DWIDTH 7 0 -BBX 6 9 0 0 -BITMAP -28 -10 -00 -78 -CC -70 -3C -CC -78 -ENDCHAR -STARTCHAR Ydieresis -ENCODING -1 -SWIDTH 667 0 -DWIDTH 8 0 -BBX 8 8 0 0 -BITMAP -14 -00 -C3 -66 -3C -18 -18 -18 -ENDCHAR -STARTCHAR Zcaron -ENCODING -1 -SWIDTH 611 0 -DWIDTH 7 0 -BBX 6 9 0 0 -BITMAP -28 -10 -00 -FC -18 -30 -60 -C0 -FC -ENDCHAR -STARTCHAR breve -ENCODING -1 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 4 2 0 6 -BITMAP -90 -60 -ENDCHAR -STARTCHAR bullet -ENCODING -1 -SWIDTH 350 0 -DWIDTH 4 0 -BBX 2 2 1 2 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR caron -ENCODING -1 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 2 0 6 -BITMAP -A0 -40 -ENDCHAR -STARTCHAR circumflex -ENCODING -1 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 2 0 6 -BITMAP -40 -A0 -ENDCHAR -STARTCHAR dagger -ENCODING -1 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 10 0 -2 -BITMAP -30 -30 -FC -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR daggerdbl -ENCODING -1 -SWIDTH 556 0 -DWIDTH 7 0 -BBX 6 10 0 -2 -BITMAP -30 -30 -FC -30 -30 -30 -FC -30 -30 -30 -ENDCHAR -STARTCHAR dotaccent -ENCODING -1 -SWIDTH 333 0 -DWIDTH 2 0 -BBX 1 1 0 7 -BITMAP -80 -ENDCHAR -STARTCHAR dotlessi -ENCODING -1 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 6 0 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR ellipsis -ENCODING -1 -SWIDTH 1000 0 -DWIDTH 10 0 -BBX 8 1 1 0 -BITMAP -DB -ENDCHAR -STARTCHAR emdash -ENCODING -1 -SWIDTH 1000 0 -DWIDTH 10 0 -BBX 10 1 0 3 -BITMAP -FFC0 -ENDCHAR -STARTCHAR endash -ENCODING -1 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 6 1 0 3 -BITMAP -FC -ENDCHAR -STARTCHAR fi -ENCODING -1 -SWIDTH 611 0 -DWIDTH 7 0 -BBX 7 8 -1 0 -BITMAP -36 -60 -F6 -66 -66 -66 -66 -66 -ENDCHAR -STARTCHAR fl -ENCODING -1 -SWIDTH 611 0 -DWIDTH 7 0 -BBX 7 8 -1 0 -BITMAP -36 -66 -F6 -66 -66 -66 -66 -66 -ENDCHAR -STARTCHAR florin -ENCODING -1 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 -2 -BITMAP -38 -60 -F8 -60 -60 -60 -60 -60 -C0 -ENDCHAR -STARTCHAR fraction -ENCODING -1 -SWIDTH 167 0 -DWIDTH 4 0 -BBX 5 7 -1 0 -BITMAP -08 -10 -10 -20 -40 -40 -80 -ENDCHAR -STARTCHAR grave -ENCODING -1 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 2 0 6 -BITMAP -80 -40 -ENDCHAR -STARTCHAR guilsinglleft -ENCODING -1 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 3 3 1 1 -BITMAP -60 -C0 -60 -ENDCHAR -STARTCHAR guilsinglright -ENCODING -1 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 3 3 1 1 -BITMAP -C0 -60 -C0 -ENDCHAR -STARTCHAR hungarumlaut -ENCODING -1 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 4 2 0 6 -BITMAP -50 -A0 -ENDCHAR -STARTCHAR lslash -ENCODING -1 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 4 8 -1 0 -BITMAP -60 -60 -60 -70 -E0 -60 -60 -60 -ENDCHAR -STARTCHAR oe -ENCODING -1 -SWIDTH 944 0 -DWIDTH 10 0 -BBX 9 6 0 0 -BITMAP -7700 -CD80 -CF80 -CC00 -CD80 -7700 -ENDCHAR -STARTCHAR ogonek -ENCODING -1 -SWIDTH 333 0 -DWIDTH 3 0 -BBX 2 2 0 -2 -BITMAP -80 -C0 -ENDCHAR -STARTCHAR perthousand -ENCODING -1 -SWIDTH 1000 0 -DWIDTH 11 0 -BBX 10 7 0 0 -BITMAP -6200 -B400 -6800 -1000 -2D80 -56C0 -8D80 -ENDCHAR -STARTCHAR quotedblbase -ENCODING -1 -SWIDTH 500 0 -DWIDTH 6 0 -BBX 5 3 0 -2 -BITMAP -D8 -48 -90 -ENDCHAR -STARTCHAR quotedblleft -ENCODING -1 -SWIDTH 500 0 -DWIDTH 6 0 -BBX 5 3 0 5 -BITMAP -48 -90 -D8 -ENDCHAR -STARTCHAR quotedblright -ENCODING -1 -SWIDTH 500 0 -DWIDTH 6 0 -BBX 5 3 0 5 -BITMAP -D8 -48 -90 -ENDCHAR -STARTCHAR quotesinglbase -ENCODING -1 -SWIDTH 278 0 -DWIDTH 3 0 -BBX 2 3 0 -2 -BITMAP -C0 -40 -80 -ENDCHAR -STARTCHAR quotesingle -ENCODING -1 -SWIDTH 238 0 -DWIDTH 3 0 -BBX 1 3 1 5 -BITMAP -80 -80 -80 -ENDCHAR -STARTCHAR ring -ENCODING -1 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 3 3 0 5 -BITMAP -40 -A0 -40 -ENDCHAR -STARTCHAR scaron -ENCODING -1 -SWIDTH 556 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -50 -20 -00 -70 -D8 -70 -18 -D8 -70 -ENDCHAR -STARTCHAR tilde -ENCODING -1 -SWIDTH 333 0 -DWIDTH 4 0 -BBX 4 2 0 6 -BITMAP -50 -A0 -ENDCHAR -STARTCHAR trademark -ENCODING -1 -SWIDTH 1000 0 -DWIDTH 11 0 -BBX 9 4 1 3 -BITMAP -E880 -4D80 -4A80 -4A80 -ENDCHAR -STARTCHAR zcaron -ENCODING -1 -SWIDTH 500 0 -DWIDTH 5 0 -BBX 5 9 0 0 -BITMAP -50 -20 -00 -F8 -18 -30 -60 -C0 -F8 -ENDCHAR -ENDFONT diff --git a/fonts/luBS14.bdf b/fonts/luBS14.bdf deleted file mode 100644 index 90c37be9..00000000 --- a/fonts/luBS14.bdf +++ /dev/null @@ -1,13542 +0,0 @@ -STARTFONT 2.1 -COMMENT $Xorg: $ -COMMENT ISO10646-1 extension by Markus Kuhn , 2001-03-20 -COMMENT (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered -COMMENT trademark of Bigelow & Holmes. See LEGAL NOTICE file for terms -COMMENT of the license. -COMMENT GRID 0014 0014 0200 0200 -FONT -B&H-Lucida-Bold-R-Normal-Sans-14-140-75-75-P-92-ISO10646-1 -SIZE 14 72 72 -FONTBOUNDINGBOX 18 21 -1 -5 -STARTPROPERTIES 22 -COMMENT Begin LogicalFontDescription -FONTNAME_REGISTRY "" -FOUNDRY "B&H" -FAMILY_NAME "Lucida" -WEIGHT_NAME "Bold" -SLANT "R" -SETWIDTH_NAME "Normal" -ADD_STYLE_NAME "Sans" -PIXEL_SIZE 14 -POINT_SIZE 140 -RESOLUTION_X 75 -RESOLUTION_Y 75 -SPACING "P" -AVERAGE_WIDTH 92 -CHARSET_REGISTRY "ISO10646" -CHARSET_ENCODING "1" -COMMENT END LogicalFontDescription -FONT_ASCENT 13 -FONT_DESCENT 2 -DEFAULT_CHAR 0 -COPYRIGHT "Copyright Bigelow & Holmes 1986, 1985." -FACE_NAME "Lucida Sans Bold" -X_HEIGHT 8 -CAP_HEIGHT 10 -ENDPROPERTIES -CHARS 756 -STARTCHAR char0 -ENCODING 0 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 7 9 2 0 -BITMAP -AA -00 -82 -00 -82 -00 -82 -00 -AA -ENDCHAR -STARTCHAR space -ENCODING 32 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclam -ENCODING 33 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 10 1 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -80 -80 -00 -C0 -C0 -ENDCHAR -STARTCHAR quotedbl -ENCODING 34 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 7 -BITMAP -D8 -D8 -90 -90 -ENDCHAR -STARTCHAR numbersign -ENCODING 35 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 9 10 0 0 -BITMAP -1B00 -1B00 -1B00 -7F80 -3600 -3600 -FF80 -6C00 -6C00 -6C00 -ENDCHAR -STARTCHAR dollar -ENCODING 36 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 12 1 -1 -BITMAP -10 -7C -D6 -D0 -F0 -70 -1C -1E -16 -D6 -7C -10 -ENDCHAR -STARTCHAR percent -ENCODING 37 -SWIDTH 898 0 -DWIDTH 12 0 -BBX 10 10 1 0 -BITMAP -7000 -D980 -DB00 -7200 -0400 -0800 -1380 -36C0 -66C0 -0380 -ENDCHAR -STARTCHAR ampersand -ENCODING 38 -SWIDTH 792 0 -DWIDTH 11 0 -BBX 9 10 1 0 -BITMAP -3C00 -6600 -6600 -6400 -3980 -5980 -CD00 -C600 -E700 -7980 -ENDCHAR -STARTCHAR quotesingle -ENCODING 39 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -80 -80 -ENDCHAR -STARTCHAR parenleft -ENCODING 40 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -30 -60 -60 -C0 -C0 -C0 -C0 -C0 -C0 -60 -60 -30 -ENDCHAR -STARTCHAR parenright -ENCODING 41 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -C0 -60 -60 -30 -30 -30 -30 -30 -30 -60 -60 -C0 -ENDCHAR -STARTCHAR asterisk -ENCODING 42 -SWIDTH 464 0 -DWIDTH 7 0 -BBX 5 5 1 5 -BITMAP -20 -A8 -70 -A8 -20 -ENDCHAR -STARTCHAR plus -ENCODING 43 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 7 1 1 -BITMAP -10 -10 -10 -FE -10 -10 -10 -ENDCHAR -STARTCHAR comma -ENCODING 44 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 4 1 -2 -BITMAP -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR hyphen -ENCODING 45 -SWIDTH 289 0 -DWIDTH 5 0 -BBX 3 1 1 4 -BITMAP -E0 -ENDCHAR -STARTCHAR period -ENCODING 46 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 2 1 0 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR slash -ENCODING 47 -SWIDTH 596 0 -DWIDTH 8 0 -BBX 8 12 0 -1 -BITMAP -03 -06 -06 -0C -0C -18 -18 -30 -30 -60 -60 -C0 -ENDCHAR -STARTCHAR zero -ENCODING 48 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -3C -66 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR one -ENCODING 49 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 5 10 2 0 -BITMAP -18 -F8 -18 -18 -18 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR two -ENCODING 50 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -7E -C7 -03 -03 -06 -0C -18 -60 -FF -FF -ENDCHAR -STARTCHAR three -ENCODING 51 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -7E -C7 -03 -06 -3C -06 -03 -03 -C7 -7E -ENDCHAR -STARTCHAR four -ENCODING 52 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -0C -1C -2C -4C -8C -FF -FF -0C -0C -0C -ENDCHAR -STARTCHAR five -ENCODING 53 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 10 2 0 -BITMAP -FC -FC -80 -80 -FC -0E -06 -06 -CC -78 -ENDCHAR -STARTCHAR six -ENCODING 54 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -3E -63 -C0 -DC -E6 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR seven -ENCODING 55 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -FF -FF -06 -0C -18 -30 -30 -60 -60 -60 -ENDCHAR -STARTCHAR eight -ENCODING 56 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -7E -C7 -C3 -72 -3C -4E -C7 -C3 -E3 -7E -ENDCHAR -STARTCHAR nine -ENCODING 57 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -3C -66 -C3 -C3 -C3 -67 -1B -03 -C6 -7C -ENDCHAR -STARTCHAR colon -ENCODING 58 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 7 1 0 -BITMAP -C0 -C0 -00 -00 -00 -C0 -C0 -ENDCHAR -STARTCHAR semicolon -ENCODING 59 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 9 1 -2 -BITMAP -C0 -C0 -00 -00 -00 -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR less -ENCODING 60 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 6 7 2 1 -BITMAP -0C -38 -60 -C0 -60 -38 -0C -ENDCHAR -STARTCHAR equal -ENCODING 61 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 3 1 3 -BITMAP -FE -00 -FE -ENDCHAR -STARTCHAR greater -ENCODING 62 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 6 7 2 1 -BITMAP -C0 -70 -18 -0C -18 -70 -C0 -ENDCHAR -STARTCHAR question -ENCODING 63 -SWIDTH 572 0 -DWIDTH 8 0 -BBX 6 10 1 0 -BITMAP -78 -CC -0C -0C -18 -30 -30 -00 -30 -30 -ENDCHAR -STARTCHAR at -ENCODING 64 -SWIDTH 833 0 -DWIDTH 12 0 -BBX 10 10 1 0 -BITMAP -1E00 -6100 -4180 -8F80 -9980 -9980 -9980 -4EC0 -6000 -1F00 -ENDCHAR -STARTCHAR A -ENCODING 65 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 10 1 0 -BITMAP -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR B -ENCODING 66 -SWIDTH 669 0 -DWIDTH 10 0 -BBX 7 10 2 0 -BITMAP -FC -C6 -C6 -CC -F0 -CC -C6 -C6 -C6 -FC -ENDCHAR -STARTCHAR C -ENCODING 67 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -ENDCHAR -STARTCHAR D -ENCODING 68 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 10 2 0 -BITMAP -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -ENDCHAR -STARTCHAR E -ENCODING 69 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR F -ENCODING 70 -SWIDTH 602 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR G -ENCODING 71 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR H -ENCODING 72 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 10 2 0 -BITMAP -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR I -ENCODING 73 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 2 10 2 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR J -ENCODING 74 -SWIDTH 501 0 -DWIDTH 6 0 -BBX 4 12 0 -2 -BITMAP -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR K -ENCODING 75 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR L -ENCODING 76 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR M -ENCODING 77 -SWIDTH 940 0 -DWIDTH 15 0 -BBX 11 10 2 0 -BITMAP -E0E0 -E0E0 -B160 -B160 -B160 -9A60 -9A60 -8C60 -8C60 -8060 -ENDCHAR -STARTCHAR N -ENCODING 78 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 10 2 0 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR O -ENCODING 79 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 10 1 0 -BITMAP -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR P -ENCODING 80 -SWIDTH 657 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -F8 -CC -CC -CC -CC -F8 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Q -ENCODING 81 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 12 1 -2 -BITMAP -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0300 -0180 -ENDCHAR -STARTCHAR R -ENCODING 82 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR S -ENCODING 83 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR T -ENCODING 84 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR U -ENCODING 85 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 10 2 0 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR V -ENCODING 86 -SWIDTH 735 0 -DWIDTH 11 0 -BBX 9 10 1 0 -BITMAP -C180 -C180 -C180 -6100 -6300 -6300 -3200 -3600 -1C00 -1C00 -ENDCHAR -STARTCHAR W -ENCODING 87 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 10 1 0 -BITMAP -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR X -ENCODING 88 -SWIDTH 699 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -C6 -C6 -6C -6C -38 -38 -6C -6C -C6 -C6 -ENDCHAR -STARTCHAR Y -ENCODING 89 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR Z -ENCODING 90 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR bracketleft -ENCODING 91 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -F0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -F0 -ENDCHAR -STARTCHAR backslash -ENCODING 92 -SWIDTH 596 0 -DWIDTH 8 0 -BBX 8 12 0 -1 -BITMAP -C0 -60 -60 -30 -30 -18 -18 -0C -0C -06 -06 -03 -ENDCHAR -STARTCHAR bracketright -ENCODING 93 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -F0 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -F0 -ENDCHAR -STARTCHAR asciicircum -ENCODING 94 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 6 7 2 3 -BITMAP -30 -30 -78 -48 -CC -84 -84 -ENDCHAR -STARTCHAR underscore -ENCODING 95 -SWIDTH 500 0 -DWIDTH 11 0 -BBX 9 1 1 -1 -BITMAP -FF80 -ENDCHAR -STARTCHAR grave -ENCODING 96 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 2 9 -BITMAP -E0 -38 -ENDCHAR -STARTCHAR a -ENCODING 97 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 8 1 0 -BITMAP -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR b -ENCODING 98 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -C0 -C0 -C0 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -ENDCHAR -STARTCHAR c -ENCODING 99 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -3C -66 -C0 -C0 -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR d -ENCODING 100 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -ENDCHAR -STARTCHAR e -ENCODING 101 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR f -ENCODING 102 -SWIDTH 461 0 -DWIDTH 7 0 -BBX 7 11 0 0 -BITMAP -1E -30 -30 -FE -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR g -ENCODING 103 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR h -ENCODING 104 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR i -ENCODING 105 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 11 1 0 -BITMAP -C0 -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR j -ENCODING 106 -SWIDTH 361 0 -DWIDTH 5 0 -BBX 4 13 0 -2 -BITMAP -30 -30 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR k -ENCODING 107 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -ENDCHAR -STARTCHAR l -ENCODING 108 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 11 1 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR m -ENCODING 109 -SWIDTH 1006 0 -DWIDTH 14 0 -BBX 12 8 1 0 -BITMAP -DDE0 -EF70 -C630 -C630 -C630 -C630 -C630 -C630 -ENDCHAR -STARTCHAR n -ENCODING 110 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR o -ENCODING 111 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR p -ENCODING 112 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -C0 -C0 -ENDCHAR -STARTCHAR q -ENCODING 113 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -3F -63 -C3 -C3 -C3 -C3 -67 -3B -03 -03 -ENDCHAR -STARTCHAR r -ENCODING 114 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 8 2 0 -BITMAP -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR s -ENCODING 115 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 8 1 0 -BITMAP -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR t -ENCODING 116 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 10 1 0 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -ENDCHAR -STARTCHAR u -ENCODING 117 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR v -ENCODING 118 -SWIDTH 663 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -C6 -C6 -C6 -C6 -64 -68 -38 -38 -ENDCHAR -STARTCHAR w -ENCODING 119 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 8 1 0 -BITMAP -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR x -ENCODING 120 -SWIDTH 568 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -C6 -C6 -64 -38 -38 -4C -C6 -C6 -ENDCHAR -STARTCHAR y -ENCODING 121 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 10 1 -2 -BITMAP -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR z -ENCODING 122 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -FE -06 -0C -18 -30 -60 -C0 -FE -ENDCHAR -STARTCHAR braceleft -ENCODING 123 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -70 -C0 -C0 -60 -20 -C0 -20 -60 -C0 -C0 -C0 -70 -ENDCHAR -STARTCHAR bar -ENCODING 124 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 12 1 -1 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR braceright -ENCODING 125 -SWIDTH 386 0 -DWIDTH 6 0 -BBX 4 12 1 -1 -BITMAP -E0 -30 -30 -60 -40 -30 -40 -60 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR asciitilde -ENCODING 126 -SWIDTH 687 0 -DWIDTH 9 0 -BBX 7 3 1 3 -BITMAP -72 -BA -9C -ENDCHAR -STARTCHAR space -ENCODING 160 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclamdown -ENCODING 161 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 10 1 -2 -BITMAP -C0 -C0 -00 -40 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR cent -ENCODING 162 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 12 1 -1 -BITMAP -08 -08 -3E -6A -C8 -C8 -C8 -C8 -68 -3E -08 -08 -ENDCHAR -STARTCHAR sterling -ENCODING 163 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 10 1 0 -BITMAP -1C -32 -30 -30 -FC -30 -30 -30 -60 -FE -ENDCHAR -STARTCHAR currency -ENCODING 164 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 9 10 0 0 -BITMAP -8080 -4100 -3E00 -6300 -6300 -6300 -6300 -3E00 -4100 -8080 -ENDCHAR -STARTCHAR yen -ENCODING 165 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -C3 -C3 -62 -66 -34 -7E -18 -7E -18 -18 -ENDCHAR -STARTCHAR brokenbar -ENCODING 166 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 12 1 -1 -BITMAP -C0 -C0 -C0 -C0 -C0 -00 -00 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR section -ENCODING 167 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 6 11 2 -1 -BITMAP -78 -CC -C0 -70 -D8 -CC -6C -38 -0C -CC -78 -ENDCHAR -STARTCHAR dieresis -ENCODING 168 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 2 3 9 -BITMAP -90 -90 -ENDCHAR -STARTCHAR copyright -ENCODING 169 -SWIDTH 825 0 -DWIDTH 12 0 -BBX 10 10 1 0 -BITMAP -1E00 -6180 -4080 -8E40 -9840 -9840 -8E40 -4080 -6180 -1E00 -ENDCHAR -STARTCHAR ordfeminine -ENCODING 170 -SWIDTH 536 0 -DWIDTH 8 0 -BBX 6 6 1 4 -BITMAP -70 -18 -78 -D8 -D8 -6C -ENDCHAR -STARTCHAR guillemotleft -ENCODING 171 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 8 5 0 2 -BITMAP -33 -66 -CC -66 -33 -ENDCHAR -STARTCHAR logicalnot -ENCODING 172 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 4 1 1 -BITMAP -FE -02 -02 -02 -ENDCHAR -STARTCHAR hyphen -ENCODING 173 -SWIDTH 289 0 -DWIDTH 5 0 -BBX 3 1 1 4 -BITMAP -E0 -ENDCHAR -STARTCHAR registered -ENCODING 174 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 7 1 3 -BITMAP -38 -44 -BA -B2 -AA -44 -38 -ENDCHAR -STARTCHAR macron -ENCODING 175 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 1 3 9 -BITMAP -F0 -ENDCHAR -STARTCHAR degree -ENCODING 176 -SWIDTH 241 0 -DWIDTH 4 0 -BBX 4 3 0 7 -BITMAP -60 -90 -60 -ENDCHAR -STARTCHAR plusminus -ENCODING 177 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 7 1 1 -BITMAP -10 -10 -FE -10 -10 -00 -FE -ENDCHAR -STARTCHAR twosuperior -ENCODING 178 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 5 6 1 4 -BITMAP -F0 -18 -18 -60 -C0 -F8 -ENDCHAR -STARTCHAR threesuperior -ENCODING 179 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 5 6 1 4 -BITMAP -F0 -18 -70 -18 -18 -F0 -ENDCHAR -STARTCHAR acute -ENCODING 180 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 9 -BITMAP -38 -E0 -ENDCHAR -STARTCHAR mu -ENCODING 181 -SWIDTH 699 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -FB -C0 -C0 -ENDCHAR -STARTCHAR paragraph -ENCODING 182 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 6 11 2 -1 -BITMAP -7C -F4 -F4 -F4 -F4 -74 -14 -14 -14 -14 -14 -ENDCHAR -STARTCHAR periodcentered -ENCODING 183 -SWIDTH 343 0 -DWIDTH 10 0 -BBX 2 2 4 3 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR cedilla -ENCODING 184 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 3 2 3 -2 -BITMAP -20 -C0 -ENDCHAR -STARTCHAR onesuperior -ENCODING 185 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 4 6 1 4 -BITMAP -30 -F0 -30 -30 -30 -30 -ENDCHAR -STARTCHAR ordmasculine -ENCODING 186 -SWIDTH 536 0 -DWIDTH 8 0 -BBX 6 6 1 4 -BITMAP -78 -CC -CC -CC -CC -78 -ENDCHAR -STARTCHAR guillemotright -ENCODING 187 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 8 5 1 2 -BITMAP -CC -66 -33 -66 -CC -ENDCHAR -STARTCHAR onequarter -ENCODING 188 -SWIDTH 1066 0 -DWIDTH 14 0 -BBX 12 10 1 0 -BITMAP -6100 -E100 -6200 -6200 -64E0 -6560 -0A60 -0BF0 -1060 -1060 -ENDCHAR -STARTCHAR onehalf -ENCODING 189 -SWIDTH 1066 0 -DWIDTH 14 0 -BBX 12 10 1 0 -BITMAP -6100 -E100 -6200 -6200 -64E0 -6530 -0870 -08E0 -1180 -11F0 -ENDCHAR -STARTCHAR threequarters -ENCODING 190 -SWIDTH 1120 0 -DWIDTH 15 0 -BBX 13 10 1 0 -BITMAP -7080 -9880 -3100 -1A00 -9A70 -74B0 -0530 -09F8 -1030 -1030 -ENDCHAR -STARTCHAR questiondown -ENCODING 191 -SWIDTH 572 0 -DWIDTH 8 0 -BBX 6 10 1 -2 -BITMAP -30 -30 -00 -30 -30 -60 -C0 -C0 -CC -78 -ENDCHAR -STARTCHAR Agrave -ENCODING 192 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -7000 -1C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR Aacute -ENCODING 193 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -0700 -1C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR Acircumflex -ENCODING 194 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1C00 -2600 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR Atilde -ENCODING 195 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1A00 -2C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR Adieresis -ENCODING 196 -SWIDTH 773 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -24 -24 -00 -18 -18 -2C -2C -66 -46 -FE -C3 -C3 -C3 -ENDCHAR -STARTCHAR Aring -ENCODING 197 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1C00 -2600 -1C00 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR AE -ENCODING 198 -SWIDTH 997 0 -DWIDTH 13 0 -BBX 11 10 1 0 -BITMAP -1FE0 -1600 -2600 -2600 -67C0 -4600 -7E00 -C600 -C600 -C7E0 -ENDCHAR -STARTCHAR Ccedilla -ENCODING 199 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 12 2 -2 -BITMAP -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -08 -30 -ENDCHAR -STARTCHAR Egrave -ENCODING 200 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -70 -1C -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR Eacute -ENCODING 201 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -1C -70 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR Ecircumflex -ENCODING 202 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -30 -58 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR Edieresis -ENCODING 203 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -48 -48 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR Igrave -ENCODING 204 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 13 1 0 -BITMAP -E0 -30 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Iacute -ENCODING 205 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 13 1 0 -BITMAP -70 -C0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Icircumflex -ENCODING 206 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 13 1 0 -BITMAP -60 -B0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Idieresis -ENCODING 207 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 13 1 0 -BITMAP -90 -90 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Eth -ENCODING 208 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 11 10 0 0 -BITMAP -3F80 -30C0 -3060 -3060 -FC60 -3060 -3060 -3060 -30C0 -3F80 -ENDCHAR -STARTCHAR Ntilde -ENCODING 209 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -1A -2C -00 -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR Ograve -ENCODING 210 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -3800 -0E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR Oacute -ENCODING 211 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -0700 -1C00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR Ocircumflex -ENCODING 212 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -0C00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR Otilde -ENCODING 213 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -0D00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR Odieresis -ENCODING 214 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -2100 -2100 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR multiply -ENCODING 215 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 5 5 2 2 -BITMAP -C8 -70 -20 -70 -98 -ENDCHAR -STARTCHAR Oslash -ENCODING 216 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 12 1 -1 -BITMAP -0040 -3F40 -6180 -C2C0 -C2C0 -C4C0 -C8C0 -D0C0 -D0C0 -6180 -BF00 -8000 -ENDCHAR -STARTCHAR Ugrave -ENCODING 217 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -70 -1C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR Uacute -ENCODING 218 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR Ucircumflex -ENCODING 219 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -18 -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR Udieresis -ENCODING 220 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -64 -3C -ENDCHAR -STARTCHAR Yacute -ENCODING 221 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -0E -38 -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR Thorn -ENCODING 222 -SWIDTH 657 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -C0 -C0 -F8 -CC -CC -CC -CC -F8 -C0 -C0 -ENDCHAR -STARTCHAR germandbls -ENCODING 223 -SWIDTH 724 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -7C -C6 -C6 -C4 -CC -C6 -C3 -C3 -C3 -C3 -CE -ENDCHAR -STARTCHAR agrave -ENCODING 224 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -70 -1C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR aacute -ENCODING 225 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -0E -38 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR acircumflex -ENCODING 226 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -18 -2C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR atilde -ENCODING 227 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -34 -58 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR adieresis -ENCODING 228 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -24 -24 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR aring -ENCODING 229 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -18 -2C -18 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR ae -ENCODING 230 -SWIDTH 913 0 -DWIDTH 14 0 -BBX 12 8 1 0 -BITMAP -7DE0 -0730 -0630 -7FF0 -C600 -C600 -C710 -79E0 -ENDCHAR -STARTCHAR ccedilla -ENCODING 231 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 10 1 -2 -BITMAP -3C -66 -C0 -C0 -C0 -C0 -62 -3C -10 -60 -ENDCHAR -STARTCHAR egrave -ENCODING 232 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -70 -1C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR eacute -ENCODING 233 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -0E -38 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR ecircumflex -ENCODING 234 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -18 -2C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR edieresis -ENCODING 235 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -44 -44 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR igrave -ENCODING 236 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 11 0 0 -BITMAP -E0 -30 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR iacute -ENCODING 237 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 11 0 0 -BITMAP -70 -C0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR icircumflex -ENCODING 238 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 11 0 0 -BITMAP -60 -B0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR idieresis -ENCODING 239 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 11 0 0 -BITMAP -90 -90 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR eth -ENCODING 240 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -10 -3E -0C -3E -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR ntilde -ENCODING 241 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -1A -2C -00 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR ograve -ENCODING 242 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -70 -1C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR oacute -ENCODING 243 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -0E -38 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR ocircumflex -ENCODING 244 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -18 -2C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR otilde -ENCODING 245 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -34 -58 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR odieresis -ENCODING 246 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -24 -24 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR divide -ENCODING 247 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 7 1 1 -BITMAP -10 -10 -00 -FE -00 -10 -10 -ENDCHAR -STARTCHAR oslash -ENCODING 248 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 10 1 -1 -BITMAP -01 -3D -66 -CB -CB -D3 -D3 -66 -BC -80 -ENDCHAR -STARTCHAR ugrave -ENCODING 249 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -70 -1C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uacute -ENCODING 250 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -1C -70 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR ucircumflex -ENCODING 251 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -18 -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR udieresis -ENCODING 252 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR yacute -ENCODING 253 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -1C -70 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR thorn -ENCODING 254 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -C0 -C0 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -C0 -C0 -ENDCHAR -STARTCHAR ydieresis -ENCODING 255 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -44 -44 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR Amacron -ENCODING 256 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 12 1 0 -BITMAP -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR amacron -ENCODING 257 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 10 1 0 -BITMAP -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR Abreve -ENCODING 258 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -2100 -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR abreve -ENCODING 259 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -42 -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR Aogonek -ENCODING 260 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 12 1 -2 -BITMAP -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -0800 -0600 -ENDCHAR -STARTCHAR aogonek -ENCODING 261 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 10 1 -2 -BITMAP -7C -06 -06 -7E -C6 -C6 -CE -77 -10 -0C -ENDCHAR -STARTCHAR Cacute -ENCODING 262 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -ENDCHAR -STARTCHAR cacute -ENCODING 263 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -0E -38 -00 -3C -66 -C0 -C0 -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Ccircumflex -ENCODING 264 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -18 -2C -00 -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -ENDCHAR -STARTCHAR ccircumflex -ENCODING 265 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -30 -58 -00 -3C -66 -C0 -C0 -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Cdotaccent -ENCODING 266 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -18 -18 -00 -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -ENDCHAR -STARTCHAR cdotaccent -ENCODING 267 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -30 -30 -00 -3C -66 -C0 -C0 -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Ccaron -ENCODING 268 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -ENDCHAR -STARTCHAR ccaron -ENCODING 269 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -58 -30 -00 -3C -66 -C0 -C0 -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Dcaron -ENCODING 270 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 13 2 0 -BITMAP -2C00 -1800 -0000 -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -ENDCHAR -STARTCHAR dcaron -ENCODING 271 -SWIDTH 926 0 -DWIDTH 14 0 -BBX 12 11 1 0 -BITMAP -0330 -0330 -0310 -3F20 -6300 -C300 -C300 -C300 -C300 -6700 -3B00 -ENDCHAR -STARTCHAR Dcroat -ENCODING 272 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 11 10 0 0 -BITMAP -3F80 -30C0 -3060 -3060 -FC60 -3060 -3060 -3060 -30C0 -3F80 -ENDCHAR -STARTCHAR dcroat -ENCODING 273 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -03 -1F -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -ENDCHAR -STARTCHAR Emacron -ENCODING 274 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 12 2 0 -BITMAP -F0 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR emacron -ENCODING 275 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -3C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Ebreve -ENCODING 276 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -84 -78 -00 -7E -60 -60 -60 -7C -60 -60 -60 -60 -7E -ENDCHAR -STARTCHAR ebreve -ENCODING 277 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -42 -3C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Edotaccent -ENCODING 278 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -60 -60 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR edotaccent -ENCODING 279 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -18 -18 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Eogonek -ENCODING 280 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 12 2 -2 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -20 -18 -ENDCHAR -STARTCHAR eogonek -ENCODING 281 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 10 1 -2 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -20 -18 -ENDCHAR -STARTCHAR Ecaron -ENCODING 282 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -B0 -60 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR ecaron -ENCODING 283 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -2C -18 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR Gcircumflex -ENCODING 284 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -18 -2C -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR gcircumflex -ENCODING 285 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -18 -2C -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR Gbreve -ENCODING 286 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -42 -3C -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR gbreve -ENCODING 287 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -42 -3C -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR Gdotaccent -ENCODING 288 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -18 -18 -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR gdotaccent -ENCODING 289 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -18 -18 -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR Gcommaaccent -ENCODING 290 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 15 2 -5 -BITMAP -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR gcommaaccent -ENCODING 291 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 15 1 -2 -BITMAP -08 -10 -18 -18 -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR Hcircumflex -ENCODING 292 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -18 -2C -00 -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR hcircumflex -ENCODING 293 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -60 -B0 -00 -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR Hbar -ENCODING 294 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 10 2 0 -BITMAP -C3 -FF -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR hbar -ENCODING 295 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -C0 -F8 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR Itilde -ENCODING 296 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 5 13 1 0 -BITMAP -68 -B0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR itilde -ENCODING 297 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 11 0 0 -BITMAP -68 -B0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Imacron -ENCODING 298 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 12 1 0 -BITMAP -F0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR imacron -ENCODING 299 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 10 0 0 -BITMAP -F0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Ibreve -ENCODING 300 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 6 13 0 0 -BITMAP -84 -78 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR ibreve -ENCODING 301 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 6 11 -1 0 -BITMAP -84 -78 -00 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR Iogonek -ENCODING 302 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 3 12 2 -2 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -80 -60 -ENDCHAR -STARTCHAR iogonek -ENCODING 303 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 3 13 1 -2 -BITMAP -C0 -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -80 -60 -ENDCHAR -STARTCHAR Idotaccent -ENCODING 304 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 2 13 2 0 -BITMAP -C0 -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR dotlessi -ENCODING 305 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 8 1 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR IJ -ENCODING 306 -SWIDTH 844 0 -DWIDTH 12 0 -BBX 8 12 2 -2 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -03 -0E -ENDCHAR -STARTCHAR ij -ENCODING 307 -SWIDTH 704 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -C6 -C6 -00 -C6 -C6 -C6 -C6 -C6 -C6 -C6 -C6 -06 -1C -ENDCHAR -STARTCHAR Jcircumflex -ENCODING 308 -SWIDTH 501 0 -DWIDTH 6 0 -BBX 5 15 0 -2 -BITMAP -30 -58 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR jcircumflex -ENCODING 309 -SWIDTH 361 0 -DWIDTH 5 0 -BBX 5 13 0 -2 -BITMAP -30 -58 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR Kcommaaccent -ENCODING 310 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 15 2 -5 -BITMAP -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR kcommaaccent -ENCODING 311 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 16 1 -5 -BITMAP -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR kgreenlandic -ENCODING 312 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 8 1 0 -BITMAP -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -ENDCHAR -STARTCHAR Lacute -ENCODING 313 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -38 -E0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR lacute -ENCODING 314 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 14 0 0 -BITMAP -38 -E0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR Lcommaaccent -ENCODING 315 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 15 2 -5 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -00 -60 -60 -20 -40 -ENDCHAR -STARTCHAR lcommaaccent -ENCODING 316 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 16 1 -5 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -00 -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR Lcaron -ENCODING 317 -SWIDTH 854 0 -DWIDTH 13 0 -BBX 10 11 2 0 -BITMAP -00C0 -C0C0 -C040 -C080 -C000 -C000 -C000 -C000 -C000 -C000 -FC00 -ENDCHAR -STARTCHAR lcaron -ENCODING 318 -SWIDTH 608 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -CC -CC -C4 -C8 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Ldot -ENCODING 319 -SWIDTH 932 0 -DWIDTH 19 0 -BBX 13 10 2 0 -BITMAP -C000 -C000 -C000 -C000 -C000 -C018 -C018 -C000 -C000 -FC00 -ENDCHAR -STARTCHAR ldot -ENCODING 320 -SWIDTH 686 0 -DWIDTH 14 0 -BBX 9 11 1 0 -BITMAP -C000 -C000 -C000 -C000 -C000 -C000 -C180 -C180 -C000 -C000 -C000 -ENDCHAR -STARTCHAR Lslash -ENCODING 321 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 8 10 0 0 -BITMAP -30 -30 -30 -30 -3C -F0 -30 -30 -30 -3F -ENDCHAR -STARTCHAR lslash -ENCODING 322 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 6 11 0 0 -BITMAP -30 -30 -30 -30 -3C -F0 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR Nacute -ENCODING 323 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR nacute -ENCODING 324 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -0E -38 -00 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR Ncommaaccent -ENCODING 325 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 15 2 -5 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -00 -0C -0C -04 -08 -ENDCHAR -STARTCHAR ncommaaccent -ENCODING 326 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 13 1 -5 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR Ncaron -ENCODING 327 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -58 -30 -00 -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR ncaron -ENCODING 328 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -2C -18 -00 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR napostrophe -ENCODING 329 -SWIDTH 945 0 -DWIDTH 14 0 -BBX 12 11 1 0 -BITMAP -C000 -C000 -4000 -8DE0 -0E70 -0C30 -0C30 -0C30 -0C30 -0C30 -0C30 -ENDCHAR -STARTCHAR Eng -ENCODING 330 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 12 2 -2 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8F -8F -87 -87 -03 -0E -ENDCHAR -STARTCHAR eng -ENCODING 331 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -03 -0E -ENDCHAR -STARTCHAR Omacron -ENCODING 332 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 12 1 0 -BITMAP -1E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR omacron -ENCODING 333 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -3C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR Obreve -ENCODING 334 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -2100 -1E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR obreve -ENCODING 335 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -42 -3C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR Ohungarumlaut -ENCODING 336 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -1B00 -1200 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR ohungarumlaut -ENCODING 337 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -36 -24 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR OE -ENCODING 338 -SWIDTH 1102 0 -DWIDTH 15 0 -BBX 13 10 1 0 -BITMAP -3DF8 -6380 -C180 -C180 -C1F0 -C180 -C180 -C180 -6380 -3DF8 -ENDCHAR -STARTCHAR oe -ENCODING 339 -SWIDTH 990 0 -DWIDTH 15 0 -BBX 13 8 1 0 -BITMAP -3CF0 -6398 -C318 -C3F8 -C300 -C300 -6388 -3CF0 -ENDCHAR -STARTCHAR Racute -ENCODING 340 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR racute -ENCODING 341 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 11 2 0 -BITMAP -38 -E0 -00 -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Rcommaaccent -ENCODING 342 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 15 2 -5 -BITMAP -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR rcommaaccent -ENCODING 343 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 13 2 -5 -BITMAP -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -00 -60 -60 -20 -40 -ENDCHAR -STARTCHAR Rcaron -ENCODING 344 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR rcaron -ENCODING 345 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 11 2 0 -BITMAP -B0 -60 -00 -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR Sacute -ENCODING 346 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -1C -70 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR sacute -ENCODING 347 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -1C -70 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR Scircumflex -ENCODING 348 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -30 -58 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR scircumflex -ENCODING 349 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -60 -B0 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR Scedilla -ENCODING 350 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 12 1 -2 -BITMAP -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -08 -30 -ENDCHAR -STARTCHAR scedilla -ENCODING 351 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 10 1 -2 -BITMAP -7C -C0 -C0 -F0 -3C -0C -0C -F8 -10 -60 -ENDCHAR -STARTCHAR Scaron -ENCODING 352 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -2C -18 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR scaron -ENCODING 353 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -58 -30 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR Tcommaaccent -ENCODING 354 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -08 -30 -ENDCHAR -STARTCHAR tcommaaccent -ENCODING 355 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 12 1 -2 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -20 -C0 -ENDCHAR -STARTCHAR Tcaron -ENCODING 356 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -2C -18 -00 -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR tcaron -ENCODING 357 -SWIDTH 679 0 -DWIDTH 11 0 -BBX 9 11 1 0 -BITMAP -0180 -6180 -6080 -F900 -6000 -6000 -6000 -6000 -6000 -6000 -3800 -ENDCHAR -STARTCHAR Tbar -ENCODING 358 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -FF -18 -18 -18 -3E -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR tbar -ENCODING 359 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 10 1 0 -BITMAP -60 -60 -F8 -60 -60 -F8 -60 -60 -60 -38 -ENDCHAR -STARTCHAR Utilde -ENCODING 360 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -1A -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR utilde -ENCODING 361 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -1A -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Umacron -ENCODING 362 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 12 2 0 -BITMAP -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR umacron -ENCODING 363 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Ubreve -ENCODING 364 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -42 -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR ubreve -ENCODING 365 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -42 -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Uring -ENCODING 366 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 14 2 0 -BITMAP -18 -2C -18 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uring -ENCODING 367 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 12 1 0 -BITMAP -18 -2C -18 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Uhungarumlaut -ENCODING 368 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -36 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uhungarumlaut -ENCODING 369 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -36 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Uogonek -ENCODING 370 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 12 2 -2 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -10 -0C -ENDCHAR -STARTCHAR uogonek -ENCODING 371 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -10 -0C -ENDCHAR -STARTCHAR Wcircumflex -ENCODING 372 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -0C00 -1600 -0000 -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR wcircumflex -ENCODING 373 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 0 -BITMAP -0C00 -1600 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR Ycircumflex -ENCODING 374 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -18 -2C -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR ycircumflex -ENCODING 375 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -30 -58 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR Ydieresis -ENCODING 376 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -24 -24 -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR Zacute -ENCODING 377 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -0E -38 -00 -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR zacute -ENCODING 378 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -0E -38 -00 -FE -06 -0C -18 -30 -60 -C0 -FE -ENDCHAR -STARTCHAR Zdotaccent -ENCODING 379 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -18 -18 -00 -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR zdotaccent -ENCODING 380 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -18 -18 -00 -FE -06 -0C -18 -30 -60 -C0 -FE -ENDCHAR -STARTCHAR Zcaron -ENCODING 381 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -2C -18 -00 -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR zcaron -ENCODING 382 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -2C -18 -00 -FE -06 -0C -18 -30 -60 -C0 -FE -ENDCHAR -STARTCHAR uni0186 -ENCODING 390 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -7C -C6 -03 -03 -03 -03 -03 -03 -C6 -7C -ENDCHAR -STARTCHAR uni0189 -ENCODING 393 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 11 10 0 0 -BITMAP -3F80 -30C0 -3060 -3060 -FC60 -3060 -3060 -3060 -30C0 -3F80 -ENDCHAR -STARTCHAR uni018E -ENCODING 398 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -FC -0C -0C -0C -0C -7C -0C -0C -0C -FC -ENDCHAR -STARTCHAR florin -ENCODING 402 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 11 2 -1 -BITMAP -1C -32 -30 -30 -FC -60 -60 -60 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni0197 -ENCODING 407 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 5 10 1 0 -BITMAP -60 -60 -60 -60 -F8 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni019A -ENCODING 410 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 11 0 0 -BITMAP -60 -60 -60 -60 -60 -F8 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni019D -ENCODING 413 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 12 0 -2 -BITMAP -3840 -3840 -2C40 -2C40 -2640 -2640 -3340 -3140 -31C0 -31C0 -3000 -E000 -ENDCHAR -STARTCHAR uni019F -ENCODING 415 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 10 1 0 -BITMAP -3F00 -6180 -C0C0 -C0C0 -FFC0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR Ohorn -ENCODING 416 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 11 10 1 0 -BITMAP -3F60 -61E0 -C0E0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR ohorn -ENCODING 417 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 10 8 1 0 -BITMAP -3CC0 -66C0 -C340 -C380 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni01A7 -ENCODING 423 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -7C -C6 -06 -0E -3C -78 -E0 -C0 -C6 -7C -ENDCHAR -STARTCHAR uni01A8 -ENCODING 424 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 8 1 0 -BITMAP -F8 -0C -0C -3C -F0 -C0 -C0 -7C -ENDCHAR -STARTCHAR uni01AE -ENCODING 430 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -18 -0E -ENDCHAR -STARTCHAR Uhorn -ENCODING 431 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 10 2 0 -BITMAP -C3C0 -C3C0 -C340 -C380 -C300 -C300 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uhorn -ENCODING 432 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 10 8 1 0 -BITMAP -C3C0 -C3C0 -C340 -C380 -C300 -C300 -E700 -7B00 -ENDCHAR -STARTCHAR uni01B5 -ENCODING 437 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -FE -06 -0C -1C -7C -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR uni01B6 -ENCODING 438 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -FE -06 -0C -7C -30 -60 -C0 -FE -ENDCHAR -STARTCHAR uni01BB -ENCODING 443 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 10 1 0 -BITMAP -7E -C7 -03 -03 -FF -0C -18 -60 -FF -FF -ENDCHAR -STARTCHAR uni01BC -ENCODING 444 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 10 2 0 -BITMAP -FC -FC -80 -80 -FC -0E -06 -06 -CC -78 -ENDCHAR -STARTCHAR uni01C0 -ENCODING 448 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 12 1 -1 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni01C2 -ENCODING 450 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 12 1 -1 -BITMAP -18 -18 -18 -18 -18 -FE -18 -FE -18 -18 -18 -18 -ENDCHAR -STARTCHAR uni01C3 -ENCODING 451 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 10 1 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -80 -80 -00 -C0 -C0 -ENDCHAR -STARTCHAR uni01CD -ENCODING 461 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1600 -0C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni01CE -ENCODING 462 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -2C -18 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni01CF -ENCODING 463 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 4 13 1 0 -BITMAP -B0 -60 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni01D0 -ENCODING 464 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 11 0 0 -BITMAP -B0 -60 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni01D1 -ENCODING 465 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -1600 -0C00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni01D2 -ENCODING 466 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -2C -18 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni01D3 -ENCODING 467 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni01D4 -ENCODING 468 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -2C -18 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni01D5 -ENCODING 469 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 15 2 0 -BITMAP -3C -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -64 -3C -ENDCHAR -STARTCHAR uni01D6 -ENCODING 470 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -3C -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni01D7 -ENCODING 471 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 16 2 0 -BITMAP -0E -38 -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -64 -3C -ENDCHAR -STARTCHAR uni01D8 -ENCODING 472 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni01D9 -ENCODING 473 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 16 2 0 -BITMAP -2C -18 -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -64 -3C -ENDCHAR -STARTCHAR uni01DA -ENCODING 474 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -2C -18 -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni01DB -ENCODING 475 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 16 2 0 -BITMAP -70 -1C -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -64 -3C -ENDCHAR -STARTCHAR uni01DC -ENCODING 476 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -70 -1C -00 -24 -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni01DD -ENCODING 477 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -78 -8C -06 -06 -FE -C6 -CC -78 -ENDCHAR -STARTCHAR uni01DE -ENCODING 478 -SWIDTH 773 0 -DWIDTH 10 0 -BBX 8 15 1 0 -BITMAP -3C -00 -24 -24 -00 -18 -18 -2C -2C -66 -46 -FE -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni01DF -ENCODING 479 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 13 1 0 -BITMAP -3C -00 -24 -24 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni01E0 -ENCODING 480 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 15 1 0 -BITMAP -1E00 -0000 -0C00 -0C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni01E1 -ENCODING 481 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 13 1 0 -BITMAP -3C -00 -18 -18 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni01E2 -ENCODING 482 -SWIDTH 997 0 -DWIDTH 13 0 -BBX 11 12 1 0 -BITMAP -0F00 -0000 -1FE0 -1600 -2600 -2600 -67C0 -4600 -7E00 -C600 -C600 -C7E0 -ENDCHAR -STARTCHAR uni01E3 -ENCODING 483 -SWIDTH 913 0 -DWIDTH 14 0 -BBX 12 10 1 0 -BITMAP -0780 -0000 -7DE0 -0730 -0630 -7FF0 -C600 -C600 -C710 -79E0 -ENDCHAR -STARTCHAR uni01E4 -ENCODING 484 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 9 10 2 0 -BITMAP -3E00 -6300 -C000 -C000 -C000 -C300 -CF80 -C300 -6300 -3F00 -ENDCHAR -STARTCHAR uni01E5 -ENCODING 485 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -3F -63 -C3 -C3 -C3 -67 -3B -FF -C6 -7C -ENDCHAR -STARTCHAR Gcaron -ENCODING 486 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR gcaron -ENCODING 487 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -2C -18 -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR uni01E8 -ENCODING 488 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni01E9 -ENCODING 489 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -B0 -60 -00 -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -ENDCHAR -STARTCHAR uni01EA -ENCODING 490 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 12 1 -2 -BITMAP -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0800 -0600 -ENDCHAR -STARTCHAR uni01EB -ENCODING 491 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -3C -66 -C3 -C3 -C3 -C3 -66 -3C -10 -0C -ENDCHAR -STARTCHAR uni01EC -ENCODING 492 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 14 1 -2 -BITMAP -1E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0800 -0600 -ENDCHAR -STARTCHAR uni01ED -ENCODING 493 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -3C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -10 -0C -ENDCHAR -STARTCHAR uni01F0 -ENCODING 496 -SWIDTH 361 0 -DWIDTH 5 0 -BBX 5 13 0 -2 -BITMAP -58 -30 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -E0 -ENDCHAR -STARTCHAR uni01F4 -ENCODING 500 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR uni01F5 -ENCODING 501 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -07 -1C -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR uni01F8 -ENCODING 504 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -E0 -38 -00 -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR uni01F9 -ENCODING 505 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -70 -1C -00 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR Aringacute -ENCODING 506 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -0700 -1C00 -0000 -1C00 -2600 -1C00 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR aringacute -ENCODING 507 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -18 -2C -18 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR AEacute -ENCODING 508 -SWIDTH 997 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -0380 -0E00 -0000 -1FE0 -1600 -2600 -2600 -67C0 -4600 -7E00 -C600 -C600 -C7E0 -ENDCHAR -STARTCHAR aeacute -ENCODING 509 -SWIDTH 913 0 -DWIDTH 14 0 -BBX 12 11 1 0 -BITMAP -01C0 -0700 -0000 -7DE0 -0730 -0630 -7FF0 -C600 -C600 -C710 -79E0 -ENDCHAR -STARTCHAR Oslashacute -ENCODING 510 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 -1 -BITMAP -0380 -0E00 -0000 -0040 -3F40 -6180 -C2C0 -C2C0 -C4C0 -C8C0 -D0C0 -D0C0 -6180 -BF00 -8000 -ENDCHAR -STARTCHAR oslashacute -ENCODING 511 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 -1 -BITMAP -07 -1C -00 -01 -3D -66 -CB -CB -D3 -D3 -66 -BC -80 -ENDCHAR -STARTCHAR uni0200 -ENCODING 512 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -3600 -1200 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni0201 -ENCODING 513 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -36 -12 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni0202 -ENCODING 514 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1E00 -2100 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni0203 -ENCODING 515 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -3C -42 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni0204 -ENCODING 516 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -D8 -48 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni0205 -ENCODING 517 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -6C -24 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni0206 -ENCODING 518 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -78 -84 -00 -7E -60 -60 -60 -7C -60 -60 -60 -60 -7E -ENDCHAR -STARTCHAR uni0207 -ENCODING 519 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -3C -42 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni0208 -ENCODING 520 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 5 13 0 0 -BITMAP -D8 -48 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR uni0209 -ENCODING 521 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 11 -1 0 -BITMAP -D8 -48 -00 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR uni020A -ENCODING 522 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 6 13 0 0 -BITMAP -78 -84 -00 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR uni020B -ENCODING 523 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 6 11 -1 0 -BITMAP -78 -84 -00 -30 -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR uni020C -ENCODING 524 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -3600 -1200 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni020D -ENCODING 525 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -6C -24 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni020E -ENCODING 526 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -1E00 -2100 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni020F -ENCODING 527 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -3C -42 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0210 -ENCODING 528 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -6C -24 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni0211 -ENCODING 529 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -D8 -48 -00 -6C -6C -70 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni0212 -ENCODING 530 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -3C -42 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni0213 -ENCODING 531 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -78 -84 -00 -6C -6C -70 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni0214 -ENCODING 532 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -6C -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0215 -ENCODING 533 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -6C -24 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni0216 -ENCODING 534 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -3C -42 -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0217 -ENCODING 535 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -3C -42 -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR Scommaaccent -ENCODING 536 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 15 1 -5 -BITMAP -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR scommaaccent -ENCODING 537 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 13 1 -5 -BITMAP -7C -C0 -C0 -F0 -3C -0C -0C -F8 -00 -30 -30 -10 -20 -ENDCHAR -STARTCHAR Tcommaaccent -ENCODING 538 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 15 1 -5 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -00 -18 -18 -08 -10 -ENDCHAR -STARTCHAR tcommaaccent -ENCODING 539 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 15 1 -5 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -00 -30 -30 -10 -20 -ENDCHAR -STARTCHAR uni021E -ENCODING 542 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -2C -18 -00 -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni021F -ENCODING 543 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -B0 -60 -00 -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni0226 -ENCODING 550 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -0C00 -0C00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni0227 -ENCODING 551 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 0 -BITMAP -18 -18 -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni0228 -ENCODING 552 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 12 2 -2 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -20 -C0 -ENDCHAR -STARTCHAR uni0229 -ENCODING 553 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 10 1 -2 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -10 -60 -ENDCHAR -STARTCHAR uni022A -ENCODING 554 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 0 -BITMAP -1E00 -0000 -2100 -2100 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni022B -ENCODING 555 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -3C -00 -24 -24 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni022C -ENCODING 556 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 0 -BITMAP -1E00 -0000 -0D00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni022D -ENCODING 557 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -3C -00 -34 -58 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni022E -ENCODING 558 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 0 -BITMAP -0C00 -0C00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni022F -ENCODING 559 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -18 -18 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0230 -ENCODING 560 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 0 -BITMAP -1E00 -0000 -0C00 -0C00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni0231 -ENCODING 561 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -3C -00 -18 -18 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0232 -ENCODING 562 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 12 1 0 -BITMAP -3C -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR uni0233 -ENCODING 563 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 12 1 -2 -BITMAP -3C -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR uni0250 -ENCODING 592 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 8 1 0 -BITMAP -EE -73 -63 -63 -7E -60 -60 -3E -ENDCHAR -STARTCHAR uni0254 -ENCODING 596 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -78 -CC -06 -06 -06 -06 -8C -78 -ENDCHAR -STARTCHAR uni0258 -ENCODING 600 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -78 -CC -C6 -FE -06 -06 -8C -78 -ENDCHAR -STARTCHAR uni0259 -ENCODING 601 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -78 -8C -06 -06 -FE -C6 -CC -78 -ENDCHAR -STARTCHAR uni025F -ENCODING 607 -SWIDTH 461 0 -DWIDTH 7 0 -BBX 7 11 0 -3 -BITMAP -18 -18 -18 -18 -18 -18 -18 -FE -18 -18 -F0 -ENDCHAR -STARTCHAR uni0265 -ENCODING 613 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -03 -03 -03 -ENDCHAR -STARTCHAR uni0275 -ENCODING 629 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -3C -66 -C3 -FF -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni0279 -ENCODING 633 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 8 2 0 -BITMAP -18 -18 -18 -18 -18 -38 -D8 -D8 -ENDCHAR -STARTCHAR uni0287 -ENCODING 647 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 10 1 0 -BITMAP -E0 -30 -30 -30 -30 -30 -30 -F8 -30 -30 -ENDCHAR -STARTCHAR uni0288 -ENCODING 648 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 12 1 -2 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -60 -60 -38 -ENDCHAR -STARTCHAR uni0289 -ENCODING 649 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 8 1 0 -BITMAP -C3 -C3 -C3 -FF -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni028C -ENCODING 652 -SWIDTH 663 0 -DWIDTH 9 0 -BBX 7 8 1 0 -BITMAP -38 -38 -2C -4C -C6 -C6 -C6 -C6 -ENDCHAR -STARTCHAR uni028D -ENCODING 653 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 8 1 0 -BITMAP -3180 -3180 -3BC0 -6AC0 -6EC0 -C460 -C460 -C060 -ENDCHAR -STARTCHAR uni028E -ENCODING 654 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 10 1 0 -BITMAP -0E -0C -18 -38 -2C -6C -C6 -C6 -C6 -C6 -ENDCHAR -STARTCHAR uni029E -ENCODING 670 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 11 1 -3 -BITMAP -E3 -63 -33 -1B -0F -1B -33 -63 -03 -03 -03 -ENDCHAR -STARTCHAR uni02BB -ENCODING 699 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -40 -80 -C0 -C0 -ENDCHAR -STARTCHAR afii57929 -ENCODING 700 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR afii64937 -ENCODING 701 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -80 -40 -ENDCHAR -STARTCHAR circumflex -ENCODING 710 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 2 3 9 -BITMAP -60 -B0 -ENDCHAR -STARTCHAR caron -ENCODING 711 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 2 3 9 -BITMAP -B0 -60 -ENDCHAR -STARTCHAR uni02C8 -ENCODING 712 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -80 -80 -ENDCHAR -STARTCHAR macron -ENCODING 713 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 1 3 9 -BITMAP -F0 -ENDCHAR -STARTCHAR uni02CA -ENCODING 714 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 9 -BITMAP -38 -E0 -ENDCHAR -STARTCHAR uni02CB -ENCODING 715 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 2 9 -BITMAP -E0 -38 -ENDCHAR -STARTCHAR uni02CD -ENCODING 717 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 1 3 -2 -BITMAP -F0 -ENDCHAR -STARTCHAR uni02CE -ENCODING 718 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 2 -3 -BITMAP -E0 -38 -ENDCHAR -STARTCHAR uni02CF -ENCODING 719 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 -3 -BITMAP -38 -E0 -ENDCHAR -STARTCHAR breve -ENCODING 728 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 6 2 2 9 -BITMAP -84 -78 -ENDCHAR -STARTCHAR dotaccent -ENCODING 729 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 2 2 4 9 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR ring -ENCODING 730 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 4 3 3 8 -BITMAP -60 -B0 -60 -ENDCHAR -STARTCHAR ogonek -ENCODING 731 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 3 2 5 -2 -BITMAP -80 -60 -ENDCHAR -STARTCHAR tilde -ENCODING 732 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 9 -BITMAP -68 -B0 -ENDCHAR -STARTCHAR hungarumlaut -ENCODING 733 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 9 -BITMAP -D8 -90 -ENDCHAR -STARTCHAR uni02EE -ENCODING 750 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 7 -BITMAP -D8 -D8 -48 -90 -ENDCHAR -STARTCHAR uni037E -ENCODING 894 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 9 1 -2 -BITMAP -C0 -C0 -00 -00 -00 -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR tonos -ENCODING 900 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 2 3 9 -BITMAP -38 -E0 -ENDCHAR -STARTCHAR dieresistonos -ENCODING 901 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 5 5 3 9 -BITMAP -38 -E0 -00 -90 -90 -ENDCHAR -STARTCHAR anoteleia -ENCODING 903 -SWIDTH 343 0 -DWIDTH 10 0 -BBX 2 2 4 3 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR mu -ENCODING 956 -SWIDTH 699 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -FB -C0 -C0 -ENDCHAR -STARTCHAR uni1E00 -ENCODING 7680 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 14 1 -4 -BITMAP -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -0000 -0C00 -1600 -0C00 -ENDCHAR -STARTCHAR uni1E01 -ENCODING 7681 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 12 1 -4 -BITMAP -7C -06 -06 -7E -C6 -C6 -CE -77 -00 -18 -2C -18 -ENDCHAR -STARTCHAR uni1E02 -ENCODING 7682 -SWIDTH 669 0 -DWIDTH 10 0 -BBX 7 13 2 0 -BITMAP -30 -30 -00 -FC -C6 -C6 -CC -F0 -CC -C6 -C6 -C6 -FC -ENDCHAR -STARTCHAR uni1E03 -ENCODING 7683 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -60 -60 -00 -C0 -C0 -C0 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -ENDCHAR -STARTCHAR uni1E04 -ENCODING 7684 -SWIDTH 669 0 -DWIDTH 10 0 -BBX 7 13 2 -3 -BITMAP -FC -C6 -C6 -CC -F0 -CC -C6 -C6 -C6 -FC -00 -30 -30 -ENDCHAR -STARTCHAR uni1E05 -ENCODING 7685 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -C0 -C0 -C0 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -00 -18 -18 -ENDCHAR -STARTCHAR uni1E06 -ENCODING 7686 -SWIDTH 669 0 -DWIDTH 10 0 -BBX 7 12 2 -2 -BITMAP -FC -C6 -C6 -CC -F0 -CC -C6 -C6 -C6 -FC -00 -78 -ENDCHAR -STARTCHAR uni1E07 -ENCODING 7687 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -C0 -C0 -C0 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -00 -3C -ENDCHAR -STARTCHAR uni1E08 -ENCODING 7688 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 8 15 2 -2 -BITMAP -0E -38 -00 -3E -63 -C0 -C0 -C0 -C0 -C0 -C0 -63 -3E -08 -30 -ENDCHAR -STARTCHAR uni1E09 -ENCODING 7689 -SWIDTH 545 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -0E -38 -00 -3C -66 -C0 -C0 -C0 -C0 -62 -3C -10 -60 -ENDCHAR -STARTCHAR uni1E0A -ENCODING 7690 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 13 2 0 -BITMAP -1800 -1800 -0000 -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -ENDCHAR -STARTCHAR uni1E0B -ENCODING 7691 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -06 -06 -00 -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -ENDCHAR -STARTCHAR uni1E0C -ENCODING 7692 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 13 2 -3 -BITMAP -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1E0D -ENCODING 7693 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -00 -18 -18 -ENDCHAR -STARTCHAR uni1E0E -ENCODING 7694 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 12 2 -2 -BITMAP -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -0000 -3C00 -ENDCHAR -STARTCHAR uni1E0F -ENCODING 7695 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -00 -3C -ENDCHAR -STARTCHAR uni1E10 -ENCODING 7696 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 12 2 -2 -BITMAP -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -0800 -3000 -ENDCHAR -STARTCHAR uni1E11 -ENCODING 7697 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -08 -30 -ENDCHAR -STARTCHAR uni1E12 -ENCODING 7698 -SWIDTH 819 0 -DWIDTH 12 0 -BBX 9 13 2 -3 -BITMAP -FE00 -C300 -C180 -C180 -C180 -C180 -C180 -C180 -C300 -FE00 -0000 -1800 -2C00 -ENDCHAR -STARTCHAR uni1E13 -ENCODING 7699 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -03 -03 -03 -3F -63 -C3 -C3 -C3 -C3 -67 -3B -00 -18 -2C -ENDCHAR -STARTCHAR uni1E14 -ENCODING 7700 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 15 1 0 -BITMAP -E0 -38 -00 -78 -00 -7E -60 -60 -60 -7C -60 -60 -60 -60 -7E -ENDCHAR -STARTCHAR uni1E15 -ENCODING 7701 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -70 -1C -00 -3C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1E16 -ENCODING 7702 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 15 2 0 -BITMAP -1C -70 -00 -F0 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni1E17 -ENCODING 7703 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -0E -38 -00 -3C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1E18 -ENCODING 7704 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 -3 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -00 -60 -B0 -ENDCHAR -STARTCHAR uni1E19 -ENCODING 7705 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 -3 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -00 -30 -58 -ENDCHAR -STARTCHAR uni1E1A -ENCODING 7706 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 -3 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -00 -68 -B0 -ENDCHAR -STARTCHAR uni1E1B -ENCODING 7707 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 -3 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -00 -34 -58 -ENDCHAR -STARTCHAR uni1E1C -ENCODING 7708 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 15 1 -2 -BITMAP -84 -78 -00 -7E -60 -60 -60 -7C -60 -60 -60 -60 -7E -10 -60 -ENDCHAR -STARTCHAR uni1E1D -ENCODING 7709 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -42 -3C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -10 -60 -ENDCHAR -STARTCHAR uni1E1E -ENCODING 7710 -SWIDTH 602 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -60 -60 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni1E1F -ENCODING 7711 -SWIDTH 461 0 -DWIDTH 7 0 -BBX 7 14 0 0 -BITMAP -18 -18 -00 -1E -30 -30 -FE -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR uni1E20 -ENCODING 7712 -SWIDTH 759 0 -DWIDTH 11 0 -BBX 8 12 2 0 -BITMAP -3C -00 -3E -63 -C0 -C0 -C0 -C3 -C3 -C3 -63 -3F -ENDCHAR -STARTCHAR uni1E21 -ENCODING 7713 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -3C -00 -3F -63 -C3 -C3 -C3 -67 -3B -03 -C6 -7C -ENDCHAR -STARTCHAR uni1E22 -ENCODING 7714 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -18 -18 -00 -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni1E23 -ENCODING 7715 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -60 -60 -00 -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni1E24 -ENCODING 7716 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E25 -ENCODING 7717 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E26 -ENCODING 7718 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -24 -24 -00 -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni1E27 -ENCODING 7719 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -90 -90 -00 -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni1E28 -ENCODING 7720 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 12 2 -2 -BITMAP -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -08 -30 -ENDCHAR -STARTCHAR uni1E29 -ENCODING 7721 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -08 -30 -ENDCHAR -STARTCHAR uni1E2A -ENCODING 7722 -SWIDTH 813 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -FF -C3 -C3 -C3 -C3 -C3 -00 -42 -3C -ENDCHAR -STARTCHAR uni1E2B -ENCODING 7723 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -42 -3C -ENDCHAR -STARTCHAR uni1E2C -ENCODING 7724 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 5 13 0 -3 -BITMAP -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -00 -68 -B0 -ENDCHAR -STARTCHAR uni1E2D -ENCODING 7725 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 14 -1 -3 -BITMAP -30 -30 -00 -30 -30 -30 -30 -30 -30 -30 -30 -00 -68 -B0 -ENDCHAR -STARTCHAR uni1E2E -ENCODING 7726 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 5 16 1 0 -BITMAP -38 -E0 -00 -90 -90 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni1E2F -ENCODING 7727 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 5 14 0 0 -BITMAP -38 -E0 -00 -90 -90 -00 -60 -60 -60 -60 -60 -60 -60 -60 -ENDCHAR -STARTCHAR uni1E30 -ENCODING 7728 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -0E -38 -00 -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni1E31 -ENCODING 7729 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -38 -E0 -00 -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -ENDCHAR -STARTCHAR uni1E32 -ENCODING 7730 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 13 2 -3 -BITMAP -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E33 -ENCODING 7731 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 14 1 -3 -BITMAP -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E34 -ENCODING 7732 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 12 2 -2 -BITMAP -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -00 -3C -ENDCHAR -STARTCHAR uni1E35 -ENCODING 7733 -SWIDTH 681 0 -DWIDTH 9 0 -BBX 8 13 1 -2 -BITMAP -C0 -C0 -C0 -C6 -CC -D8 -F0 -D8 -CC -C6 -C7 -00 -3C -ENDCHAR -STARTCHAR uni1E36 -ENCODING 7734 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 13 2 -3 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -00 -60 -60 -ENDCHAR -STARTCHAR uni1E37 -ENCODING 7735 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 14 1 -3 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -00 -C0 -C0 -ENDCHAR -STARTCHAR uni1E38 -ENCODING 7736 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 15 2 -3 -BITMAP -F0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -00 -60 -60 -ENDCHAR -STARTCHAR uni1E39 -ENCODING 7737 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 16 0 -3 -BITMAP -F0 -00 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -00 -60 -60 -ENDCHAR -STARTCHAR uni1E3A -ENCODING 7738 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 12 2 -2 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -00 -F0 -ENDCHAR -STARTCHAR uni1E3B -ENCODING 7739 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 13 0 -2 -BITMAP -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -00 -F0 -ENDCHAR -STARTCHAR uni1E3C -ENCODING 7740 -SWIDTH 620 0 -DWIDTH 9 0 -BBX 6 13 2 -3 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -FC -00 -60 -B0 -ENDCHAR -STARTCHAR uni1E3D -ENCODING 7741 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 4 14 0 -3 -BITMAP -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -60 -00 -60 -B0 -ENDCHAR -STARTCHAR uni1E3E -ENCODING 7742 -SWIDTH 940 0 -DWIDTH 15 0 -BBX 11 13 2 0 -BITMAP -0380 -0E00 -0000 -E0E0 -E0E0 -B160 -B160 -B160 -9A60 -9A60 -8C60 -8C60 -8060 -ENDCHAR -STARTCHAR uni1E3F -ENCODING 7743 -SWIDTH 1006 0 -DWIDTH 14 0 -BBX 12 11 1 0 -BITMAP -0380 -0E00 -0000 -DDE0 -EF70 -C630 -C630 -C630 -C630 -C630 -C630 -ENDCHAR -STARTCHAR uni1E40 -ENCODING 7744 -SWIDTH 940 0 -DWIDTH 15 0 -BBX 11 13 2 0 -BITMAP -0600 -0600 -0000 -E0E0 -E0E0 -B160 -B160 -B160 -9A60 -9A60 -8C60 -8C60 -8060 -ENDCHAR -STARTCHAR uni1E41 -ENCODING 7745 -SWIDTH 1006 0 -DWIDTH 14 0 -BBX 12 11 1 0 -BITMAP -0600 -0600 -0000 -DDE0 -EF70 -C630 -C630 -C630 -C630 -C630 -C630 -ENDCHAR -STARTCHAR uni1E42 -ENCODING 7746 -SWIDTH 940 0 -DWIDTH 15 0 -BBX 11 13 2 -3 -BITMAP -E0E0 -E0E0 -B160 -B160 -B160 -9A60 -9A60 -8C60 -8C60 -8060 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E43 -ENCODING 7747 -SWIDTH 1006 0 -DWIDTH 14 0 -BBX 12 11 1 -3 -BITMAP -DDE0 -EF70 -C630 -C630 -C630 -C630 -C630 -C630 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E44 -ENCODING 7748 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 0 -BITMAP -30 -30 -00 -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -ENDCHAR -STARTCHAR uni1E45 -ENCODING 7749 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 0 -BITMAP -18 -18 -00 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -ENDCHAR -STARTCHAR uni1E46 -ENCODING 7750 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -00 -0C -0C -ENDCHAR -STARTCHAR uni1E47 -ENCODING 7751 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E48 -ENCODING 7752 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 12 2 -2 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -00 -1E -ENDCHAR -STARTCHAR uni1E49 -ENCODING 7753 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 10 1 -2 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -3C -ENDCHAR -STARTCHAR uni1E4A -ENCODING 7754 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -E1 -E1 -B1 -B1 -99 -99 -8D -8D -87 -87 -00 -0C -16 -ENDCHAR -STARTCHAR uni1E4B -ENCODING 7755 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -18 -2C -ENDCHAR -STARTCHAR uni1E4C -ENCODING 7756 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 0 -BITMAP -0700 -1C00 -0000 -0D00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1E4D -ENCODING 7757 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -34 -58 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E4E -ENCODING 7758 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 0 -BITMAP -1200 -1200 -0000 -0D00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1E4F -ENCODING 7759 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -24 -24 -00 -34 -58 -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E50 -ENCODING 7760 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 0 -BITMAP -3800 -0E00 -0000 -1E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1E51 -ENCODING 7761 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -70 -1C -00 -3C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E52 -ENCODING 7762 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 15 1 0 -BITMAP -0700 -1C00 -0000 -1E00 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1E53 -ENCODING 7763 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -0E -38 -00 -3C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E54 -ENCODING 7764 -SWIDTH 657 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -1C -70 -00 -F8 -CC -CC -CC -CC -F8 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni1E55 -ENCODING 7765 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -0E -38 -00 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -C0 -C0 -ENDCHAR -STARTCHAR uni1E56 -ENCODING 7766 -SWIDTH 657 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -30 -30 -00 -F8 -CC -CC -CC -CC -F8 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni1E57 -ENCODING 7767 -SWIDTH 696 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -18 -18 -00 -DC -E6 -C3 -C3 -C3 -C3 -C6 -FC -C0 -C0 -ENDCHAR -STARTCHAR uni1E58 -ENCODING 7768 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 0 -BITMAP -18 -18 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni1E59 -ENCODING 7769 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 11 2 0 -BITMAP -60 -60 -00 -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni1E5A -ENCODING 7770 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 13 2 -3 -BITMAP -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E5B -ENCODING 7771 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 11 2 -3 -BITMAP -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -00 -60 -60 -ENDCHAR -STARTCHAR uni1E5C -ENCODING 7772 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 15 2 -3 -BITMAP -78 -00 -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E5D -ENCODING 7773 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 13 2 -3 -BITMAP -F0 -00 -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -00 -60 -60 -ENDCHAR -STARTCHAR uni1E5E -ENCODING 7774 -SWIDTH 734 0 -DWIDTH 11 0 -BBX 8 12 2 -2 -BITMAP -FC -C6 -C6 -C4 -CC -F8 -CC -C6 -C3 -C3 -00 -3C -ENDCHAR -STARTCHAR uni1E5F -ENCODING 7775 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 5 10 2 -2 -BITMAP -D8 -D8 -E0 -C0 -C0 -C0 -C0 -C0 -00 -F0 -ENDCHAR -STARTCHAR uni1E60 -ENCODING 7776 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -30 -30 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR uni1E61 -ENCODING 7777 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 11 1 0 -BITMAP -30 -30 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR uni1E62 -ENCODING 7778 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 13 1 -3 -BITMAP -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -00 -18 -18 -ENDCHAR -STARTCHAR uni1E63 -ENCODING 7779 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 11 1 -3 -BITMAP -7C -C0 -C0 -F0 -3C -0C -0C -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E64 -ENCODING 7780 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 16 1 0 -BITMAP -18 -18 -00 -1C -70 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR uni1E65 -ENCODING 7781 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 14 1 0 -BITMAP -30 -30 -00 -1C -70 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR uni1E66 -ENCODING 7782 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 16 1 0 -BITMAP -18 -18 -00 -2C -18 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -ENDCHAR -STARTCHAR uni1E67 -ENCODING 7783 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 14 1 0 -BITMAP -30 -30 -00 -58 -30 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -ENDCHAR -STARTCHAR uni1E68 -ENCODING 7784 -SWIDTH 594 0 -DWIDTH 9 0 -BBX 7 16 1 -3 -BITMAP -30 -30 -00 -7C -C6 -C0 -E0 -78 -3C -0E -06 -C6 -7C -00 -18 -18 -ENDCHAR -STARTCHAR uni1E69 -ENCODING 7785 -SWIDTH 622 0 -DWIDTH 8 0 -BBX 6 14 1 -3 -BITMAP -30 -30 -00 -7C -C0 -C0 -F0 -3C -0C -0C -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E6A -ENCODING 7786 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -18 -18 -00 -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR uni1E6B -ENCODING 7787 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 13 1 0 -BITMAP -60 -60 -00 -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -ENDCHAR -STARTCHAR uni1E6C -ENCODING 7788 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 13 1 -3 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -00 -18 -18 -ENDCHAR -STARTCHAR uni1E6D -ENCODING 7789 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 13 1 -3 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E6E -ENCODING 7790 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -00 -3C -ENDCHAR -STARTCHAR uni1E6F -ENCODING 7791 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 12 1 -2 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -00 -78 -ENDCHAR -STARTCHAR uni1E70 -ENCODING 7792 -SWIDTH 735 0 -DWIDTH 10 0 -BBX 8 13 1 -3 -BITMAP -FF -18 -18 -18 -18 -18 -18 -18 -18 -18 -00 -18 -2C -ENDCHAR -STARTCHAR uni1E71 -ENCODING 7793 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 13 1 -3 -BITMAP -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -00 -30 -58 -ENDCHAR -STARTCHAR uni1E72 -ENCODING 7794 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -00 -24 -24 -ENDCHAR -STARTCHAR uni1E73 -ENCODING 7795 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -00 -24 -24 -ENDCHAR -STARTCHAR uni1E74 -ENCODING 7796 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -00 -34 -58 -ENDCHAR -STARTCHAR uni1E75 -ENCODING 7797 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -00 -34 -58 -ENDCHAR -STARTCHAR uni1E76 -ENCODING 7798 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -00 -18 -2C -ENDCHAR -STARTCHAR uni1E77 -ENCODING 7799 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -00 -18 -2C -ENDCHAR -STARTCHAR uni1E78 -ENCODING 7800 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 16 2 0 -BITMAP -0E -38 -00 -1A -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E79 -ENCODING 7801 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -07 -1C -00 -1A -2C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni1E7A -ENCODING 7802 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 15 2 0 -BITMAP -24 -24 -00 -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1E7B -ENCODING 7803 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -24 -24 -00 -3C -00 -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -ENDCHAR -STARTCHAR uni1E7C -ENCODING 7804 -SWIDTH 735 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1A00 -2C00 -0000 -C180 -C180 -C180 -6100 -6300 -6300 -3200 -3600 -1C00 -1C00 -ENDCHAR -STARTCHAR uni1E7D -ENCODING 7805 -SWIDTH 663 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -34 -58 -00 -C6 -C6 -C6 -C6 -64 -68 -38 -38 -ENDCHAR -STARTCHAR uni1E7E -ENCODING 7806 -SWIDTH 735 0 -DWIDTH 11 0 -BBX 9 13 1 -3 -BITMAP -C180 -C180 -C180 -6100 -6300 -6300 -3200 -3600 -1C00 -1C00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E7F -ENCODING 7807 -SWIDTH 663 0 -DWIDTH 9 0 -BBX 7 11 1 -3 -BITMAP -C6 -C6 -C6 -C6 -64 -68 -38 -38 -00 -30 -30 -ENDCHAR -STARTCHAR Wgrave -ENCODING 7808 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -3800 -0E00 -0000 -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR wgrave -ENCODING 7809 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 0 -BITMAP -3800 -0E00 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR Wacute -ENCODING 7810 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -0380 -0E00 -0000 -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR wacute -ENCODING 7811 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 0 -BITMAP -0380 -0E00 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR Wdieresis -ENCODING 7812 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -0900 -0900 -0000 -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR wdieresis -ENCODING 7813 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 0 -BITMAP -0900 -0900 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR uni1E86 -ENCODING 7814 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 0 -BITMAP -0600 -0600 -0000 -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR uni1E87 -ENCODING 7815 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 0 -BITMAP -0600 -0600 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR uni1E88 -ENCODING 7816 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 13 1 -3 -BITMAP -C060 -C060 -C660 -C660 -6640 -6B40 -6B40 -7BC0 -3180 -3180 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E89 -ENCODING 7817 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 11 1 -3 -BITMAP -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E8A -ENCODING 7818 -SWIDTH 699 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -18 -18 -00 -C6 -C6 -6C -6C -38 -38 -6C -6C -C6 -C6 -ENDCHAR -STARTCHAR uni1E8B -ENCODING 7819 -SWIDTH 568 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -30 -30 -00 -C6 -C6 -64 -38 -38 -4C -C6 -C6 -ENDCHAR -STARTCHAR uni1E8C -ENCODING 7820 -SWIDTH 699 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -24 -24 -00 -C6 -C6 -6C -6C -38 -38 -6C -6C -C6 -C6 -ENDCHAR -STARTCHAR uni1E8D -ENCODING 7821 -SWIDTH 568 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -48 -48 -00 -C6 -C6 -64 -38 -38 -4C -C6 -C6 -ENDCHAR -STARTCHAR uni1E8E -ENCODING 7822 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -18 -18 -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR uni1E8F -ENCODING 7823 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -18 -18 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR uni1E90 -ENCODING 7824 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 13 1 0 -BITMAP -18 -2C -00 -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -ENDCHAR -STARTCHAR uni1E91 -ENCODING 7825 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -18 -2C -00 -FE -06 -0C -18 -30 -60 -C0 -FE -ENDCHAR -STARTCHAR uni1E92 -ENCODING 7826 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 13 1 -3 -BITMAP -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -00 -30 -30 -ENDCHAR -STARTCHAR uni1E93 -ENCODING 7827 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 11 1 -3 -BITMAP -FE -06 -0C -18 -30 -60 -C0 -FE -00 -30 -30 -ENDCHAR -STARTCHAR uni1E94 -ENCODING 7828 -SWIDTH 675 0 -DWIDTH 9 0 -BBX 7 12 1 -2 -BITMAP -FE -06 -0C -1C -18 -30 -70 -60 -C0 -FE -00 -78 -ENDCHAR -STARTCHAR uni1E95 -ENCODING 7829 -SWIDTH 608 0 -DWIDTH 9 0 -BBX 7 10 1 -2 -BITMAP -FE -06 -0C -18 -30 -60 -C0 -FE -00 -78 -ENDCHAR -STARTCHAR uni1E96 -ENCODING 7830 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 13 1 -2 -BITMAP -C0 -C0 -C0 -DE -E7 -C3 -C3 -C3 -C3 -C3 -C3 -00 -3C -ENDCHAR -STARTCHAR uni1E97 -ENCODING 7831 -SWIDTH 436 0 -DWIDTH 7 0 -BBX 5 13 1 0 -BITMAP -90 -90 -00 -60 -60 -F8 -60 -60 -60 -60 -60 -60 -38 -ENDCHAR -STARTCHAR uni1E98 -ENCODING 7832 -SWIDTH 885 0 -DWIDTH 13 0 -BBX 11 12 1 0 -BITMAP -0600 -0B00 -0600 -0000 -C060 -C460 -C460 -6EC0 -6AC0 -7B80 -3180 -3180 -ENDCHAR -STARTCHAR uni1E99 -ENCODING 7833 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 14 1 -2 -BITMAP -18 -2C -18 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR uni1EA0 -ENCODING 7840 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 -3 -BITMAP -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EA1 -ENCODING 7841 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 11 1 -3 -BITMAP -7C -06 -06 -7E -C6 -C6 -CE -77 -00 -18 -18 -ENDCHAR -STARTCHAR uni1EA4 -ENCODING 7844 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -0700 -1C00 -0000 -1C00 -2600 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EA5 -ENCODING 7845 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -18 -2C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EA6 -ENCODING 7846 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -7000 -1C00 -0000 -1C00 -2600 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EA7 -ENCODING 7847 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -70 -1C -00 -18 -2C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EAA -ENCODING 7850 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -1A00 -2C00 -0000 -1C00 -2600 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EAB -ENCODING 7851 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -1A -2C -00 -18 -2C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EAC -ENCODING 7852 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 -3 -BITMAP -0C00 -1600 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EAD -ENCODING 7853 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 -3 -BITMAP -18 -2C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -00 -18 -18 -ENDCHAR -STARTCHAR uni1EAE -ENCODING 7854 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -0700 -1C00 -0000 -2100 -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EAF -ENCODING 7855 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -42 -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EB0 -ENCODING 7856 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -3800 -0E00 -0000 -2100 -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EB1 -ENCODING 7857 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -70 -1C -00 -42 -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EB4 -ENCODING 7860 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 0 -BITMAP -1A00 -2C00 -0000 -2100 -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni1EB5 -ENCODING 7861 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 0 -BITMAP -1A -2C -00 -42 -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -ENDCHAR -STARTCHAR uni1EB6 -ENCODING 7862 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 16 1 -3 -BITMAP -2100 -1E00 -0000 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EB7 -ENCODING 7863 -SWIDTH 623 0 -DWIDTH 9 0 -BBX 8 14 1 -3 -BITMAP -42 -3C -00 -7C -06 -06 -7E -C6 -C6 -CE -77 -00 -18 -18 -ENDCHAR -STARTCHAR uni1EB8 -ENCODING 7864 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 -3 -BITMAP -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -00 -60 -60 -ENDCHAR -STARTCHAR uni1EB9 -ENCODING 7865 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 -3 -BITMAP -3C -66 -C6 -FE -C0 -C0 -62 -3C -00 -30 -30 -ENDCHAR -STARTCHAR uni1EBC -ENCODING 7868 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 13 2 0 -BITMAP -68 -B0 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni1EBD -ENCODING 7869 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 11 1 0 -BITMAP -34 -58 -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1EBE -ENCODING 7870 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 16 2 0 -BITMAP -1C -70 -00 -30 -58 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni1EBF -ENCODING 7871 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 14 1 0 -BITMAP -0E -38 -00 -18 -2C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1EC0 -ENCODING 7872 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 16 2 0 -BITMAP -E0 -38 -00 -30 -58 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni1EC1 -ENCODING 7873 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 14 1 0 -BITMAP -70 -1C -00 -18 -2C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1EC4 -ENCODING 7876 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 16 2 0 -BITMAP -34 -58 -00 -30 -58 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -ENDCHAR -STARTCHAR uni1EC5 -ENCODING 7877 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 14 1 0 -BITMAP -1A -2C -00 -18 -2C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -ENDCHAR -STARTCHAR uni1EC6 -ENCODING 7878 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 16 2 -3 -BITMAP -60 -B0 -00 -FC -C0 -C0 -C0 -F8 -C0 -C0 -C0 -C0 -FC -00 -60 -60 -ENDCHAR -STARTCHAR uni1EC7 -ENCODING 7879 -SWIDTH 614 0 -DWIDTH 9 0 -BBX 7 14 1 -3 -BITMAP -18 -2C -00 -3C -66 -C6 -FE -C0 -C0 -62 -3C -00 -30 -30 -ENDCHAR -STARTCHAR uni1ECA -ENCODING 7882 -SWIDTH 361 0 -DWIDTH 6 0 -BBX 2 13 2 -3 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -00 -C0 -C0 -ENDCHAR -STARTCHAR uni1ECB -ENCODING 7883 -SWIDTH 361 0 -DWIDTH 4 0 -BBX 2 14 1 -3 -BITMAP -C0 -C0 -00 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -00 -C0 -C0 -ENDCHAR -STARTCHAR uni1ECC -ENCODING 7884 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 13 1 -3 -BITMAP -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1ECD -ENCODING 7885 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -3C -66 -C3 -C3 -C3 -C3 -66 -3C -00 -18 -18 -ENDCHAR -STARTCHAR uni1ED0 -ENCODING 7888 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 0 -BITMAP -0700 -1C00 -0000 -0C00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1ED1 -ENCODING 7889 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -0E -38 -00 -18 -2C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1ED2 -ENCODING 7890 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 0 -BITMAP -3800 -0E00 -0000 -0C00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1ED3 -ENCODING 7891 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -70 -1C -00 -18 -2C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1ED6 -ENCODING 7894 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 0 -BITMAP -0D00 -1600 -0000 -0C00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1ED7 -ENCODING 7895 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 0 -BITMAP -1A -2C -00 -18 -2C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -ENDCHAR -STARTCHAR uni1ED8 -ENCODING 7896 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 10 16 1 -3 -BITMAP -0C00 -1600 -0000 -3F00 -6180 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1ED9 -ENCODING 7897 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 8 14 1 -3 -BITMAP -18 -2C -00 -3C -66 -C3 -C3 -C3 -C3 -66 -3C -00 -18 -18 -ENDCHAR -STARTCHAR uni1EDA -ENCODING 7898 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 11 13 1 0 -BITMAP -0380 -0E00 -0000 -3F60 -61E0 -C0E0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1EDB -ENCODING 7899 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -0380 -0E00 -0000 -3CC0 -66C0 -C340 -C380 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EDC -ENCODING 7900 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 11 13 1 0 -BITMAP -1C00 -0700 -0000 -3F60 -61E0 -C0E0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1EDD -ENCODING 7901 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -3800 -0E00 -0000 -3CC0 -66C0 -C340 -C380 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EE0 -ENCODING 7904 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 11 13 1 0 -BITMAP -0680 -0B00 -0000 -3F60 -61E0 -C0E0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -ENDCHAR -STARTCHAR uni1EE1 -ENCODING 7905 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -0D00 -1600 -0000 -3CC0 -66C0 -C340 -C380 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EE2 -ENCODING 7906 -SWIDTH 855 0 -DWIDTH 12 0 -BBX 11 13 1 -3 -BITMAP -3F60 -61E0 -C0E0 -C0C0 -C0C0 -C0C0 -C0C0 -C0C0 -6180 -3F00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EE3 -ENCODING 7907 -SWIDTH 675 0 -DWIDTH 10 0 -BBX 10 11 1 -3 -BITMAP -3CC0 -66C0 -C340 -C380 -C300 -C300 -6600 -3C00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1EE4 -ENCODING 7908 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 13 2 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -C3 -C3 -66 -3C -00 -18 -18 -ENDCHAR -STARTCHAR uni1EE5 -ENCODING 7909 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 8 11 1 -3 -BITMAP -C3 -C3 -C3 -C3 -C3 -C3 -E7 -7B -00 -18 -18 -ENDCHAR -STARTCHAR uni1EE8 -ENCODING 7912 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 13 2 0 -BITMAP -0380 -0E00 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EE9 -ENCODING 7913 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -0380 -0E00 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -E700 -7B00 -ENDCHAR -STARTCHAR uni1EEA -ENCODING 7914 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 13 2 0 -BITMAP -3800 -0E00 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EEB -ENCODING 7915 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -3800 -0E00 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -E700 -7B00 -ENDCHAR -STARTCHAR uni1EEE -ENCODING 7918 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 13 2 0 -BITMAP -0D00 -1600 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -C300 -C300 -6600 -3C00 -ENDCHAR -STARTCHAR uni1EEF -ENCODING 7919 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 10 11 1 0 -BITMAP -0D00 -1600 -0000 -C3C0 -C3C0 -C340 -C380 -C300 -C300 -E700 -7B00 -ENDCHAR -STARTCHAR uni1EF0 -ENCODING 7920 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 10 13 2 -3 -BITMAP -C3C0 -C3C0 -C340 -C380 -C300 -C300 -C300 -C300 -6600 -3C00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1EF1 -ENCODING 7921 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 10 11 1 -3 -BITMAP -C3C0 -C3C0 -C340 -C380 -C300 -C300 -E700 -7B00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR Ygrave -ENCODING 7922 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -70 -1C -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR ygrave -ENCODING 7923 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -E0 -38 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR uni1EF4 -ENCODING 7924 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 -3 -BITMAP -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -00 -18 -18 -ENDCHAR -STARTCHAR uni1EF5 -ENCODING 7925 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -5 -BITMAP -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -00 -30 -30 -ENDCHAR -STARTCHAR uni1EF8 -ENCODING 7928 -SWIDTH 738 0 -DWIDTH 10 0 -BBX 8 13 1 0 -BITMAP -1A -2C -00 -C3 -C3 -62 -66 -34 -18 -18 -18 -18 -18 -ENDCHAR -STARTCHAR uni1EF9 -ENCODING 7929 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 7 13 1 -2 -BITMAP -34 -58 -00 -C6 -C6 -C6 -C6 -6C -68 -38 -30 -60 -E0 -ENDCHAR -STARTCHAR uni2000 -ENCODING 8192 -SWIDTH 500 0 -DWIDTH 7 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2001 -ENCODING 8193 -SWIDTH 1000 0 -DWIDTH 15 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2002 -ENCODING 8194 -SWIDTH 500 0 -DWIDTH 7 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2003 -ENCODING 8195 -SWIDTH 1000 0 -DWIDTH 15 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2004 -ENCODING 8196 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2005 -ENCODING 8197 -SWIDTH 250 0 -DWIDTH 4 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2006 -ENCODING 8198 -SWIDTH 167 0 -DWIDTH 2 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2007 -ENCODING 8199 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2008 -ENCODING 8200 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2009 -ENCODING 8201 -SWIDTH 200 0 -DWIDTH 3 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni200A -ENCODING 8202 -SWIDTH 100 0 -DWIDTH 1 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni200B -ENCODING 8203 -SWIDTH 0 0 -DWIDTH 0 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2010 -ENCODING 8208 -SWIDTH 289 0 -DWIDTH 5 0 -BBX 3 1 1 4 -BITMAP -E0 -ENDCHAR -STARTCHAR uni2011 -ENCODING 8209 -SWIDTH 289 0 -DWIDTH 5 0 -BBX 3 1 1 4 -BITMAP -E0 -ENDCHAR -STARTCHAR figuredash -ENCODING 8210 -SWIDTH 500 0 -DWIDTH 7 0 -BBX 5 1 1 4 -BITMAP -F8 -ENDCHAR -STARTCHAR endash -ENCODING 8211 -SWIDTH 500 0 -DWIDTH 7 0 -BBX 5 1 1 4 -BITMAP -F8 -ENDCHAR -STARTCHAR emdash -ENCODING 8212 -SWIDTH 1000 0 -DWIDTH 15 0 -BBX 13 1 1 4 -BITMAP -FFF8 -ENDCHAR -STARTCHAR afii00208 -ENCODING 8213 -SWIDTH 1000 0 -DWIDTH 15 0 -BBX 13 1 1 4 -BITMAP -FFF8 -ENDCHAR -STARTCHAR quoteleft -ENCODING 8216 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -40 -80 -C0 -C0 -ENDCHAR -STARTCHAR quoteright -ENCODING 8217 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR quotesinglbase -ENCODING 8218 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 -2 -BITMAP -C0 -C0 -40 -80 -ENDCHAR -STARTCHAR quotereversed -ENCODING 8219 -SWIDTH 265 0 -DWIDTH 4 0 -BBX 2 4 1 7 -BITMAP -C0 -C0 -80 -40 -ENDCHAR -STARTCHAR quotedblleft -ENCODING 8220 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 7 -BITMAP -48 -90 -D8 -D8 -ENDCHAR -STARTCHAR quotedblright -ENCODING 8221 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 7 -BITMAP -D8 -D8 -48 -90 -ENDCHAR -STARTCHAR quotedblbase -ENCODING 8222 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 -2 -BITMAP -D8 -D8 -48 -90 -ENDCHAR -STARTCHAR uni201F -ENCODING 8223 -SWIDTH 530 0 -DWIDTH 7 0 -BBX 5 4 1 7 -BITMAP -D8 -D8 -90 -48 -ENDCHAR -STARTCHAR dagger -ENCODING 8224 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 6 11 2 -1 -BITMAP -30 -30 -30 -FC -30 -30 -30 -30 -30 -30 -30 -ENDCHAR -STARTCHAR daggerdbl -ENCODING 8225 -SWIDTH 693 0 -DWIDTH 10 0 -BBX 6 11 2 -1 -BITMAP -30 -30 -30 -FC -30 -30 -30 -FC -30 -30 -30 -ENDCHAR -STARTCHAR bullet -ENCODING 8226 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 4 4 3 2 -BITMAP -F0 -F0 -F0 -F0 -ENDCHAR -STARTCHAR ellipsis -ENCODING 8230 -SWIDTH 1000 0 -DWIDTH 10 0 -BBX 6 2 2 0 -BITMAP -CC -CC -ENDCHAR -STARTCHAR perthousand -ENCODING 8240 -SWIDTH 1313 0 -DWIDTH 18 0 -BBX 16 10 1 0 -BITMAP -7000 -D980 -DB00 -7200 -0400 -0800 -138E -36DB -66DB -038E -ENDCHAR -STARTCHAR guilsinglleft -ENCODING 8249 -SWIDTH 361 0 -DWIDTH 5 0 -BBX 4 5 0 2 -BITMAP -30 -60 -C0 -60 -30 -ENDCHAR -STARTCHAR guilsinglright -ENCODING 8250 -SWIDTH 361 0 -DWIDTH 5 0 -BBX 4 5 1 2 -BITMAP -C0 -60 -30 -60 -C0 -ENDCHAR -STARTCHAR fraction -ENCODING 8260 -SWIDTH 93 0 -DWIDTH 4 0 -BBX 6 10 -1 0 -BITMAP -0C -0C -18 -18 -30 -30 -60 -60 -C0 -C0 -ENDCHAR -STARTCHAR oneinferior -ENCODING 8321 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 4 6 1 -2 -BITMAP -30 -F0 -30 -30 -30 -30 -ENDCHAR -STARTCHAR twoinferior -ENCODING 8322 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 5 6 1 -2 -BITMAP -F0 -18 -18 -60 -C0 -F8 -ENDCHAR -STARTCHAR threeinferior -ENCODING 8323 -SWIDTH 536 0 -DWIDTH 7 0 -BBX 5 6 1 -2 -BITMAP -F0 -18 -70 -18 -18 -F0 -ENDCHAR -STARTCHAR uni20A5 -ENCODING 8357 -SWIDTH 1006 0 -DWIDTH 14 0 -BBX 12 12 1 -2 -BITMAP -00C0 -0180 -DDE0 -EF70 -C730 -C630 -C630 -CE30 -CE30 -DE30 -1800 -3000 -ENDCHAR -STARTCHAR uni20A6 -ENCODING 8358 -SWIDTH 783 0 -DWIDTH 12 0 -BBX 8 10 2 0 -BITMAP -E1 -E1 -B1 -FF -99 -FF -8D -8D -87 -87 -ENDCHAR -STARTCHAR uni20A9 -ENCODING 8361 -SWIDTH 940 0 -DWIDTH 13 0 -BBX 11 10 1 0 -BITMAP -C060 -C060 -C660 -FFE0 -6640 -7FC0 -6B40 -7BC0 -3180 -3180 -ENDCHAR -STARTCHAR Euro -ENCODING 8364 -SWIDTH 726 0 -DWIDTH 11 0 -BBX 9 10 1 0 -BITMAP -1F00 -3180 -6000 -FE00 -6000 -FE00 -6000 -6000 -3180 -1F00 -ENDCHAR -STARTCHAR uni20AD -ENCODING 8365 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -C3 -C6 -CC -D8 -FF -D8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni2103 -ENCODING 8451 -SWIDTH 955 0 -DWIDTH 15 0 -BBX 14 10 0 0 -BITMAP -60F8 -918C -6300 -0300 -0300 -0300 -0300 -0300 -018C -00F8 -ENDCHAR -STARTCHAR uni2109 -ENCODING 8457 -SWIDTH 831 0 -DWIDTH 13 0 -BBX 12 10 0 0 -BITMAP -63F0 -9300 -6300 -0300 -03E0 -0300 -0300 -0300 -0300 -0300 -ENDCHAR -STARTCHAR trademark -ENCODING 8482 -SWIDTH 901 0 -DWIDTH 13 0 -BBX 10 5 1 5 -BITMAP -FEC0 -2540 -2540 -2540 -2440 -ENDCHAR -STARTCHAR uni212A -ENCODING 8490 -SWIDTH 753 0 -DWIDTH 11 0 -BBX 8 10 2 0 -BITMAP -C3 -C6 -CC -D8 -F0 -D8 -CC -C6 -C3 -C3 -ENDCHAR -STARTCHAR uni212B -ENCODING 8491 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 13 1 0 -BITMAP -1C00 -2600 -1C00 -1C00 -1C00 -2600 -2600 -6300 -4300 -FF00 -C180 -C180 -C180 -ENDCHAR -STARTCHAR uni2132 -ENCODING 8498 -SWIDTH 602 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -0C -0C -0C -0C -0C -7C -0C -0C -0C -FC -ENDCHAR -STARTCHAR universal -ENCODING 8704 -SWIDTH 773 0 -DWIDTH 11 0 -BBX 9 10 1 0 -BITMAP -C180 -C180 -C180 -FF00 -4300 -6300 -2600 -2600 -1C00 -1C00 -ENDCHAR -STARTCHAR existential -ENCODING 8707 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 6 10 2 0 -BITMAP -FC -0C -0C -0C -7C -0C -0C -0C -0C -FC -ENDCHAR -STARTCHAR uni2204 -ENCODING 8708 -SWIDTH 645 0 -DWIDTH 9 0 -BBX 8 12 1 -1 -BITMAP -03 -7E -06 -0E -0E -3E -1E -36 -36 -66 -7E -C0 -ENDCHAR -STARTCHAR minus -ENCODING 8722 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 1 1 4 -BITMAP -FE -ENDCHAR -STARTCHAR fraction -ENCODING 8725 -SWIDTH 93 0 -DWIDTH 4 0 -BBX 6 10 -1 0 -BITMAP -0C -0C -18 -18 -30 -30 -60 -60 -C0 -C0 -ENDCHAR -STARTCHAR periodcentered -ENCODING 8729 -SWIDTH 343 0 -DWIDTH 10 0 -BBX 2 2 4 3 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR uni2236 -ENCODING 8758 -SWIDTH 343 0 -DWIDTH 4 0 -BBX 2 7 1 0 -BITMAP -C0 -C0 -00 -00 -00 -C0 -C0 -ENDCHAR -STARTCHAR uni2259 -ENCODING 8793 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 6 1 3 -BITMAP -18 -2C -00 -FE -00 -FE -ENDCHAR -STARTCHAR uni225A -ENCODING 8794 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 6 1 3 -BITMAP -2C -18 -00 -FE -00 -FE -ENDCHAR -STARTCHAR notequal -ENCODING 8800 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 1 -1 -BITMAP -03 -06 -06 -0C -0C -FE -18 -FE -30 -60 -60 -C0 -ENDCHAR -STARTCHAR equivalence -ENCODING 8801 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 7 5 0 2 -BITMAP -FE -00 -FE -00 -FE -ENDCHAR -STARTCHAR uni2262 -ENCODING 8802 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 0 -1 -BITMAP -03 -06 -06 -0C -FE -18 -FE -30 -FE -60 -60 -C0 -ENDCHAR -STARTCHAR lessequal -ENCODING 8804 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 6 9 2 -1 -BITMAP -0C -38 -60 -C0 -60 -38 -0C -00 -FC -ENDCHAR -STARTCHAR greaterequal -ENCODING 8805 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 6 9 2 -1 -BITMAP -C0 -70 -18 -0C -18 -70 -C0 -00 -FC -ENDCHAR -STARTCHAR uni226E -ENCODING 8814 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 1 -1 -BITMAP -03 -06 -06 -0E -1C -38 -78 -30 -3C -66 -60 -C0 -ENDCHAR -STARTCHAR uni226F -ENCODING 8815 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 1 -1 -BITMAP -03 -06 -06 -6C -3C -1C -1E -3C -38 -60 -60 -C0 -ENDCHAR -STARTCHAR uni2270 -ENCODING 8816 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -03 -06 -06 -1C -3C -78 -38 -3C -36 -60 -7E -C0 -ENDCHAR -STARTCHAR uni2271 -ENCODING 8817 -SWIDTH 687 0 -DWIDTH 10 0 -BBX 8 12 1 -2 -BITMAP -03 -06 -66 -3C -0C -1E -1C -38 -70 -60 -7E -C0 -ENDCHAR -STARTCHAR fi -ENCODING -1 -SWIDTH 711 0 -DWIDTH 11 0 -BBX 9 11 0 0 -BITMAP -1D80 -3180 -3000 -FF80 -3180 -3180 -3180 -3180 -3180 -3180 -3180 -ENDCHAR -STARTCHAR fl -ENCODING -1 -SWIDTH 711 0 -DWIDTH 10 0 -BBX 9 11 0 0 -BITMAP -1F80 -3180 -3180 -FD80 -3180 -3180 -3180 -3180 -3180 -3180 -3180 -ENDCHAR -ENDFONT diff --git a/fonts/ncenB18.bdf b/fonts/ncenB18.bdf deleted file mode 100644 index d8eae064..00000000 --- a/fonts/ncenB18.bdf +++ /dev/null @@ -1,16273 +0,0 @@ -STARTFONT 2.1 -FONT -Adobe-New Century Schoolbook-Bold-R-Normal--18-180-75-75-P-113-ISO10646-1 -SIZE 18 75 75 -FONTBOUNDINGBOX 24 31 -3 -8 -COMMENT $Xorg: $ -COMMENT ISO10646-1 extension by Markus Kuhn , 2001-03-20 -COMMENT -COMMENT + -COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. -COMMENT Copyright 1988, 1994 Digital Equipment Corporation. -COMMENT -COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be -COMMENT registered in certain jurisdictions. -COMMENT Permission to use these trademarks is hereby granted only in -COMMENT association with the images described in this file. -COMMENT -COMMENT Permission to use, copy, modify, distribute and sell this software -COMMENT and its documentation for any purpose and without fee is hereby -COMMENT granted, provided that the above copyright notices appear in all -COMMENT copies and that both those copyright notices and this permission -COMMENT notice appear in supporting documentation, and that the names of -COMMENT Adobe Systems and Digital Equipment Corporation not be used in -COMMENT advertising or publicity pertaining to distribution of the software -COMMENT without specific, written prior permission. Adobe Systems and -COMMENT Digital Equipment Corporation make no representations about the -COMMENT suitability of this software for any purpose. It is provided "as -COMMENT is" without express or implied warranty. -COMMENT - -STARTPROPERTIES 26 -FOUNDRY "Adobe" -FAMILY_NAME "New Century Schoolbook" -WEIGHT_NAME "Bold" -SLANT "R" -SETWIDTH_NAME "Normal" -ADD_STYLE_NAME "" -PIXEL_SIZE 18 -POINT_SIZE 180 -RESOLUTION_X 75 -RESOLUTION_Y 75 -SPACING "P" -AVERAGE_WIDTH 113 -CHARSET_REGISTRY "ISO10646" -CHARSET_ENCODING "1" -CAP_HEIGHT 14 -X_HEIGHT 9 -FONT_ASCENT 16 -FONT_DESCENT 4 -FACE_NAME "New Century Schoolbook Bold" -COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." -NOTICE "New Century Schoolbook is a trademark of Linotype-Hell AG and/or its subsidiaries." -_DEC_DEVICE_FONTNAMES "PS=NewCenturySchlbk-Bold" -DEFAULT_CHAR 0 -RELATIVE_SETWIDTH 50 -RELATIVE_WEIGHT 70 -FULL_NAME "New Century Schoolbook Bold" -ENDPROPERTIES -CHARS 756 -STARTCHAR char0 -ENCODING 0 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 13 13 1 0 -BITMAP -AAA8 -0000 -8008 -0000 -8008 -0000 -8008 -0000 -8008 -0000 -8008 -0000 -AAA8 -ENDCHAR -STARTCHAR space -ENCODING 32 -SWIDTH 287 0 -DWIDTH 5 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclam -ENCODING 33 -SWIDTH 296 0 -DWIDTH 6 0 -BBX 4 14 1 0 -BITMAP -60 -F0 -F0 -F0 -F0 -F0 -60 -60 -60 -00 -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR quotedbl -ENCODING 34 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 5 5 1 9 -BITMAP -D8 -D8 -D8 -D8 -D8 -ENDCHAR -STARTCHAR numbersign -ENCODING 35 -SWIDTH 574 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -0D80 -0D80 -0D80 -7FE0 -7FE0 -1B00 -1B00 -FFC0 -FFC0 -3600 -3600 -3600 -3600 -ENDCHAR -STARTCHAR dollar -ENCODING 36 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 18 1 -2 -BITMAP -0800 -0800 -3E00 -6B80 -C980 -C980 -E800 -F800 -7E00 -3F00 -0F80 -0B80 -C980 -C980 -EB80 -7F00 -0800 -0800 -ENDCHAR -STARTCHAR percent -ENCODING 37 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -38C0 -6740 -C4C0 -C480 -C580 -C900 -7300 -0238 -0664 -04C4 -0CC4 -08C4 -18C8 -1070 -ENDCHAR -STARTCHAR ampersand -ENCODING 38 -SWIDTH 852 0 -DWIDTH 17 0 -BBX 16 14 0 0 -BITMAP -0780 -0CC0 -1840 -18C0 -1D80 -1F00 -0E3E -3F18 -7790 -E3E0 -E1E0 -E0F1 -F1FE -3F1C -ENDCHAR -STARTCHAR quotesingle -ENCODING 39 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 2 5 1 9 -BITMAP -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR parenleft -ENCODING 40 -SWIDTH 389 0 -DWIDTH 6 0 -BBX 5 16 1 -2 -BITMAP -18 -30 -60 -60 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -60 -60 -30 -18 -ENDCHAR -STARTCHAR parenright -ENCODING 41 -SWIDTH 389 0 -DWIDTH 6 0 -BBX 5 16 0 -2 -BITMAP -C0 -60 -30 -30 -18 -18 -18 -18 -18 -18 -18 -18 -30 -30 -60 -C0 -ENDCHAR -STARTCHAR asterisk -ENCODING 42 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 7 7 0 7 -BITMAP -38 -92 -D6 -38 -D6 -92 -38 -ENDCHAR -STARTCHAR plus -ENCODING 43 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 10 0 0 -BITMAP -0C00 -0C00 -0C00 -0C00 -FFC0 -FFC0 -0C00 -0C00 -0C00 -0C00 -ENDCHAR -STARTCHAR comma -ENCODING 44 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 4 7 0 -3 -BITMAP -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR hyphen -ENCODING 45 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 5 2 0 4 -BITMAP -F8 -F8 -ENDCHAR -STARTCHAR period -ENCODING 46 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 4 4 0 0 -BITMAP -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR slash -ENCODING 47 -SWIDTH 278 0 -DWIDTH 7 0 -BBX 6 14 0 0 -BITMAP -0C -0C -0C -18 -18 -18 -30 -30 -30 -60 -60 -60 -C0 -C0 -ENDCHAR -STARTCHAR zero -ENCODING 48 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1C00 -7700 -6300 -E380 -E380 -E380 -E380 -E380 -E380 -E380 -E380 -6300 -7700 -1C00 -ENDCHAR -STARTCHAR one -ENCODING 49 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 7 14 2 0 -BITMAP -18 -38 -F8 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -FE -ENDCHAR -STARTCHAR two -ENCODING 50 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1E00 -6700 -E380 -E380 -6380 -0380 -0700 -0700 -0E00 -1800 -3000 -6080 -FF80 -FF80 -ENDCHAR -STARTCHAR three -ENCODING 51 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1E00 -6700 -E380 -E380 -6380 -0300 -1C00 -0300 -0380 -6380 -E380 -E380 -6700 -3E00 -ENDCHAR -STARTCHAR four -ENCODING 52 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -0700 -0F00 -0F00 -1700 -1700 -2700 -2700 -4700 -4700 -8700 -FF80 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR five -ENCODING 53 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -7F80 -7F00 -4000 -4000 -4000 -7E00 -4700 -0380 -0380 -6380 -E380 -E380 -6700 -3E00 -ENDCHAR -STARTCHAR six -ENCODING 54 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1F00 -7380 -6380 -E300 -E000 -EE00 -F700 -E380 -E380 -E380 -E380 -6380 -7300 -1C00 -ENDCHAR -STARTCHAR seven -ENCODING 55 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -FF80 -FF80 -FF80 -8300 -0600 -0600 -0C00 -0C00 -1C00 -1C00 -3800 -3800 -3800 -3800 -ENDCHAR -STARTCHAR eight -ENCODING 56 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1C00 -6300 -C180 -C180 -E180 -FB00 -7E00 -3F00 -4F80 -C380 -C180 -C180 -E300 -3C00 -ENDCHAR -STARTCHAR nine -ENCODING 57 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1C00 -6700 -E300 -E380 -E380 -E380 -E380 -7780 -3B80 -0380 -6380 -E300 -E700 -7C00 -ENDCHAR -STARTCHAR colon -ENCODING 58 -SWIDTH 278 0 -DWIDTH 6 0 -BBX 4 9 1 0 -BITMAP -60 -F0 -F0 -60 -00 -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR semicolon -ENCODING 59 -SWIDTH 278 0 -DWIDTH 6 0 -BBX 4 12 1 -3 -BITMAP -60 -F0 -F0 -60 -00 -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR less -ENCODING 60 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 10 0 0 -BITMAP -00C0 -03C0 -0F00 -3C00 -F000 -F000 -3C00 -0F00 -03C0 -00C0 -ENDCHAR -STARTCHAR equal -ENCODING 61 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 6 1 2 -BITMAP -FF80 -FF80 -0000 -0000 -FF80 -FF80 -ENDCHAR -STARTCHAR greater -ENCODING 62 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 10 0 0 -BITMAP -C000 -F000 -3C00 -0F00 -03C0 -03C0 -0F00 -3C00 -F000 -C000 -ENDCHAR -STARTCHAR question -ENCODING 63 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -1F00 -6780 -E380 -E380 -6380 -0300 -0600 -0C00 -1800 -0000 -1800 -3C00 -3C00 -1800 -ENDCHAR -STARTCHAR at -ENCODING 64 -SWIDTH 747 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -07F0 -1C1C -300C -63E6 -6666 -CC66 -CC66 -D8CC -D8CC -D9D8 -CEF0 -6008 -7870 -1FC0 -ENDCHAR -STARTCHAR A -ENCODING 65 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 14 0 0 -BITMAP -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR B -ENCODING 66 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 14 1 0 -BITMAP -FFC0 -71E0 -70E0 -70E0 -70E0 -71C0 -7F80 -70E0 -70F0 -7070 -7070 -7070 -70E0 -FF80 -ENDCHAR -STARTCHAR C -ENCODING 67 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 14 1 0 -BITMAP -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -ENDCHAR -STARTCHAR D -ENCODING 68 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -ENDCHAR -STARTCHAR E -ENCODING 69 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR F -ENCODING 70 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7320 -7F00 -7300 -7100 -7100 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR G -ENCODING 71 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 14 1 0 -BITMAP -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR H -ENCODING 72 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR I -ENCODING 73 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 14 2 0 -BITMAP -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR J -ENCODING 74 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -07E0 -01C0 -01C0 -01C0 -01C0 -01C0 -01C0 -01C0 -61C0 -F1C0 -F1C0 -C3C0 -4780 -3E00 -ENDCHAR -STARTCHAR K -ENCODING 75 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 14 1 0 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -ENDCHAR -STARTCHAR L -ENCODING 76 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 14 1 0 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR M -ENCODING 77 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 17 14 1 0 -BITMAP -7C0780 -3C0F00 -3E0F00 -2E1F00 -2F1700 -2F1700 -273700 -27A700 -23E700 -23C700 -23C700 -21C700 -718700 -F88F80 -ENDCHAR -STARTCHAR N -ENCODING 78 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 1 0 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR O -ENCODING 79 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR P -ENCODING 80 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 12 14 1 0 -BITMAP -FFE0 -70F0 -7070 -7070 -7070 -70F0 -71E0 -7F80 -7000 -7000 -7000 -7000 -7000 -FC00 -ENDCHAR -STARTCHAR Q -ENCODING 81 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 -4 -BITMAP -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F79E -79DC -70FC -3CF8 -0FE0 -0060 -0074 -007C -0038 -ENDCHAR -STARTCHAR R -ENCODING 82 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR S -ENCODING 83 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -ENDCHAR -STARTCHAR T -ENCODING 84 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -ENDCHAR -STARTCHAR U -ENCODING 85 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR V -ENCODING 86 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 14 0 0 -BITMAP -F87C -7038 -7830 -3820 -3820 -3C60 -1C40 -1E40 -0EC0 -0E80 -0780 -0780 -0300 -0300 -ENDCHAR -STARTCHAR W -ENCODING 87 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 14 0 0 -BITMAP -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR X -ENCODING 88 -SWIDTH 722 0 -DWIDTH 17 0 -BBX 16 14 0 0 -BITMAP -7E3F -3C1C -1E18 -0E30 -0F60 -07C0 -03C0 -03E0 -06F0 -0C70 -1878 -303C -703E -F87F -ENDCHAR -STARTCHAR Y -ENCODING 89 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 14 1 0 -BITMAP -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR Z -ENCODING 90 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -ENDCHAR -STARTCHAR bracketleft -ENCODING 91 -SWIDTH 389 0 -DWIDTH 5 0 -BBX 4 16 1 -2 -BITMAP -F0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -F0 -ENDCHAR -STARTCHAR backslash -ENCODING 92 -SWIDTH 606 0 -DWIDTH 9 0 -BBX 8 14 0 0 -BITMAP -C0 -C0 -60 -60 -30 -30 -18 -18 -0C -0C -06 -06 -03 -03 -ENDCHAR -STARTCHAR bracketright -ENCODING 93 -SWIDTH 389 0 -DWIDTH 5 0 -BBX 4 16 0 -2 -BITMAP -F0 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -30 -F0 -ENDCHAR -STARTCHAR asciicircum -ENCODING 94 -SWIDTH 606 0 -DWIDTH 9 0 -BBX 8 8 0 6 -BITMAP -18 -18 -3C -3C -66 -66 -C3 -C3 -ENDCHAR -STARTCHAR underscore -ENCODING 95 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 10 2 0 -3 -BITMAP -FFC0 -FFC0 -ENDCHAR -STARTCHAR grave -ENCODING 96 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 10 -BITMAP -C0 -E0 -70 -18 -ENDCHAR -STARTCHAR a -ENCODING 97 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR b -ENCODING 98 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 12 14 -1 0 -BITMAP -F000 -7000 -7000 -7000 -7000 -7780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -6F80 -ENDCHAR -STARTCHAR c -ENCODING 99 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 9 0 0 -BITMAP -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -ENDCHAR -STARTCHAR d -ENCODING 100 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -ENDCHAR -STARTCHAR e -ENCODING 101 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR f -ENCODING 102 -SWIDTH 389 0 -DWIDTH 7 0 -BBX 8 14 0 0 -BITMAP -1E -37 -77 -70 -70 -FC -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR g -ENCODING 103 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 15 0 -4 -BITMAP -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR h -ENCODING 104 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR i -ENCODING 105 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 14 0 0 -BITMAP -70 -70 -70 -00 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR j -ENCODING 106 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 7 18 -3 -4 -BITMAP -0E -0E -0E -00 -00 -1E -0E -0E -0E -0E -0E -0E -0E -0E -0E -EE -EC -78 -ENDCHAR -STARTCHAR k -ENCODING 107 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -ENDCHAR -STARTCHAR l -ENCODING 108 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 5 14 0 0 -BITMAP -F0 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR m -ENCODING 109 -SWIDTH 963 0 -DWIDTH 20 0 -BBX 19 9 0 0 -BITMAP -F7DF80 -79F3C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -F9F3E0 -ENDCHAR -STARTCHAR n -ENCODING 110 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 9 0 0 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR o -ENCODING 111 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 9 0 0 -BITMAP -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR p -ENCODING 112 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 12 13 -1 -4 -BITMAP -E780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -7780 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR q -ENCODING 113 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 12 13 0 -4 -BITMAP -1E60 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EE0 -00E0 -00E0 -00E0 -01F0 -ENDCHAR -STARTCHAR r -ENCODING 114 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 9 0 0 -BITMAP -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR s -ENCODING 115 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 9 0 0 -BITMAP -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR t -ENCODING 116 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 13 0 0 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -ENDCHAR -STARTCHAR u -ENCODING 117 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 9 0 0 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR v -ENCODING 118 -SWIDTH 611 0 -DWIDTH 9 0 -BBX 10 9 -1 0 -BITMAP -F9C0 -7080 -7080 -3900 -3900 -1E00 -1E00 -0C00 -0C00 -ENDCHAR -STARTCHAR w -ENCODING 119 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 9 -1 0 -BITMAP -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR x -ENCODING 120 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 9 0 0 -BITMAP -FCE0 -78C0 -3D00 -1E00 -0E00 -0F00 -1780 -63C0 -E7E0 -ENDCHAR -STARTCHAR y -ENCODING 121 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 -4 -BITMAP -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR z -ENCODING 122 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 9 0 0 -BITMAP -FF -CF -8E -1C -38 -39 -71 -F3 -FF -ENDCHAR -STARTCHAR braceleft -ENCODING 123 -SWIDTH 389 0 -DWIDTH 6 0 -BBX 5 16 0 -2 -BITMAP -18 -20 -60 -60 -60 -60 -60 -C0 -60 -60 -60 -60 -60 -60 -20 -18 -ENDCHAR -STARTCHAR bar -ENCODING 124 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 2 14 4 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR braceright -ENCODING 125 -SWIDTH 389 0 -DWIDTH 6 0 -BBX 5 16 0 -2 -BITMAP -C0 -20 -30 -30 -30 -30 -30 -18 -30 -30 -30 -30 -30 -30 -20 -C0 -ENDCHAR -STARTCHAR asciitilde -ENCODING 126 -SWIDTH 606 0 -DWIDTH 12 0 -BBX 10 3 1 4 -BITMAP -39C0 -7F80 -E700 -ENDCHAR -STARTCHAR space -ENCODING 160 -SWIDTH 287 0 -DWIDTH 5 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR exclamdown -ENCODING 161 -SWIDTH 296 0 -DWIDTH 7 0 -BBX 4 14 1 -4 -BITMAP -60 -F0 -F0 -60 -00 -60 -60 -60 -F0 -F0 -F0 -F0 -F0 -60 -ENDCHAR -STARTCHAR cent -ENCODING 162 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 13 1 -2 -BITMAP -0080 -0080 -1F00 -7380 -E380 -E400 -E400 -E800 -E880 -7180 -1E00 -2000 -2000 -ENDCHAR -STARTCHAR sterling -ENCODING 163 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -1F00 -3180 -7380 -7380 -7000 -7000 -3800 -FF80 -1C00 -1C00 -1840 -70C0 -9FC0 -EF80 -ENDCHAR -STARTCHAR currency -ENCODING 164 -SWIDTH 606 0 -DWIDTH 10 0 -BBX 9 9 0 2 -BITMAP -DD80 -FF80 -6300 -C180 -C180 -C180 -6300 -FF80 -DD80 -ENDCHAR -STARTCHAR yen -ENCODING 165 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 14 1 0 -BITMAP -F878 -7030 -7820 -3860 -1C40 -1CC0 -0F80 -1FC0 -0700 -1FC0 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR brokenbar -ENCODING 166 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 2 14 4 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -00 -00 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR section -ENCODING 167 -SWIDTH 500 0 -DWIDTH 8 0 -BBX 7 16 0 -2 -BITMAP -78 -CC -8C -C0 -70 -7C -9E -86 -C2 -F2 -7C -1C -04 -C4 -CC -78 -ENDCHAR -STARTCHAR dieresis -ENCODING 168 -SWIDTH 333 0 -DWIDTH 10 0 -BBX 6 2 2 10 -BITMAP -CC -CC -ENDCHAR -STARTCHAR copyright -ENCODING 169 -SWIDTH 747 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -0780 -1860 -2010 -47C8 -4CC8 -9844 -9804 -9804 -9804 -4C48 -4788 -2010 -1860 -0780 -ENDCHAR -STARTCHAR ordfeminine -ENCODING 170 -SWIDTH 367 0 -DWIDTH 8 0 -BBX 7 8 0 6 -BITMAP -78 -CC -3C -CC -DC -6E -00 -FE -ENDCHAR -STARTCHAR guillemotleft -ENCODING 171 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 8 5 0 3 -BITMAP -11 -66 -CC -66 -11 -ENDCHAR -STARTCHAR logicalnot -ENCODING 172 -SWIDTH 606 0 -DWIDTH 10 0 -BBX 9 6 0 2 -BITMAP -FF80 -FF80 -0180 -0180 -0180 -0180 -ENDCHAR -STARTCHAR hyphen -ENCODING 173 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 5 2 0 4 -BITMAP -F8 -F8 -ENDCHAR -STARTCHAR registered -ENCODING 174 -SWIDTH 747 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -0780 -1860 -2010 -5F88 -4CC8 -8CC4 -8F84 -8D84 -8CC4 -5EE8 -4008 -2010 -1860 -0780 -ENDCHAR -STARTCHAR macron -ENCODING 175 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 6 2 1 10 -BITMAP -FC -FC -ENDCHAR -STARTCHAR degree -ENCODING 176 -SWIDTH 400 0 -DWIDTH 7 0 -BBX 6 6 0 8 -BITMAP -78 -CC -84 -84 -CC -78 -ENDCHAR -STARTCHAR plusminus -ENCODING 177 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 11 0 0 -BITMAP -0C00 -0C00 -0C00 -FFC0 -FFC0 -0C00 -0C00 -0C00 -0000 -FFC0 -FFC0 -ENDCHAR -STARTCHAR twosuperior -ENCODING 178 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 6 -BITMAP -78 -CC -CC -18 -30 -60 -C4 -FC -ENDCHAR -STARTCHAR threesuperior -ENCODING 179 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 6 -BITMAP -78 -CC -0C -38 -0C -CC -CC -78 -ENDCHAR -STARTCHAR acute -ENCODING 180 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 10 -BITMAP -18 -38 -70 -C0 -ENDCHAR -STARTCHAR mu -ENCODING 181 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 -4 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -7EF0 -6000 -7000 -7000 -2000 -ENDCHAR -STARTCHAR paragraph -ENCODING 182 -SWIDTH 747 0 -DWIDTH 14 0 -BBX 13 14 0 0 -BITMAP -3FF8 -7E70 -FE70 -FE70 -FE70 -FE70 -7E70 -3E70 -0E70 -0E70 -0E70 -0E70 -0E70 -1FF8 -ENDCHAR -STARTCHAR periodcentered -ENCODING 183 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 4 4 0 3 -BITMAP -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR cedilla -ENCODING 184 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 4 4 1 -4 -BITMAP -40 -70 -30 -E0 -ENDCHAR -STARTCHAR onesuperior -ENCODING 185 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 6 -BITMAP -30 -F0 -30 -30 -30 -30 -30 -FC -ENDCHAR -STARTCHAR ordmasculine -ENCODING 186 -SWIDTH 367 0 -DWIDTH 7 0 -BBX 6 8 0 6 -BITMAP -78 -CC -CC -CC -CC -78 -00 -FC -ENDCHAR -STARTCHAR guillemotright -ENCODING 187 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 8 5 0 3 -BITMAP -88 -66 -33 -66 -88 -ENDCHAR -STARTCHAR onequarter -ENCODING 188 -SWIDTH 861 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -3060 -F060 -30C0 -30C0 -3180 -3180 -3318 -FF38 -0678 -06D8 -0D98 -0DFC -1818 -183C -ENDCHAR -STARTCHAR onehalf -ENCODING 189 -SWIDTH 861 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -3060 -F060 -30C0 -30C0 -3180 -3180 -3378 -FFCC -06CC -0618 -0C30 -0C60 -18C4 -18FC -ENDCHAR -STARTCHAR threequarters -ENCODING 190 -SWIDTH 861 0 -DWIDTH 15 0 -BBX 14 14 0 0 -BITMAP -7860 -CC60 -0CC0 -38C0 -0D80 -CD80 -CF18 -7B38 -0678 -06D8 -0D98 -0DFC -1818 -183C -ENDCHAR -STARTCHAR questiondown -ENCODING 191 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 14 0 -4 -BITMAP -0C00 -1E00 -1E00 -0C00 -0000 -0C00 -1800 -3000 -6000 -E300 -E380 -E380 -F300 -7C00 -ENDCHAR -STARTCHAR Agrave -ENCODING 192 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 19 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR Aacute -ENCODING 193 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 19 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR Acircumflex -ENCODING 194 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0380 -07C0 -0C60 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR Atilde -ENCODING 195 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0620 -0FC0 -1180 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR Adieresis -ENCODING 196 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 17 0 0 -BITMAP -0CC0 -0CC0 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR Aring -ENCODING 197 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0300 -0480 -0480 -0300 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR AE -ENCODING 198 -SWIDTH 981 0 -DWIDTH 21 0 -BBX 20 14 0 0 -BITMAP -03FFF0 -00B870 -01B830 -013890 -033890 -063980 -043F80 -0C3980 -1FF880 -103890 -203810 -203830 -603870 -F1FFF0 -ENDCHAR -STARTCHAR Ccedilla -ENCODING 199 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 18 1 -4 -BITMAP -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -0400 -0700 -0300 -0E00 -ENDCHAR -STARTCHAR Egrave -ENCODING 200 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR Eacute -ENCODING 201 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR Ecircumflex -ENCODING 202 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 0 -BITMAP -0E00 -1F00 -3180 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR Edieresis -ENCODING 203 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -1980 -1980 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR Igrave -ENCODING 204 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 19 2 0 -BITMAP -C0 -E0 -70 -18 -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Iacute -ENCODING 205 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 19 2 0 -BITMAP -0C -1C -38 -60 -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Icircumflex -ENCODING 206 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 7 18 1 0 -BITMAP -38 -7C -C6 -00 -7C -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR Idieresis -ENCODING 207 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 17 2 0 -BITMAP -CC -CC -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Eth -ENCODING 208 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -7FE0 -3878 -383C -381C -381E -380E -FE0E -380E -380E -381E -381C -383C -3878 -7FE0 -ENDCHAR -STARTCHAR Ntilde -ENCODING 209 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 1 0 -BITMAP -0310 -07E0 -08C0 -0000 -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR Ograve -ENCODING 210 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 0 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR Oacute -ENCODING 211 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR Ocircumflex -ENCODING 212 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 0 -BITMAP -0380 -07C0 -0C60 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR Otilde -ENCODING 213 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 0 -BITMAP -0310 -07E0 -08C0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR Odieresis -ENCODING 214 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 0 0 -BITMAP -0660 -0660 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR multiply -ENCODING 215 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 10 0 0 -BITMAP -C0C0 -E1C0 -7380 -3F00 -1E00 -1E00 -3F00 -7380 -E1C0 -C0C0 -ENDCHAR -STARTCHAR Oslash -ENCODING 216 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -0FC8 -38F0 -7078 -7078 -E0BC -E11C -E21C -E21C -E41C -E83C -7038 -7078 -78F0 -8FC0 -ENDCHAR -STARTCHAR Ugrave -ENCODING 217 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR Uacute -ENCODING 218 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR Ucircumflex -ENCODING 219 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 0 -BITMAP -0380 -07C0 -0C60 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR Udieresis -ENCODING 220 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0CC0 -0CC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR Yacute -ENCODING 221 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR Thorn -ENCODING 222 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 12 14 1 0 -BITMAP -F800 -7000 -7000 -7FC0 -70F0 -7070 -7070 -7070 -7070 -70E0 -7F80 -7000 -7000 -F800 -ENDCHAR -STARTCHAR germandbls -ENCODING 223 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -1E00 -3380 -71C0 -71C0 -71C0 -7180 -7700 -71C0 -70E0 -70E0 -70E0 -70E0 -71C0 -F700 -ENDCHAR -STARTCHAR agrave -ENCODING 224 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR aacute -ENCODING 225 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -0600 -0E00 -1C00 -3000 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR acircumflex -ENCODING 226 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -1C00 -3E00 -6300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR atilde -ENCODING 227 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -1880 -3F00 -4600 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR adieresis -ENCODING 228 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -3300 -3300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR aring -ENCODING 229 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -0C00 -1200 -1200 -0C00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR ae -ENCODING 230 -SWIDTH 870 0 -DWIDTH 17 0 -BBX 16 9 0 0 -BITMAP -3F78 -63CE -E387 -0787 -3BFF -E380 -E381 -E7C3 -78FC -ENDCHAR -STARTCHAR ccedilla -ENCODING 231 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 13 0 -4 -BITMAP -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -1000 -1C00 -0C00 -3800 -ENDCHAR -STARTCHAR egrave -ENCODING 232 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR eacute -ENCODING 233 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -0600 -0E00 -1C00 -3000 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR ecircumflex -ENCODING 234 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -0E00 -1F00 -3180 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR edieresis -ENCODING 235 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -3300 -3300 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR igrave -ENCODING 236 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 14 0 0 -BITMAP -C0 -E0 -70 -18 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR iacute -ENCODING 237 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 14 0 0 -BITMAP -18 -38 -70 -C0 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR icircumflex -ENCODING 238 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 7 13 -1 0 -BITMAP -38 -7C -C6 -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR idieresis -ENCODING 239 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 6 12 0 0 -BITMAP -CC -CC -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR eth -ENCODING 240 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -6000 -1B00 -1C00 -6600 -0300 -1F80 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR ntilde -ENCODING 241 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 0 -BITMAP -0C40 -1F80 -2300 -0000 -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR ograve -ENCODING 242 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR oacute -ENCODING 243 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR ocircumflex -ENCODING 244 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -0E00 -1F00 -3180 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR otilde -ENCODING 245 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -1880 -3F00 -4600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR odieresis -ENCODING 246 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 0 -BITMAP -1980 -1980 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR divide -ENCODING 247 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 10 0 0 -BITMAP -0C00 -0C00 -0000 -0000 -FFC0 -FFC0 -0000 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR oslash -ENCODING 248 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 11 0 -1 -BITMAP -0100 -1F00 -7380 -E3C0 -E5C0 -E5C0 -E9C0 -E9C0 -7380 -3E00 -2000 -ENDCHAR -STARTCHAR ugrave -ENCODING 249 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uacute -ENCODING 250 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR ucircumflex -ENCODING 251 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 0 -BITMAP -0700 -0F80 -18C0 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR udieresis -ENCODING 252 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 0 -BITMAP -1980 -1980 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR yacute -ENCODING 253 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -0180 -0380 -0700 -0C00 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR thorn -ENCODING 254 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 12 18 -1 -4 -BITMAP -F000 -7000 -7000 -7000 -7000 -7780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -7780 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR ydieresis -ENCODING 255 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 -4 -BITMAP -1980 -1980 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR Amacron -ENCODING 256 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 17 0 0 -BITMAP -0FC0 -0FC0 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR amacron -ENCODING 257 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -3F00 -3F00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR Abreve -ENCODING 258 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0840 -0CC0 -0780 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR abreve -ENCODING 259 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -2100 -3300 -1E00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR Aogonek -ENCODING 260 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 -4 -BITMAP -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -0180 -0300 -0340 -0180 -ENDCHAR -STARTCHAR aogonek -ENCODING 261 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 13 0 -4 -BITMAP -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -0C00 -1800 -1A00 -0C00 -ENDCHAR -STARTCHAR Cacute -ENCODING 262 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -ENDCHAR -STARTCHAR cacute -ENCODING 263 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -ENDCHAR -STARTCHAR Ccircumflex -ENCODING 264 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 19 1 0 -BITMAP -0200 -0700 -0F80 -18C0 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -ENDCHAR -STARTCHAR ccircumflex -ENCODING 265 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -0800 -1C00 -3E00 -6300 -0000 -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -ENDCHAR -STARTCHAR Cdotaccent -ENCODING 266 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 17 1 0 -BITMAP -0600 -0600 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -ENDCHAR -STARTCHAR cdotaccent -ENCODING 267 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 12 0 0 -BITMAP -0C00 -0C00 -0000 -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -ENDCHAR -STARTCHAR Ccaron -ENCODING 268 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -ENDCHAR -STARTCHAR ccaron -ENCODING 269 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -6300 -3E00 -1C00 -0800 -0000 -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -ENDCHAR -STARTCHAR Dcaron -ENCODING 270 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -ENDCHAR -STARTCHAR dcaron -ENCODING 271 -SWIDTH 875 0 -DWIDTH 17 0 -BBX 16 14 0 0 -BITMAP -01E6 -00EF -00EF -00E7 -00E2 -1EE4 -71E8 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -ENDCHAR -STARTCHAR Dcroat -ENCODING 272 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -7FE0 -3878 -383C -381C -381E -380E -FE0E -380E -380E -381E -381C -383C -3878 -7FE0 -ENDCHAR -STARTCHAR dcroat -ENCODING 273 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -01E0 -00E0 -00E0 -01F0 -01F0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -ENDCHAR -STARTCHAR Emacron -ENCODING 274 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -1F80 -1F80 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR emacron -ENCODING 275 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -3F00 -3F00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR Ebreve -ENCODING 276 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 0 -BITMAP -1080 -1980 -0F00 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR ebreve -ENCODING 277 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -2100 -3300 -1E00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR Edotaccent -ENCODING 278 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR edotaccent -ENCODING 279 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -0C00 -0C00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR Eogonek -ENCODING 280 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 -4 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0600 -0C00 -0D00 -0600 -ENDCHAR -STARTCHAR eogonek -ENCODING 281 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 -4 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0C00 -1800 -1A00 -0C00 -ENDCHAR -STARTCHAR Ecaron -ENCODING 282 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR ecaron -ENCODING 283 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR Gcircumflex -ENCODING 284 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -0200 -0700 -0F80 -18C0 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR gcircumflex -ENCODING 285 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 20 0 -4 -BITMAP -0200 -0700 -0F80 -18C0 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR Gbreve -ENCODING 286 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 18 1 0 -BITMAP -1080 -1980 -0F00 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR gbreve -ENCODING 287 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 19 0 -4 -BITMAP -1080 -1980 -0F00 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR Gdotaccent -ENCODING 288 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 17 1 0 -BITMAP -0600 -0600 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR gdotaccent -ENCODING 289 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 18 0 -4 -BITMAP -0600 -0600 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR Gcommaaccent -ENCODING 290 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 22 1 -8 -BITMAP -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -0000 -0300 -0780 -0780 -0380 -0100 -0200 -0400 -ENDCHAR -STARTCHAR gcommaaccent -ENCODING 291 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 23 0 -4 -BITMAP -0100 -0200 -0400 -0E00 -0F00 -0F00 -0600 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR Hcircumflex -ENCODING 292 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0100 -0380 -07C0 -0C60 -0000 -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR hcircumflex -ENCODING 293 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 19 0 0 -BITMAP -1000 -3800 -7C00 -C600 -0000 -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR Hbar -ENCODING 294 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FCFC -7038 -7038 -7038 -FFFC -FFFC -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR hbar -ENCODING 295 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -F000 -7000 -7000 -7C00 -7C00 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR Itilde -ENCODING 296 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 8 18 1 0 -BITMAP -31 -7E -8C -00 -7C -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR itilde -ENCODING 297 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 8 13 -1 0 -BITMAP -31 -7E -8C -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR Imacron -ENCODING 298 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 17 2 0 -BITMAP -FC -FC -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR imacron -ENCODING 299 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 6 12 -1 0 -BITMAP -FC -FC -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR Ibreve -ENCODING 300 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 18 2 0 -BITMAP -84 -CC -78 -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR ibreve -ENCODING 301 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 6 13 -1 0 -BITMAP -84 -CC -78 -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR Iogonek -ENCODING 302 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 18 2 -4 -BITMAP -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -30 -60 -68 -30 -ENDCHAR -STARTCHAR iogonek -ENCODING 303 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 18 0 -4 -BITMAP -70 -70 -70 -00 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -30 -60 -68 -30 -ENDCHAR -STARTCHAR Idotaccent -ENCODING 304 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 17 2 0 -BITMAP -30 -30 -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR dotlessi -ENCODING 305 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 9 0 0 -BITMAP -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR IJ -ENCODING 306 -SWIDTH 1070 0 -DWIDTH 21 0 -BBX 18 14 2 0 -BITMAP -F80FC0 -700380 -700380 -700380 -700380 -700380 -700380 -700380 -70C380 -71E380 -71E380 -718780 -708F00 -F87C00 -ENDCHAR -STARTCHAR ij -ENCODING 307 -SWIDTH 704 0 -DWIDTH 12 0 -BBX 10 18 0 -4 -BITMAP -71C0 -71C0 -71C0 -0000 -0000 -F3C0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -F9C0 -01C0 -1DC0 -1D80 -0F00 -ENDCHAR -STARTCHAR Jcircumflex -ENCODING 308 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 11 19 0 0 -BITMAP -0100 -0380 -07C0 -0C60 -0000 -07E0 -01C0 -01C0 -01C0 -01C0 -01C0 -01C0 -01C0 -61C0 -F1C0 -F1C0 -C3C0 -4780 -3E00 -ENDCHAR -STARTCHAR jcircumflex -ENCODING 309 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 8 18 -3 -4 -BITMAP -08 -1C -3E -63 -00 -1E -0E -0E -0E -0E -0E -0E -0E -0E -0E -EE -EC -78 -ENDCHAR -STARTCHAR Kcommaaccent -ENCODING 310 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 22 1 -8 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -0000 -0180 -03C0 -03C0 -01C0 -0080 -0100 -0200 -ENDCHAR -STARTCHAR kcommaaccent -ENCODING 311 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 22 0 -8 -BITMAP -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -0000 -0600 -0F00 -0F00 -0700 -0200 -0400 -0800 -ENDCHAR -STARTCHAR kgreenlandic -ENCODING 312 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 9 0 0 -BITMAP -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -ENDCHAR -STARTCHAR Lacute -ENCODING 313 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 19 1 0 -BITMAP -0600 -0E00 -1C00 -3000 -0000 -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR lacute -ENCODING 314 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 5 19 0 0 -BITMAP -18 -38 -70 -C0 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Lcommaaccent -ENCODING 315 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 22 1 -8 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -0000 -0C00 -1E00 -1E00 -0E00 -0400 -0800 -1000 -ENDCHAR -STARTCHAR lcommaaccent -ENCODING 316 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 5 22 0 -8 -BITMAP -F0 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -00 -30 -78 -78 -38 -10 -20 -40 -ENDCHAR -STARTCHAR Lcaron -ENCODING 317 -SWIDTH 927 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FC18 -703C -703C -701C -7008 -7010 -7020 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR lcaron -ENCODING 318 -SWIDTH 575 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -F180 -73C0 -73C0 -71C0 -7080 -7100 -7200 -7000 -7000 -7000 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR Ldot -ENCODING 319 -SWIDTH 964 0 -DWIDTH 16 0 -BBX 14 14 1 0 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7018 -703C -703C -7038 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR ldot -ENCODING 320 -SWIDTH 612 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -F000 -7000 -7000 -7000 -7000 -7000 -7000 -7180 -73C0 -73C0 -7180 -7000 -7000 -F800 -ENDCHAR -STARTCHAR Lslash -ENCODING 321 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 12 14 -1 0 -BITMAP -7E00 -3C00 -3C00 -3C00 -3D00 -3E00 -3C00 -3C00 -7C00 -BC10 -3C10 -3C30 -3C70 -7FF0 -ENDCHAR -STARTCHAR lslash -ENCODING 322 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 6 14 0 0 -BITMAP -F0 -70 -70 -70 -74 -78 -70 -F0 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Nacute -ENCODING 323 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR nacute -ENCODING 324 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR Ncommaaccent -ENCODING 325 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 22 1 -8 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -0000 -0300 -0780 -0780 -0380 -0100 -0200 -0400 -ENDCHAR -STARTCHAR ncommaaccent -ENCODING 326 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 -8 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -0600 -0F00 -0F00 -0700 -0200 -0400 -0800 -ENDCHAR -STARTCHAR Ncaron -ENCODING 327 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR ncaron -ENCODING 328 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR napostrophe -ENCODING 329 -SWIDTH 914 0 -DWIDTH 18 0 -BBX 17 14 0 0 -BITMAP -600000 -F00000 -F00000 -700000 -200000 -47BE00 -83CF00 -038700 -038700 -038700 -038700 -038700 -038700 -07CF80 -ENDCHAR -STARTCHAR Eng -ENCODING 330 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 1 -4 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F838 -0038 -03B8 -03B0 -01E0 -ENDCHAR -STARTCHAR eng -ENCODING 331 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 11 13 0 -4 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F8E0 -00E0 -0EE0 -0EC0 -0780 -ENDCHAR -STARTCHAR Omacron -ENCODING 332 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 0 0 -BITMAP -07E0 -07E0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR omacron -ENCODING 333 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 0 -BITMAP -1F80 -1F80 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR Obreve -ENCODING 334 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 0 -BITMAP -0420 -0660 -03C0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR obreve -ENCODING 335 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -1080 -1980 -0F00 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR Ohungarumlaut -ENCODING 336 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 0 0 -BITMAP -0660 -0660 -0CC0 -0880 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR ohungarumlaut -ENCODING 337 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -1980 -1980 -3300 -2200 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR OE -ENCODING 338 -SWIDTH 1000 0 -DWIDTH 22 0 -BBX 21 14 0 0 -BITMAP -0FFFF8 -3C7C38 -783C18 -783C48 -F03C48 -F03CC0 -F03FC0 -F03CC0 -F03C40 -F03C48 -783C08 -783C18 -3C7C38 -0FFFF8 -ENDCHAR -STARTCHAR oe -ENCODING 339 -SWIDTH 907 0 -DWIDTH 19 0 -BBX 18 9 0 0 -BITMAP -1F1E00 -71F380 -E0E1C0 -E0E1C0 -E0FFC0 -E0E000 -E0E040 -71F0C0 -1F1F00 -ENDCHAR -STARTCHAR Racute -ENCODING 340 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR racute -ENCODING 341 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 14 0 0 -BITMAP -06 -0E -1C -30 -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Rcommaaccent -ENCODING 342 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 22 1 -8 -BITMAP -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -0000 -0300 -0780 -0780 -0380 -0100 -0200 -0400 -ENDCHAR -STARTCHAR rcommaaccent -ENCODING 343 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 17 0 -8 -BITMAP -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -00 -30 -78 -78 -38 -10 -20 -40 -ENDCHAR -STARTCHAR Rcaron -ENCODING 344 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR rcaron -ENCODING 345 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 14 0 0 -BITMAP -63 -3E -1C -08 -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR Sacute -ENCODING 346 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 19 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -ENDCHAR -STARTCHAR sacute -ENCODING 347 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -0600 -0E00 -1C00 -3000 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR Scircumflex -ENCODING 348 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 19 0 0 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -ENDCHAR -STARTCHAR scircumflex -ENCODING 349 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -0800 -1C00 -3E00 -6300 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR Scedilla -ENCODING 350 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR scedilla -ENCODING 351 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 13 0 -4 -BITMAP -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -1000 -1C00 -0C00 -3800 -ENDCHAR -STARTCHAR Scaron -ENCODING 352 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 10 14 0 0 -BITMAP -6180 -3300 -1E00 -0C00 -0000 -3F80 -7180 -7880 -7E00 -3F00 -0F80 -83C0 -C780 -BF00 -ENDCHAR -STARTCHAR scaron -ENCODING 353 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 14 0 0 -BITMAP -C300 -6600 -3C00 -1800 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR Tcommaaccent -ENCODING 354 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 18 1 -4 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR tcommaaccent -ENCODING 355 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 17 0 -4 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -20 -38 -18 -70 -ENDCHAR -STARTCHAR Tcaron -ENCODING 356 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -ENDCHAR -STARTCHAR tcaron -ENCODING 357 -SWIDTH 646 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -0060 -10F0 -30F0 -3070 -7020 -FC40 -7080 -7000 -7000 -7000 -7000 -7200 -7200 -3C00 -ENDCHAR -STARTCHAR Tbar -ENCODING 358 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -1F00 -1F00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -ENDCHAR -STARTCHAR tbar -ENCODING 359 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 13 0 0 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -7C -7C -72 -72 -3C -ENDCHAR -STARTCHAR Utilde -ENCODING 360 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 0 -BITMAP -0620 -0FC0 -1180 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR utilde -ENCODING 361 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 0 -BITMAP -0C40 -1F80 -2300 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Umacron -ENCODING 362 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0FC0 -0FC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR umacron -ENCODING 363 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 0 -BITMAP -1F80 -1F80 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Ubreve -ENCODING 364 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 0 -BITMAP -0840 -0CC0 -0780 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR ubreve -ENCODING 365 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 0 -BITMAP -1080 -1980 -0F00 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Uring -ENCODING 366 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0300 -0480 -0480 -0300 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uring -ENCODING 367 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -0600 -0900 -0900 -0600 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Uhungarumlaut -ENCODING 368 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0CC0 -0CC0 -1980 -1100 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uhungarumlaut -ENCODING 369 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -0CC0 -0CC0 -1980 -1100 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Uogonek -ENCODING 370 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 -4 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -0600 -0C00 -0D00 -0600 -ENDCHAR -STARTCHAR uogonek -ENCODING 371 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 -4 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -0300 -0600 -0680 -0300 -ENDCHAR -STARTCHAR Wcircumflex -ENCODING 372 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 19 0 0 -BITMAP -008000 -01C000 -03E000 -063000 -000000 -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR wcircumflex -ENCODING 373 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 14 -1 0 -BITMAP -0100 -0380 -07C0 -0C60 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR Ycircumflex -ENCODING 374 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -0200 -0700 -0F80 -18C0 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR ycircumflex -ENCODING 375 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -0800 -1C00 -3E00 -6300 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR Ydieresis -ENCODING 376 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 14 0 0 -BITMAP -0CC0 -0CC0 -0000 -0000 -0000 -FCF8 -7870 -3CE0 -1FC0 -0F80 -0780 -0780 -0780 -0FC0 -ENDCHAR -STARTCHAR Zacute -ENCODING 377 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -ENDCHAR -STARTCHAR zacute -ENCODING 378 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 14 0 0 -BITMAP -06 -0E -1C -30 -00 -FF -CF -8E -1C -38 -39 -71 -F3 -FF -ENDCHAR -STARTCHAR Zdotaccent -ENCODING 379 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -ENDCHAR -STARTCHAR zdotaccent -ENCODING 380 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 12 0 0 -BITMAP -18 -18 -00 -FF -CF -8E -1C -38 -39 -71 -F3 -FF -ENDCHAR -STARTCHAR Zcaron -ENCODING 381 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -30C0 -1980 -0F00 -0600 -0000 -FFF0 -C1E0 -83C0 -0780 -0F10 -1E10 -3C30 -7870 -FFF0 -ENDCHAR -STARTCHAR zcaron -ENCODING 382 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 14 0 0 -BITMAP -C3 -66 -3C -18 -00 -FF -C7 -8F -1E -3C -79 -F1 -E3 -FF -ENDCHAR -STARTCHAR uni0186 -ENCODING 390 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 14 1 0 -BITMAP -1F00 -63C0 -41E0 -80E0 -80F0 -0070 -0070 -0070 -8070 -80F0 -C0E0 -C1E0 -E3C0 -9F00 -ENDCHAR -STARTCHAR uni0189 -ENCODING 393 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -7FE0 -3878 -383C -381C -381E -380E -FE0E -380E -380E -381E -381C -383C -3878 -7FE0 -ENDCHAR -STARTCHAR uni018E -ENCODING 398 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -E1C0 -C1C0 -81C0 -91C0 -11C0 -19C0 -1FC0 -19C0 -91C0 -91C0 -C1C0 -E1C0 -FFE0 -ENDCHAR -STARTCHAR florin -ENCODING 402 -SWIDTH 574 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -01C0 -0360 -0760 -0700 -0700 -1FC0 -0E00 -0E00 -0E00 -0E00 -0E00 -1C00 -1C00 -1C00 -1C00 -DC00 -D800 -7000 -ENDCHAR -STARTCHAR uni0197 -ENCODING 407 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 14 2 0 -BITMAP -F8 -70 -70 -70 -70 -70 -F8 -F8 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni019A -ENCODING 410 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 5 14 0 0 -BITMAP -F0 -70 -70 -70 -70 -70 -F8 -F8 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni019D -ENCODING 413 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 18 -1 -4 -BITMAP -3E0F80 -1F0700 -0F0200 -0F8200 -0BC200 -09E200 -08E200 -087200 -087A00 -083A00 -0E1E00 -0E1E00 -0E0E00 -0E0600 -0E0000 -EE0000 -EC0000 -780000 -ENDCHAR -STARTCHAR uni019F -ENCODING 415 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 0 0 -BITMAP -0FE0 -3C78 -783C -701C -F01E -E00E -FFFE -FFFE -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR Ohorn -ENCODING 416 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 18 14 0 0 -BITMAP -0FE180 -3C7BC0 -783FC0 -701DC0 -F01E80 -E00F00 -E00E00 -E00E00 -E00E00 -F01E00 -701C00 -783C00 -3C7800 -0FE000 -ENDCHAR -STARTCHAR ohorn -ENCODING 417 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 14 9 0 0 -BITMAP -1F18 -71FC -E0FC -E0FC -E0E8 -E0F0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni01A7 -ENCODING 423 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -5F80 -70C0 -6060 -4060 -00E0 -0FE0 -7FC0 -FFC0 -FE00 -E020 -C020 -C060 -60E0 -3FA0 -ENDCHAR -STARTCHAR uni01A8 -ENCODING 424 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 9 0 0 -BITMAP -5E00 -6300 -4380 -1F80 -7F00 -F800 -E080 -6180 -3E80 -ENDCHAR -STARTCHAR uni01AE -ENCODING 430 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 18 1 -4 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0EE0 -06E0 -03C0 -ENDCHAR -STARTCHAR Uhorn -ENCODING 431 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 14 1 0 -BITMAP -F87F00 -703F80 -701780 -701380 -701100 -701200 -701400 -701000 -701000 -701000 -701000 -701000 -382000 -1FC000 -ENDCHAR -STARTCHAR uhorn -ENCODING 432 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 15 9 0 0 -BITMAP -F1EC -70FE -70FE -70EE -70E4 -70E8 -70F0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01B5 -ENCODING 437 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -1F00 -1F00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -ENDCHAR -STARTCHAR uni01B6 -ENCODING 438 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 9 0 0 -BITMAP -FF -CF -8E -3E -3E -39 -71 -F3 -FF -ENDCHAR -STARTCHAR uni01BB -ENCODING 443 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -1E00 -6700 -E380 -E380 -6380 -0380 -FF80 -FF80 -0E00 -1800 -3000 -6080 -FF80 -FF80 -ENDCHAR -STARTCHAR uni01BC -ENCODING 444 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 9 14 1 0 -BITMAP -7F80 -7F00 -4000 -4000 -4000 -7E00 -4700 -0380 -0380 -6380 -E380 -E380 -6700 -3E00 -ENDCHAR -STARTCHAR uni01C0 -ENCODING 448 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 2 14 4 0 -BITMAP -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR uni01C2 -ENCODING 450 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 14 1 -2 -BITMAP -0C00 -0C00 -0C00 -0C00 -FF80 -FF80 -0C00 -0C00 -FF80 -FF80 -0C00 -0C00 -0C00 -0C00 -ENDCHAR -STARTCHAR uni01C3 -ENCODING 451 -SWIDTH 296 0 -DWIDTH 6 0 -BBX 4 14 1 0 -BITMAP -60 -F0 -F0 -F0 -F0 -F0 -60 -60 -60 -00 -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR uni01CD -ENCODING 461 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 19 0 0 -BITMAP -0C60 -07C0 -0380 -0100 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni01CE -ENCODING 462 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -6300 -3E00 -1C00 -0800 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni01CF -ENCODING 463 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 7 19 1 0 -BITMAP -C6 -7C -38 -10 -00 -7C -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR uni01D0 -ENCODING 464 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 7 14 -1 0 -BITMAP -C6 -7C -38 -10 -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR uni01D1 -ENCODING 465 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 0 0 -BITMAP -0C60 -07C0 -0380 -0100 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni01D2 -ENCODING 466 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni01D3 -ENCODING 467 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni01D4 -ENCODING 468 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01D5 -ENCODING 469 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 20 1 0 -BITMAP -0FC0 -0FC0 -0000 -0CC0 -0CC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni01D6 -ENCODING 470 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 15 0 0 -BITMAP -1F80 -1F80 -0000 -1980 -1980 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01D7 -ENCODING 471 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 22 1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0CC0 -0CC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni01D8 -ENCODING 472 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -1980 -1980 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01D9 -ENCODING 473 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 22 1 0 -BITMAP -0C60 -07C0 -0380 -0100 -0000 -0CC0 -0CC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni01DA -ENCODING 474 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -3180 -1F00 -0E00 -0400 -0000 -1980 -1980 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01DB -ENCODING 475 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 22 1 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -0CC0 -0CC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni01DC -ENCODING 476 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -1980 -1980 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni01DD -ENCODING 477 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -3E00 -C380 -81C0 -01C0 -FFC0 -E1C0 -E1C0 -7380 -1E00 -ENDCHAR -STARTCHAR uni01DE -ENCODING 478 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 20 0 0 -BITMAP -0FC0 -0FC0 -0000 -0CC0 -0CC0 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni01DF -ENCODING 479 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 15 0 0 -BITMAP -3F00 -3F00 -0000 -3300 -3300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni01E0 -ENCODING 480 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 20 0 0 -BITMAP -0FC0 -0FC0 -0000 -0300 -0300 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni01E1 -ENCODING 481 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 15 0 0 -BITMAP -3F00 -3F00 -0000 -0C00 -0C00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni01E2 -ENCODING 482 -SWIDTH 981 0 -DWIDTH 21 0 -BBX 20 17 0 0 -BITMAP -007E00 -007E00 -000000 -03FFF0 -00B870 -01B830 -013890 -033890 -063980 -043F80 -0C3980 -1FF880 -103890 -203810 -203830 -603870 -F1FFF0 -ENDCHAR -STARTCHAR uni01E3 -ENCODING 483 -SWIDTH 870 0 -DWIDTH 17 0 -BBX 16 12 0 0 -BITMAP -07E0 -07E0 -0000 -3F78 -63CE -E387 -0787 -3BFF -E380 -E381 -E7C3 -78FC -ENDCHAR -STARTCHAR uni01E4 -ENCODING 484 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 14 14 1 0 -BITMAP -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -787C -3CFC -0F90 -ENDCHAR -STARTCHAR uni01E5 -ENCODING 485 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 15 0 -4 -BITMAP -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -FFE0 -FFE0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR Gcaron -ENCODING 486 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR gcaron -ENCODING 487 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 20 0 -4 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR uni01E8 -ENCODING 488 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 19 1 0 -BITMAP -18C0 -0F80 -0700 -0200 -0000 -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -ENDCHAR -STARTCHAR uni01E9 -ENCODING 489 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 19 0 0 -BITMAP -C600 -7C00 -3800 -1000 -0000 -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -ENDCHAR -STARTCHAR uni01EA -ENCODING 490 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 -4 -BITMAP -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -0180 -0300 -0340 -0180 -ENDCHAR -STARTCHAR uni01EB -ENCODING 491 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 -4 -BITMAP -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -0600 -0C00 -0D00 -0600 -ENDCHAR -STARTCHAR uni01EC -ENCODING 492 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 21 0 -4 -BITMAP -07E0 -07E0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -0180 -0300 -0340 -0180 -ENDCHAR -STARTCHAR uni01ED -ENCODING 493 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 -4 -BITMAP -1F80 -1F80 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -0600 -0C00 -0D00 -0600 -ENDCHAR -STARTCHAR uni01F0 -ENCODING 496 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 8 18 -3 -4 -BITMAP -63 -3E -1C -08 -00 -1E -0E -0E -0E -0E -0E -0E -0E -0E -0E -EE -EC -78 -ENDCHAR -STARTCHAR uni01F4 -ENCODING 500 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR uni01F5 -ENCODING 501 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 20 0 -4 -BITMAP -0180 -0380 -0700 -0C00 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR uni01F8 -ENCODING 504 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 1 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR uni01F9 -ENCODING 505 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR Aringacute -ENCODING 506 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 23 0 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0300 -0480 -0480 -0300 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR aringacute -ENCODING 507 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 19 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -0C00 -1200 -1200 -0C00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR AEacute -ENCODING 508 -SWIDTH 981 0 -DWIDTH 21 0 -BBX 20 19 0 0 -BITMAP -000600 -000E00 -001C00 -003000 -000000 -03FFF0 -00B870 -01B830 -013890 -033890 -063980 -043F80 -0C3980 -1FF880 -103890 -203810 -203830 -603870 -F1FFF0 -ENDCHAR -STARTCHAR aeacute -ENCODING 509 -SWIDTH 870 0 -DWIDTH 17 0 -BBX 16 14 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -3F78 -63CE -E387 -0787 -3BFF -E380 -E381 -E7C3 -78FC -ENDCHAR -STARTCHAR Oslashacute -ENCODING 510 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0FC8 -38F0 -7078 -7078 -E0BC -E11C -E21C -E21C -E41C -E83C -7038 -7078 -78F0 -8FC0 -ENDCHAR -STARTCHAR oslashacute -ENCODING 511 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 16 0 -1 -BITMAP -0300 -0700 -0E00 -1800 -0000 -0100 -1F00 -7380 -E3C0 -E5C0 -E5C0 -E9C0 -E9C0 -7380 -3E00 -2000 -ENDCHAR -STARTCHAR uni0200 -ENCODING 512 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 19 0 0 -BITMAP -1980 -1980 -0CC0 -0440 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni0201 -ENCODING 513 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -6600 -6600 -3300 -1100 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni0202 -ENCODING 514 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0780 -0CC0 -0840 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni0203 -ENCODING 515 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -1E00 -3300 -2100 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni0204 -ENCODING 516 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -3300 -3300 -1980 -0880 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni0205 -ENCODING 517 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 0 -BITMAP -6600 -6600 -3300 -1100 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni0206 -ENCODING 518 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 0 -BITMAP -0F00 -1980 -1080 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni0207 -ENCODING 519 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -1E00 -3300 -2100 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni0208 -ENCODING 520 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 7 19 1 0 -BITMAP -CC -CC -66 -22 -00 -7C -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR uni0209 -ENCODING 521 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 7 14 -2 0 -BITMAP -CC -CC -66 -22 -00 -3C -1C -1C -1C -1C -1C -1C -1C -3E -ENDCHAR -STARTCHAR uni020A -ENCODING 522 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 18 2 0 -BITMAP -78 -CC -84 -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni020B -ENCODING 523 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 6 13 -1 0 -BITMAP -78 -CC -84 -00 -78 -38 -38 -38 -38 -38 -38 -38 -7C -ENDCHAR -STARTCHAR uni020C -ENCODING 524 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 0 0 -BITMAP -0CC0 -0CC0 -0660 -0220 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni020D -ENCODING 525 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -3300 -3300 -1980 -0880 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni020E -ENCODING 526 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 18 0 0 -BITMAP -03C0 -0660 -0420 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni020F -ENCODING 527 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -0F00 -1980 -1080 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni0210 -ENCODING 528 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -1980 -1980 -0CC0 -0440 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR uni0211 -ENCODING 529 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 14 0 0 -BITMAP -CC -CC -66 -22 -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni0212 -ENCODING 530 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 18 1 0 -BITMAP -0F00 -1980 -1080 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR uni0213 -ENCODING 531 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 13 0 0 -BITMAP -3C -66 -42 -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni0214 -ENCODING 532 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -1980 -1980 -0CC0 -0440 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni0215 -ENCODING 533 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 0 -BITMAP -3300 -3300 -1980 -0880 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni0216 -ENCODING 534 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 0 -BITMAP -0780 -0CC0 -0840 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni0217 -ENCODING 535 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 0 -BITMAP -0F00 -1980 -1080 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR Scommaaccent -ENCODING 536 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 22 0 -8 -BITMAP -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -0000 -0C00 -1E00 -1E00 -0E00 -0400 -0800 -1000 -ENDCHAR -STARTCHAR scommaaccent -ENCODING 537 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 17 0 -8 -BITMAP -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -0000 -1800 -3C00 -3C00 -1C00 -0800 -1000 -2000 -ENDCHAR -STARTCHAR Tcommaaccent -ENCODING 538 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 22 1 -8 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -0000 -0600 -0F00 -0F00 -0700 -0200 -0400 -0800 -ENDCHAR -STARTCHAR tcommaaccent -ENCODING 539 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 21 0 -8 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -00 -30 -78 -78 -38 -10 -20 -40 -ENDCHAR -STARTCHAR uni021E -ENCODING 542 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 19 1 0 -BITMAP -0C60 -07C0 -0380 -0100 -0000 -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR uni021F -ENCODING 543 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 19 0 0 -BITMAP -C600 -7C00 -3800 -1000 -0000 -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR uni0226 -ENCODING 550 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 17 0 0 -BITMAP -0300 -0300 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni0227 -ENCODING 551 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 12 0 0 -BITMAP -0C00 -0C00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni0228 -ENCODING 552 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 -4 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR uni0229 -ENCODING 553 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 -4 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR uni022A -ENCODING 554 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 20 0 0 -BITMAP -07E0 -07E0 -0000 -0660 -0660 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni022B -ENCODING 555 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 15 0 0 -BITMAP -1F80 -1F80 -0000 -1980 -1980 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni022C -ENCODING 556 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 21 0 0 -BITMAP -07E0 -07E0 -0000 -0310 -07E0 -08C0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni022D -ENCODING 557 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 0 -BITMAP -3F00 -3F00 -0000 -1880 -3F00 -4600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni022E -ENCODING 558 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 0 0 -BITMAP -0180 -0180 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni022F -ENCODING 559 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 0 -BITMAP -0600 -0600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni0230 -ENCODING 560 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 20 0 0 -BITMAP -07E0 -07E0 -0000 -0180 -0180 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni0231 -ENCODING 561 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 15 0 0 -BITMAP -1F80 -1F80 -0000 -0600 -0600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni0232 -ENCODING 562 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 17 1 0 -BITMAP -1F80 -1F80 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR uni0233 -ENCODING 563 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 -4 -BITMAP -3F00 -3F00 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR uni0250 -ENCODING 592 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -F780 -79C0 -71C0 -71C0 -7700 -7800 -70C0 -71C0 -3F80 -ENDCHAR -STARTCHAR uni0254 -ENCODING 596 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 9 0 0 -BITMAP -7C00 -E700 -C380 -0380 -0380 -0380 -8380 -C700 -3C00 -ENDCHAR -STARTCHAR uni0258 -ENCODING 600 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -01C0 -81C0 -C380 -3E00 -ENDCHAR -STARTCHAR uni0259 -ENCODING 601 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 9 0 0 -BITMAP -3E00 -C380 -81C0 -01C0 -FFC0 -E1C0 -E1C0 -7380 -1E00 -ENDCHAR -STARTCHAR uni025F -ENCODING 607 -SWIDTH 389 0 -DWIDTH 7 0 -BBX 8 14 0 -5 -BITMAP -1F -0E -0E -0E -0E -0E -0E -0E -3F -0E -0E -EE -EC -78 -ENDCHAR -STARTCHAR uni0265 -ENCODING 613 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 -5 -BITMAP -F9F0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EE0 -00E0 -00E0 -00E0 -00E0 -00F0 -ENDCHAR -STARTCHAR uni0275 -ENCODING 629 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 9 0 0 -BITMAP -1F00 -71C0 -E0E0 -FFE0 -FFE0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni0279 -ENCODING 633 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 9 0 0 -BITMAP -1F -0E -0E -0E -0E -0E -CE -DE -EF -ENDCHAR -STARTCHAR uni0287 -ENCODING 647 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 13 0 0 -BITMAP -78 -9C -9C -1C -1C -1C -1C -1C -7E -1C -18 -18 -10 -ENDCHAR -STARTCHAR uni0288 -ENCODING 648 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 8 17 0 -4 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -70 -70 -70 -70 -77 -37 -1E -ENDCHAR -STARTCHAR uni0289 -ENCODING 649 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 9 0 0 -BITMAP -F1E0 -70E0 -70E0 -FFF0 -FFF0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni028C -ENCODING 652 -SWIDTH 611 0 -DWIDTH 9 0 -BBX 10 9 -1 0 -BITMAP -0C00 -0C00 -1E00 -1E00 -2700 -2700 -4380 -4380 -E7C0 -ENDCHAR -STARTCHAR uni028D -ENCODING 653 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 9 -1 0 -BITMAP -0C30 -0C30 -1E78 -1E78 -279C -279C -438E -438E -E7DF -ENDCHAR -STARTCHAR uni028E -ENCODING 654 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 13 0 0 -BITMAP -01C0 -02E0 -0460 -0400 -0E00 -0E00 -1700 -1700 -2380 -2380 -41C0 -41C0 -E3E0 -ENDCHAR -STARTCHAR uni029E -ENCODING 670 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 14 0 -5 -BITMAP -FDF0 -78E0 -3CE0 -1EE0 -0FE0 -06E0 -04E0 -18E0 -7CE0 -00E0 -00E0 -00E0 -00E0 -00F0 -ENDCHAR -STARTCHAR uni02BB -ENCODING 699 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -10 -20 -40 -E0 -F0 -F0 -60 -ENDCHAR -STARTCHAR afii57929 -ENCODING 700 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR afii64937 -ENCODING 701 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -60 -F0 -F0 -E0 -40 -20 -10 -ENDCHAR -STARTCHAR circumflex -ENCODING 710 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 7 4 0 10 -BITMAP -10 -38 -7C -C6 -ENDCHAR -STARTCHAR caron -ENCODING 711 -SWIDTH 333 0 -DWIDTH 10 0 -BBX 7 4 1 10 -BITMAP -C6 -7C -38 -10 -ENDCHAR -STARTCHAR uni02C8 -ENCODING 712 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 2 5 1 9 -BITMAP -C0 -C0 -C0 -C0 -C0 -ENDCHAR -STARTCHAR macron -ENCODING 713 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 6 2 1 10 -BITMAP -FC -FC -ENDCHAR -STARTCHAR uni02CA -ENCODING 714 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 10 -BITMAP -18 -38 -70 -C0 -ENDCHAR -STARTCHAR uni02CB -ENCODING 715 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 10 -BITMAP -C0 -E0 -70 -18 -ENDCHAR -STARTCHAR uni02CD -ENCODING 717 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 6 2 1 -3 -BITMAP -FC -FC -ENDCHAR -STARTCHAR uni02CE -ENCODING 718 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 -5 -BITMAP -C0 -E0 -70 -18 -ENDCHAR -STARTCHAR uni02CF -ENCODING 719 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 -5 -BITMAP -18 -38 -70 -C0 -ENDCHAR -STARTCHAR breve -ENCODING 728 -SWIDTH 333 0 -DWIDTH 8 0 -BBX 6 3 1 10 -BITMAP -84 -CC -78 -ENDCHAR -STARTCHAR dotaccent -ENCODING 729 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 2 2 2 10 -BITMAP -C0 -C0 -ENDCHAR -STARTCHAR ring -ENCODING 730 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 4 4 1 10 -BITMAP -60 -90 -90 -60 -ENDCHAR -STARTCHAR ogonek -ENCODING 731 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 4 4 1 -4 -BITMAP -60 -C0 -D0 -60 -ENDCHAR -STARTCHAR tilde -ENCODING 732 -SWIDTH 333 0 -DWIDTH 10 0 -BBX 8 3 1 10 -BITMAP -31 -7E -8C -ENDCHAR -STARTCHAR hungarumlaut -ENCODING 733 -SWIDTH 333 0 -DWIDTH 9 0 -BBX 7 4 1 10 -BITMAP -66 -66 -CC -88 -ENDCHAR -STARTCHAR uni02EE -ENCODING 750 -SWIDTH 481 0 -DWIDTH 10 0 -BBX 9 7 0 7 -BITMAP -6300 -F780 -F780 -7380 -2100 -4200 -8400 -ENDCHAR -STARTCHAR uni037E -ENCODING 894 -SWIDTH 278 0 -DWIDTH 6 0 -BBX 4 12 1 -3 -BITMAP -60 -F0 -F0 -60 -00 -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR tonos -ENCODING 900 -SWIDTH 333 0 -DWIDTH 7 0 -BBX 5 4 1 10 -BITMAP -18 -38 -70 -C0 -ENDCHAR -STARTCHAR dieresistonos -ENCODING 901 -SWIDTH 333 0 -DWIDTH 10 0 -BBX 6 7 2 10 -BITMAP -0C -1C -38 -60 -00 -CC -CC -ENDCHAR -STARTCHAR anoteleia -ENCODING 903 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 4 4 0 3 -BITMAP -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR mu -ENCODING 956 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 -4 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -7EF0 -6000 -7000 -7000 -2000 -ENDCHAR -STARTCHAR uni1E00 -ENCODING 7680 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 19 0 -5 -BITMAP -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -0000 -0180 -0240 -0240 -0180 -ENDCHAR -STARTCHAR uni1E01 -ENCODING 7681 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 14 0 -5 -BITMAP -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -0000 -0C00 -1200 -1200 -0C00 -ENDCHAR -STARTCHAR uni1E02 -ENCODING 7682 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 17 1 0 -BITMAP -0600 -0600 -0000 -FFC0 -71E0 -70E0 -70E0 -70E0 -71C0 -7F80 -70E0 -70F0 -7070 -7070 -7070 -70E0 -FF80 -ENDCHAR -STARTCHAR uni1E03 -ENCODING 7683 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 12 17 -1 0 -BITMAP -1800 -1800 -0000 -F000 -7000 -7000 -7000 -7000 -7780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -6F80 -ENDCHAR -STARTCHAR uni1E04 -ENCODING 7684 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 17 1 -3 -BITMAP -FFC0 -71E0 -70E0 -70E0 -70E0 -71C0 -7F80 -70E0 -70F0 -7070 -7070 -7070 -70E0 -FF80 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E05 -ENCODING 7685 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 12 17 -1 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -7780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -6F80 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E06 -ENCODING 7686 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 17 1 -3 -BITMAP -FFC0 -71E0 -70E0 -70E0 -70E0 -71C0 -7F80 -70E0 -70F0 -7070 -7070 -7070 -70E0 -FF80 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E07 -ENCODING 7687 -SWIDTH 648 0 -DWIDTH 12 0 -BBX 12 17 -1 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -7780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -6F80 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E08 -ENCODING 7688 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 12 23 1 -4 -BITMAP -0180 -0380 -0700 -0C00 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E000 -F010 -7010 -7820 -3C60 -0F80 -0400 -0700 -0300 -0E00 -ENDCHAR -STARTCHAR uni1E09 -ENCODING 7689 -SWIDTH 556 0 -DWIDTH 10 0 -BBX 9 18 0 -4 -BITMAP -0600 -0E00 -1C00 -3000 -0000 -1F00 -7380 -E180 -E000 -E000 -E000 -E080 -7180 -1E00 -1000 -1C00 -0C00 -3800 -ENDCHAR -STARTCHAR uni1E0A -ENCODING 7690 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0300 -0300 -0000 -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -ENDCHAR -STARTCHAR uni1E0B -ENCODING 7691 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -0180 -0180 -0000 -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -ENDCHAR -STARTCHAR uni1E0C -ENCODING 7692 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E0D -ENCODING 7693 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E0E -ENCODING 7694 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -0000 -0FC0 -0FC0 -ENDCHAR -STARTCHAR uni1E0F -ENCODING 7695 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E10 -ENCODING 7696 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 -4 -BITMAP -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -0400 -0700 -0300 -0E00 -ENDCHAR -STARTCHAR uni1E11 -ENCODING 7697 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 18 0 -4 -BITMAP -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -0400 -0700 -0300 -0E00 -ENDCHAR -STARTCHAR uni1E12 -ENCODING 7698 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 -5 -BITMAP -FFC0 -70F0 -7078 -7038 -703C -701C -701C -701C -701C -703C -7038 -7078 -70F0 -FFC0 -0000 -0200 -0700 -0F80 -18C0 -ENDCHAR -STARTCHAR uni1E13 -ENCODING 7699 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 19 0 -5 -BITMAP -01E0 -00E0 -00E0 -00E0 -00E0 -1EE0 -71E0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71E0 -1EF0 -0000 -0200 -0700 -0F80 -18C0 -ENDCHAR -STARTCHAR uni1E14 -ENCODING 7700 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 22 1 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -1F80 -1F80 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1E15 -ENCODING 7701 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 17 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -3F00 -3F00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1E16 -ENCODING 7702 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 22 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -1F80 -1F80 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1E17 -ENCODING 7703 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 17 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -3F00 -3F00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1E18 -ENCODING 7704 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 19 1 -5 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0000 -0400 -0E00 -1F00 -3180 -ENDCHAR -STARTCHAR uni1E19 -ENCODING 7705 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 14 0 -5 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0000 -0800 -1C00 -3E00 -6300 -ENDCHAR -STARTCHAR uni1E1A -ENCODING 7706 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 -4 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0000 -1880 -3F00 -4600 -ENDCHAR -STARTCHAR uni1E1B -ENCODING 7707 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 -4 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0000 -1880 -3F00 -4600 -ENDCHAR -STARTCHAR uni1E1C -ENCODING 7708 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 22 1 -4 -BITMAP -2100 -3300 -1E00 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR uni1E1D -ENCODING 7709 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 17 0 -4 -BITMAP -2100 -3300 -1E00 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0800 -0E00 -0600 -1C00 -ENDCHAR -STARTCHAR uni1E1E -ENCODING 7710 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7320 -7F00 -7300 -7100 -7100 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR uni1E1F -ENCODING 7711 -SWIDTH 389 0 -DWIDTH 7 0 -BBX 8 17 0 0 -BITMAP -18 -18 -00 -1E -37 -77 -70 -70 -FC -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni1E20 -ENCODING 7712 -SWIDTH 833 0 -DWIDTH 15 0 -BBX 13 17 1 0 -BITMAP -1F80 -1F80 -0000 -0F90 -3C70 -7830 -7030 -F010 -E010 -E000 -E000 -E0F8 -F070 -7070 -7870 -3CF0 -0F90 -ENDCHAR -STARTCHAR uni1E21 -ENCODING 7713 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 11 18 0 -4 -BITMAP -1F80 -1F80 -0000 -0060 -00E0 -3F00 -7380 -6180 -6180 -7380 -3F00 -6000 -7F80 -3FC0 -C1C0 -C0C0 -E180 -7F00 -ENDCHAR -STARTCHAR uni1E22 -ENCODING 7714 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0300 -0300 -0000 -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR uni1E23 -ENCODING 7715 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -1800 -1800 -0000 -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR uni1E24 -ENCODING 7716 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E25 -ENCODING 7717 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E26 -ENCODING 7718 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0CC0 -0CC0 -0000 -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -ENDCHAR -STARTCHAR uni1E27 -ENCODING 7719 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 0 -BITMAP -6600 -6600 -0000 -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR uni1E28 -ENCODING 7720 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 18 1 -4 -BITMAP -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -0200 -0380 -0180 -0700 -ENDCHAR -STARTCHAR uni1E29 -ENCODING 7721 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 18 0 -4 -BITMAP -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0400 -0700 -0300 -0E00 -ENDCHAR -STARTCHAR uni1E2A -ENCODING 7722 -SWIDTH 870 0 -DWIDTH 16 0 -BBX 14 18 1 -4 -BITMAP -FCFC -7038 -7038 -7038 -7038 -7038 -7FF8 -7038 -7038 -7038 -7038 -7038 -7038 -FCFC -0000 -0840 -0CC0 -0780 -ENDCHAR -STARTCHAR uni1E2B -ENCODING 7723 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 18 0 -4 -BITMAP -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -1080 -1980 -0F00 -ENDCHAR -STARTCHAR uni1E2C -ENCODING 7724 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 8 18 0 -4 -BITMAP -3E -1C -1C -1C -1C -1C -1C -1C -1C -1C -1C -1C -1C -3E -00 -31 -7E -8C -ENDCHAR -STARTCHAR uni1E2D -ENCODING 7725 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 8 18 -2 -4 -BITMAP -1C -1C -1C -00 -00 -3C -1C -1C -1C -1C -1C -1C -1C -3E -00 -31 -7E -8C -ENDCHAR -STARTCHAR uni1E2E -ENCODING 7726 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 6 22 2 0 -BITMAP -0C -1C -38 -60 -00 -CC -CC -00 -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni1E2F -ENCODING 7727 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 6 17 0 0 -BITMAP -0C -1C -38 -60 -00 -CC -CC -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni1E30 -ENCODING 7728 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -ENDCHAR -STARTCHAR uni1E31 -ENCODING 7729 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 19 0 0 -BITMAP -0C00 -1C00 -3800 -6000 -0000 -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -ENDCHAR -STARTCHAR uni1E32 -ENCODING 7730 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 17 1 -3 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1E33 -ENCODING 7731 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E34 -ENCODING 7732 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 17 1 -3 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -0000 -07E0 -07E0 -ENDCHAR -STARTCHAR uni1E35 -ENCODING 7733 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -73E0 -7180 -7200 -7600 -7F00 -7780 -73C0 -71E0 -FBF0 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E36 -ENCODING 7734 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 17 1 -3 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E37 -ENCODING 7735 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 5 17 0 -3 -BITMAP -F0 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E38 -ENCODING 7736 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 20 1 -3 -BITMAP -7E00 -7E00 -0000 -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E39 -ENCODING 7737 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 6 20 -1 -3 -BITMAP -FC -FC -00 -78 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -00 -18 -18 -ENDCHAR -STARTCHAR uni1E3A -ENCODING 7738 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 17 1 -3 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -0000 -3F00 -3F00 -ENDCHAR -STARTCHAR uni1E3B -ENCODING 7739 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 6 17 0 -3 -BITMAP -F0 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -00 -FC -FC -ENDCHAR -STARTCHAR uni1E3C -ENCODING 7740 -SWIDTH 722 0 -DWIDTH 12 0 -BBX 11 19 1 -5 -BITMAP -FC00 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7000 -7020 -7020 -7060 -70E0 -FFE0 -0000 -0400 -0E00 -1F00 -3180 -ENDCHAR -STARTCHAR uni1E3D -ENCODING 7741 -SWIDTH 352 0 -DWIDTH 6 0 -BBX 7 19 -1 -5 -BITMAP -78 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -38 -7C -00 -10 -38 -7C -C6 -ENDCHAR -STARTCHAR uni1E3E -ENCODING 7742 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 17 19 1 0 -BITMAP -003000 -007000 -00E000 -018000 -000000 -7C0780 -3C0F00 -3E0F00 -2E1F00 -2F1700 -2F1700 -273700 -27A700 -23E700 -23C700 -23C700 -21C700 -718700 -F88F80 -ENDCHAR -STARTCHAR uni1E3F -ENCODING 7743 -SWIDTH 963 0 -DWIDTH 20 0 -BBX 19 14 0 0 -BITMAP -003000 -007000 -00E000 -018000 -000000 -F7DF80 -79F3C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -F9F3E0 -ENDCHAR -STARTCHAR uni1E40 -ENCODING 7744 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 17 17 1 0 -BITMAP -00C000 -00C000 -000000 -7C0780 -3C0F00 -3E0F00 -2E1F00 -2F1700 -2F1700 -273700 -27A700 -23E700 -23C700 -23C700 -21C700 -718700 -F88F80 -ENDCHAR -STARTCHAR uni1E41 -ENCODING 7745 -SWIDTH 963 0 -DWIDTH 20 0 -BBX 19 12 0 0 -BITMAP -00C000 -00C000 -000000 -F7DF80 -79F3C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -F9F3E0 -ENDCHAR -STARTCHAR uni1E42 -ENCODING 7746 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 17 17 1 -3 -BITMAP -7C0780 -3C0F00 -3E0F00 -2E1F00 -2F1700 -2F1700 -273700 -27A700 -23E700 -23C700 -23C700 -21C700 -718700 -F88F80 -000000 -00C000 -00C000 -ENDCHAR -STARTCHAR uni1E43 -ENCODING 7747 -SWIDTH 963 0 -DWIDTH 20 0 -BBX 19 12 0 -3 -BITMAP -F7DF80 -79F3C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -F9F3E0 -000000 -006000 -006000 -ENDCHAR -STARTCHAR uni1E44 -ENCODING 7748 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 1 0 -BITMAP -0300 -0300 -0000 -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR uni1E45 -ENCODING 7749 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 0 -BITMAP -0600 -0600 -0000 -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -ENDCHAR -STARTCHAR uni1E46 -ENCODING 7750 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 1 -3 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E47 -ENCODING 7751 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 -3 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E48 -ENCODING 7752 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 1 -3 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -0000 -0FC0 -0FC0 -ENDCHAR -STARTCHAR uni1E49 -ENCODING 7753 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 -3 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E4A -ENCODING 7754 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 19 1 -5 -BITMAP -F83E -7C1C -3C08 -3E08 -2F08 -2788 -2388 -21C8 -21E8 -20E8 -2078 -2078 -7038 -F818 -0000 -0100 -0380 -07C0 -0C60 -ENDCHAR -STARTCHAR uni1E4B -ENCODING 7755 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 -5 -BITMAP -F7C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -0200 -0700 -0F80 -18C0 -ENDCHAR -STARTCHAR uni1E4C -ENCODING 7756 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 23 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -0310 -07E0 -08C0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1E4D -ENCODING 7757 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -1880 -3F00 -4600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1E4E -ENCODING 7758 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 21 0 0 -BITMAP -0660 -0660 -0000 -0310 -07E0 -08C0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1E4F -ENCODING 7759 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 0 -BITMAP -3300 -3300 -0000 -1880 -3F00 -4600 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1E50 -ENCODING 7760 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 22 0 0 -BITMAP -0600 -0700 -0380 -00C0 -0000 -07E0 -07E0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1E51 -ENCODING 7761 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 17 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -1F80 -1F80 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1E52 -ENCODING 7762 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 22 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -07E0 -07E0 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1E53 -ENCODING 7763 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 17 0 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -1F80 -1F80 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1E54 -ENCODING 7764 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 12 19 1 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -FFE0 -70F0 -7070 -7070 -7070 -70F0 -71E0 -7F80 -7000 -7000 -7000 -7000 -7000 -FC00 -ENDCHAR -STARTCHAR uni1E55 -ENCODING 7765 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 12 18 -1 -4 -BITMAP -0180 -0380 -0700 -0C00 -0000 -E780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -7780 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR uni1E56 -ENCODING 7766 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 12 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -70F0 -7070 -7070 -7070 -70F0 -71E0 -7F80 -7000 -7000 -7000 -7000 -7000 -FC00 -ENDCHAR -STARTCHAR uni1E57 -ENCODING 7767 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 12 16 -1 -4 -BITMAP -0600 -0600 -0000 -E780 -78E0 -7070 -7070 -7070 -7070 -7070 -78E0 -7780 -7000 -7000 -7000 -F800 -ENDCHAR -STARTCHAR uni1E58 -ENCODING 7768 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -ENDCHAR -STARTCHAR uni1E59 -ENCODING 7769 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 12 0 0 -BITMAP -18 -18 -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -ENDCHAR -STARTCHAR uni1E5A -ENCODING 7770 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E5B -ENCODING 7771 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 12 0 -3 -BITMAP -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E5C -ENCODING 7772 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 20 1 -3 -BITMAP -0FC0 -0FC0 -0000 -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E5D -ENCODING 7773 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 15 0 -3 -BITMAP -7E -7E -00 -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1E5E -ENCODING 7774 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -FFE0 -70F0 -7070 -7070 -70F0 -71E0 -7F80 -71C0 -71E0 -70E0 -70E0 -70F0 -7074 -F878 -0000 -0FC0 -0FC0 -ENDCHAR -STARTCHAR uni1E5F -ENCODING 7775 -SWIDTH 519 0 -DWIDTH 9 0 -BBX 8 12 0 -3 -BITMAP -F7 -7B -73 -70 -70 -70 -70 -70 -F8 -00 -FC -FC -ENDCHAR -STARTCHAR uni1E60 -ENCODING 7776 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 17 0 0 -BITMAP -0C00 -0C00 -0000 -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -ENDCHAR -STARTCHAR uni1E61 -ENCODING 7777 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 12 0 0 -BITMAP -1800 -1800 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR uni1E62 -ENCODING 7778 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 17 0 -3 -BITMAP -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E63 -ENCODING 7779 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 12 0 -3 -BITMAP -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1E64 -ENCODING 7780 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 22 0 0 -BITMAP -0600 -0600 -0000 -0300 -0700 -0E00 -1800 -0000 -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -ENDCHAR -STARTCHAR uni1E65 -ENCODING 7781 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 17 0 0 -BITMAP -0C00 -0C00 -0000 -0600 -0E00 -1C00 -3000 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR uni1E66 -ENCODING 7782 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 10 17 0 0 -BITMAP -0C00 -0C00 -0000 -6180 -3300 -1E00 -0C00 -0000 -3F80 -7180 -7880 -7E00 -3F00 -0F80 -83C0 -C780 -BF00 -ENDCHAR -STARTCHAR uni1E67 -ENCODING 7783 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 17 0 0 -BITMAP -1800 -1800 -0000 -C300 -6600 -3C00 -1800 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -ENDCHAR -STARTCHAR uni1E68 -ENCODING 7784 -SWIDTH 667 0 -DWIDTH 12 0 -BBX 11 20 0 -3 -BITMAP -0C00 -0C00 -0000 -3F40 -61C0 -C0C0 -C040 -E000 -FE00 -7FC0 -7FE0 -0FE0 -80E0 -8060 -C060 -E0C0 -BF80 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E69 -ENCODING 7785 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 15 0 -3 -BITMAP -1800 -1800 -0000 -3D00 -6300 -E100 -FC00 -7F00 -0F80 -8380 -C300 -BE00 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1E6A -ENCODING 7786 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 17 1 0 -BITMAP -0600 -0600 -0000 -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -ENDCHAR -STARTCHAR uni1E6B -ENCODING 7787 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 16 0 0 -BITMAP -30 -30 -00 -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -ENDCHAR -STARTCHAR uni1E6C -ENCODING 7788 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 17 1 -3 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1E6D -ENCODING 7789 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 16 0 -3 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -00 -30 -30 -ENDCHAR -STARTCHAR uni1E6E -ENCODING 7790 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 17 1 -3 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E6F -ENCODING 7791 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 16 0 -3 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -00 -FC -FC -ENDCHAR -STARTCHAR uni1E70 -ENCODING 7792 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 19 1 -5 -BITMAP -FFE0 -CE60 -CE60 -8E20 -8E20 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -0E00 -1F00 -0000 -0400 -0E00 -1F00 -3180 -ENDCHAR -STARTCHAR uni1E71 -ENCODING 7793 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 18 0 -5 -BITMAP -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -00 -10 -38 -7C -C6 -ENDCHAR -STARTCHAR uni1E72 -ENCODING 7794 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -0000 -1980 -1980 -ENDCHAR -STARTCHAR uni1E73 -ENCODING 7795 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 -3 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -0000 -1980 -1980 -ENDCHAR -STARTCHAR uni1E74 -ENCODING 7796 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 18 1 -4 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -0000 -0C40 -1F80 -2300 -ENDCHAR -STARTCHAR uni1E75 -ENCODING 7797 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 13 0 -4 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -0000 -0C40 -1F80 -2300 -ENDCHAR -STARTCHAR uni1E76 -ENCODING 7798 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 19 1 -5 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -0000 -0200 -0700 -0F80 -18C0 -ENDCHAR -STARTCHAR uni1E77 -ENCODING 7799 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 14 0 -5 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -0000 -0200 -0700 -0F80 -18C0 -ENDCHAR -STARTCHAR uni1E78 -ENCODING 7800 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 23 1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0620 -0FC0 -1180 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni1E79 -ENCODING 7801 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 18 0 0 -BITMAP -0180 -0380 -0700 -0C00 -0000 -0C40 -1F80 -2300 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni1E7A -ENCODING 7802 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 20 1 0 -BITMAP -0CC0 -0CC0 -0000 -0FC0 -0FC0 -0000 -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -ENDCHAR -STARTCHAR uni1E7B -ENCODING 7803 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 15 0 0 -BITMAP -1980 -1980 -0000 -1F80 -1F80 -0000 -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni1E7C -ENCODING 7804 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0620 -0FC0 -1180 -0000 -F87C -7038 -7830 -3820 -3820 -3C60 -1C40 -1E40 -0EC0 -0E80 -0780 -0780 -0300 -0300 -ENDCHAR -STARTCHAR uni1E7D -ENCODING 7805 -SWIDTH 611 0 -DWIDTH 9 0 -BBX 10 13 -1 0 -BITMAP -1880 -3F00 -4600 -0000 -F9C0 -7080 -7080 -3900 -3900 -1E00 -1E00 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E7E -ENCODING 7806 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 17 0 -3 -BITMAP -F87C -7038 -7830 -3820 -3820 -3C60 -1C40 -1E40 -0EC0 -0E80 -0780 -0780 -0300 -0300 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1E7F -ENCODING 7807 -SWIDTH 611 0 -DWIDTH 9 0 -BBX 10 12 -1 -3 -BITMAP -F9C0 -7080 -7080 -3900 -3900 -1E00 -1E00 -0C00 -0C00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR Wgrave -ENCODING 7808 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 19 0 0 -BITMAP -030000 -038000 -01C000 -006000 -000000 -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR wgrave -ENCODING 7809 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 14 -1 0 -BITMAP -0600 -0700 -0380 -00C0 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR Wacute -ENCODING 7810 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 19 0 0 -BITMAP -003000 -007000 -00E000 -018000 -000000 -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR wacute -ENCODING 7811 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 14 -1 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR Wdieresis -ENCODING 7812 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 17 0 0 -BITMAP -033000 -033000 -000000 -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR wdieresis -ENCODING 7813 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 12 -1 0 -BITMAP -0CC0 -0CC0 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR uni1E86 -ENCODING 7814 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 17 0 0 -BITMAP -00C000 -00C000 -000000 -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR uni1E87 -ENCODING 7815 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 12 -1 0 -BITMAP -0300 -0300 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR uni1E88 -ENCODING 7816 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 17 0 -3 -BITMAP -FBF3E0 -71E1C0 -70E180 -78E100 -38F100 -39F300 -3D7200 -1D3A00 -1F3E00 -1E3C00 -0E1C00 -0E1C00 -0C1800 -040800 -000000 -00C000 -00C000 -ENDCHAR -STARTCHAR uni1E89 -ENCODING 7817 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 12 -1 -3 -BITMAP -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1E8A -ENCODING 7818 -SWIDTH 722 0 -DWIDTH 17 0 -BBX 16 17 0 0 -BITMAP -0180 -0180 -0000 -7E3F -3C1C -1E18 -0E30 -0F60 -07C0 -03C0 -03E0 -06F0 -0C70 -1878 -303C -703E -F87F -ENDCHAR -STARTCHAR uni1E8B -ENCODING 7819 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 0 -BITMAP -0C00 -0C00 -0000 -FCE0 -78C0 -3D00 -1E00 -0E00 -0F00 -1780 -63C0 -E7E0 -ENDCHAR -STARTCHAR uni1E8C -ENCODING 7820 -SWIDTH 722 0 -DWIDTH 17 0 -BBX 16 17 0 0 -BITMAP -0660 -0660 -0000 -7E3F -3C1C -1E18 -0E30 -0F60 -07C0 -03C0 -03E0 -06F0 -0C70 -1878 -303C -703E -F87F -ENDCHAR -STARTCHAR uni1E8D -ENCODING 7821 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 0 -BITMAP -3300 -3300 -0000 -FCE0 -78C0 -3D00 -1E00 -0E00 -0F00 -1780 -63C0 -E7E0 -ENDCHAR -STARTCHAR uni1E8E -ENCODING 7822 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 17 1 0 -BITMAP -0600 -0600 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR uni1E8F -ENCODING 7823 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 -4 -BITMAP -0C00 -0C00 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR uni1E90 -ENCODING 7824 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 19 1 0 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -ENDCHAR -STARTCHAR uni1E91 -ENCODING 7825 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 14 0 0 -BITMAP -08 -1C -3E -63 -00 -FF -CF -8E -1C -38 -39 -71 -F3 -FF -ENDCHAR -STARTCHAR uni1E92 -ENCODING 7826 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 17 1 -3 -BITMAP -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1E93 -ENCODING 7827 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 12 0 -3 -BITMAP -FF -CF -8E -1C -38 -39 -71 -F3 -FF -00 -18 -18 -ENDCHAR -STARTCHAR uni1E94 -ENCODING 7828 -SWIDTH 667 0 -DWIDTH 13 0 -BBX 11 17 1 -3 -BITMAP -FFE0 -E1E0 -C1C0 -83C0 -8780 -0700 -0F00 -1E00 -1C00 -3C20 -7820 -7060 -F0E0 -FFE0 -0000 -3F00 -3F00 -ENDCHAR -STARTCHAR uni1E95 -ENCODING 7829 -SWIDTH 537 0 -DWIDTH 10 0 -BBX 8 12 0 -3 -BITMAP -FF -CF -8E -1C -38 -39 -71 -F3 -FF -00 -7E -7E -ENDCHAR -STARTCHAR uni1E96 -ENCODING 7830 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 17 0 -3 -BITMAP -F000 -7000 -7000 -7000 -7000 -77C0 -79E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -F9F0 -0000 -1F80 -1F80 -ENDCHAR -STARTCHAR uni1E97 -ENCODING 7831 -SWIDTH 426 0 -DWIDTH 8 0 -BBX 7 16 0 0 -BITMAP -CC -CC -00 -10 -30 -30 -70 -FC -70 -70 -70 -70 -70 -72 -72 -3C -ENDCHAR -STARTCHAR uni1E98 -ENCODING 7832 -SWIDTH 889 0 -DWIDTH 15 0 -BBX 16 14 -1 0 -BITMAP -0300 -0480 -0480 -0300 -0000 -FBE7 -71C2 -71C2 -39E4 -39E4 -1E78 -1E78 -0C30 -0C30 -ENDCHAR -STARTCHAR uni1E99 -ENCODING 7833 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -0C00 -1200 -1200 -0C00 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR uni1EA0 -ENCODING 7840 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 17 0 -3 -BITMAP -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1EA1 -ENCODING 7841 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 12 0 -3 -BITMAP -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EA4 -ENCODING 7844 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 23 0 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0380 -07C0 -0C60 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EA5 -ENCODING 7845 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -1C00 -3E00 -6300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EA6 -ENCODING 7846 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 23 0 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -0380 -07C0 -0C60 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EA7 -ENCODING 7847 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -1C00 -3E00 -6300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EAA -ENCODING 7850 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 22 0 0 -BITMAP -0310 -07E0 -08C0 -0000 -0380 -07C0 -0C60 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EAB -ENCODING 7851 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 17 0 0 -BITMAP -1880 -3F00 -4600 -0000 -1C00 -3E00 -6300 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EAC -ENCODING 7852 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 22 0 -3 -BITMAP -0200 -0700 -0F80 -18C0 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1EAD -ENCODING 7853 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 17 0 -3 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EAE -ENCODING 7854 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 23 0 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0840 -0CC0 -0780 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EAF -ENCODING 7855 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -2100 -3300 -1E00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EB0 -ENCODING 7856 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 23 0 0 -BITMAP -0C00 -0E00 -0700 -0180 -0000 -0840 -0CC0 -0780 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EB1 -ENCODING 7857 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -2100 -3300 -1E00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EB4 -ENCODING 7860 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 22 0 0 -BITMAP -0620 -0FC0 -1180 -0000 -0840 -0CC0 -0780 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni1EB5 -ENCODING 7861 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 17 0 0 -BITMAP -1880 -3F00 -4600 -0000 -2100 -3300 -1E00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -ENDCHAR -STARTCHAR uni1EB6 -ENCODING 7862 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 21 0 -3 -BITMAP -0840 -0CC0 -0780 -0000 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1EB7 -ENCODING 7863 -SWIDTH 611 0 -DWIDTH 11 0 -BBX 10 16 0 -3 -BITMAP -2100 -3300 -1E00 -0000 -7F00 -E380 -C380 -0780 -3B80 -E380 -E380 -E780 -7BC0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EB8 -ENCODING 7864 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 17 1 -3 -BITMAP -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EB9 -ENCODING 7865 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 12 0 -3 -BITMAP -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EBC -ENCODING 7868 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 18 1 0 -BITMAP -0C40 -1F80 -2300 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1EBD -ENCODING 7869 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 13 0 0 -BITMAP -1880 -3F00 -4600 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1EBE -ENCODING 7870 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 23 1 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -0E00 -1F00 -3180 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1EBF -ENCODING 7871 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -0E00 -1F00 -3180 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1EC0 -ENCODING 7872 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 23 1 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -0E00 -1F00 -3180 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1EC1 -ENCODING 7873 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 18 0 0 -BITMAP -3000 -3800 -1C00 -0600 -0000 -0E00 -1F00 -3180 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1EC4 -ENCODING 7876 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 22 1 0 -BITMAP -0C40 -1F80 -2300 -0000 -0E00 -1F00 -3180 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -ENDCHAR -STARTCHAR uni1EC5 -ENCODING 7877 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 17 0 0 -BITMAP -0C40 -1F80 -2300 -0000 -0E00 -1F00 -3180 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -ENDCHAR -STARTCHAR uni1EC6 -ENCODING 7878 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 22 1 -3 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -FFE0 -70E0 -7060 -7120 -7120 -7300 -7F00 -7300 -7100 -7120 -7020 -7060 -70E0 -FFE0 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1EC7 -ENCODING 7879 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 10 17 0 -3 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -1E00 -7380 -E1C0 -E1C0 -FFC0 -E000 -E040 -70C0 -1F00 -0000 -0C00 -0C00 -ENDCHAR -STARTCHAR uni1ECA -ENCODING 7882 -SWIDTH 444 0 -DWIDTH 9 0 -BBX 5 17 2 -3 -BITMAP -F8 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -70 -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1ECB -ENCODING 7883 -SWIDTH 370 0 -DWIDTH 6 0 -BBX 5 17 0 -3 -BITMAP -70 -70 -70 -00 -00 -F0 -70 -70 -70 -70 -70 -70 -70 -F8 -00 -30 -30 -ENDCHAR -STARTCHAR uni1ECC -ENCODING 7884 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 17 0 -3 -BITMAP -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1ECD -ENCODING 7885 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 12 0 -3 -BITMAP -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1ED0 -ENCODING 7888 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 23 0 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -0380 -07C0 -0C60 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1ED1 -ENCODING 7889 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 0 -BITMAP -0300 -0700 -0E00 -1800 -0000 -0E00 -1F00 -3180 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1ED2 -ENCODING 7890 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 23 0 0 -BITMAP -0600 -0700 -0380 -00C0 -0000 -0380 -07C0 -0C60 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1ED3 -ENCODING 7891 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -0E00 -1F00 -3180 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1ED6 -ENCODING 7894 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 22 0 0 -BITMAP -0310 -07E0 -08C0 -0000 -0380 -07C0 -0C60 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -ENDCHAR -STARTCHAR uni1ED7 -ENCODING 7895 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 17 0 0 -BITMAP -0C40 -1F80 -2300 -0000 -0E00 -1F00 -3180 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1ED8 -ENCODING 7896 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 22 0 -3 -BITMAP -0100 -0380 -07C0 -0C60 -0000 -0FE0 -3C78 -783C -701C -F01E -E00E -E00E -E00E -E00E -F01E -701C -783C -3C78 -0FE0 -0000 -0180 -0180 -ENDCHAR -STARTCHAR uni1ED9 -ENCODING 7897 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 17 0 -3 -BITMAP -0400 -0E00 -1F00 -3180 -0000 -1F00 -71C0 -E0E0 -E0E0 -E0E0 -E0E0 -E0E0 -71C0 -1F00 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1EDA -ENCODING 7898 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 18 19 0 0 -BITMAP -001800 -003800 -007000 -00C000 -000000 -0FE180 -3C7BC0 -783FC0 -701DC0 -F01E80 -E00F00 -E00E00 -E00E00 -E00E00 -F01E00 -701C00 -783C00 -3C7800 -0FE000 -ENDCHAR -STARTCHAR uni1EDB -ENCODING 7899 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 14 14 0 0 -BITMAP -00C0 -01C0 -0380 -0600 -0000 -1F18 -71FC -E0FC -E0FC -E0E8 -E0F0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1EDC -ENCODING 7900 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 18 19 0 0 -BITMAP -018000 -01C000 -00E000 -003000 -000000 -0FE180 -3C7BC0 -783FC0 -701DC0 -F01E80 -E00F00 -E00E00 -E00E00 -E00E00 -F01E00 -701C00 -783C00 -3C7800 -0FE000 -ENDCHAR -STARTCHAR uni1EDD -ENCODING 7901 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 14 14 0 0 -BITMAP -0600 -0700 -0380 -00C0 -0000 -1F18 -71FC -E0FC -E0FC -E0E8 -E0F0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1EE0 -ENCODING 7904 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 18 18 0 0 -BITMAP -00C400 -01F800 -023000 -000000 -0FE180 -3C7BC0 -783FC0 -701DC0 -F01E80 -E00F00 -E00E00 -E00E00 -E00E00 -F01E00 -701C00 -783C00 -3C7800 -0FE000 -ENDCHAR -STARTCHAR uni1EE1 -ENCODING 7905 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 14 13 0 0 -BITMAP -0310 -07E0 -08C0 -0000 -1F18 -71FC -E0FC -E0FC -E0E8 -E0F0 -E0E0 -71C0 -1F00 -ENDCHAR -STARTCHAR uni1EE2 -ENCODING 7906 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 18 17 0 -3 -BITMAP -0FE180 -3C7BC0 -783FC0 -701DC0 -F01E80 -E00F00 -E00E00 -E00E00 -E00E00 -F01E00 -701C00 -783C00 -3C7800 -0FE000 -000000 -018000 -018000 -ENDCHAR -STARTCHAR uni1EE3 -ENCODING 7907 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 14 12 0 -3 -BITMAP -1F18 -71FC -E0FC -E0FC -E0E8 -E0F0 -E0E0 -71C0 -1F00 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1EE4 -ENCODING 7908 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 14 17 1 -3 -BITMAP -F87C -7038 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -7010 -3820 -1FC0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1EE5 -ENCODING 7909 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 12 12 0 -3 -BITMAP -F1E0 -70E0 -70E0 -70E0 -70E0 -70E0 -70E0 -79E0 -3EF0 -0000 -0600 -0600 -ENDCHAR -STARTCHAR uni1EE8 -ENCODING 7912 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 19 1 0 -BITMAP -003000 -007000 -00E000 -018000 -000000 -F87F00 -703F80 -701780 -701380 -701100 -701200 -701400 -701000 -701000 -701000 -701000 -701000 -382000 -1FC000 -ENDCHAR -STARTCHAR uni1EE9 -ENCODING 7913 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 15 14 0 0 -BITMAP -0060 -00E0 -01C0 -0300 -0000 -F1EC -70FE -70FE -70EE -70E4 -70E8 -70F0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni1EEA -ENCODING 7914 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 19 1 0 -BITMAP -030000 -038000 -01C000 -006000 -000000 -F87F00 -703F80 -701780 -701380 -701100 -701200 -701400 -701000 -701000 -701000 -701000 -701000 -382000 -1FC000 -ENDCHAR -STARTCHAR uni1EEB -ENCODING 7915 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 15 14 0 0 -BITMAP -0600 -0700 -0380 -00C0 -0000 -F1EC -70FE -70FE -70EE -70E4 -70E8 -70F0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni1EEE -ENCODING 7918 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 18 1 0 -BITMAP -018800 -03F000 -046000 -000000 -F87F00 -703F80 -701780 -701380 -701100 -701200 -701400 -701000 -701000 -701000 -701000 -701000 -382000 -1FC000 -ENDCHAR -STARTCHAR uni1EEF -ENCODING 7919 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 15 13 0 0 -BITMAP -0310 -07E0 -08C0 -0000 -F1EC -70FE -70FE -70EE -70E4 -70E8 -70F0 -79E0 -3EF0 -ENDCHAR -STARTCHAR uni1EF0 -ENCODING 7920 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 17 17 1 -3 -BITMAP -F87F00 -703F80 -701780 -701380 -701100 -701200 -701400 -701000 -701000 -701000 -701000 -701000 -382000 -1FC000 -000000 -030000 -030000 -ENDCHAR -STARTCHAR uni1EF1 -ENCODING 7921 -SWIDTH 685 0 -DWIDTH 13 0 -BBX 15 12 0 -3 -BITMAP -F1EC -70FE -70FE -70EE -70E4 -70E8 -70F0 -79E0 -3EF0 -0000 -0300 -0300 -ENDCHAR -STARTCHAR Ygrave -ENCODING 7922 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 19 1 0 -BITMAP -1800 -1C00 -0E00 -0300 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR ygrave -ENCODING 7923 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 18 0 -4 -BITMAP -3000 -3800 -1C00 -0600 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR uni1EF4 -ENCODING 7924 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 17 1 -3 -BITMAP -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -0000 -0300 -0300 -ENDCHAR -STARTCHAR uni1EF5 -ENCODING 7925 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 16 0 -7 -BITMAP -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -0000 -1800 -1800 -ENDCHAR -STARTCHAR uni1EF8 -ENCODING 7928 -SWIDTH 722 0 -DWIDTH 15 0 -BBX 13 18 1 0 -BITMAP -0C40 -1F80 -2300 -0000 -F878 -7030 -7820 -3860 -3C40 -1CC0 -1F80 -0F80 -0F00 -0700 -0700 -0700 -0700 -0F80 -ENDCHAR -STARTCHAR uni1EF9 -ENCODING 7929 -SWIDTH 611 0 -DWIDTH 12 0 -BBX 11 17 0 -4 -BITMAP -1880 -3F00 -4600 -0000 -F8E0 -7040 -7040 -3880 -3880 -1D00 -1D00 -0E00 -0E00 -0400 -C400 -E800 -7000 -ENDCHAR -STARTCHAR uni2000 -ENCODING 8192 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2001 -ENCODING 8193 -SWIDTH 1000 0 -DWIDTH 19 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2002 -ENCODING 8194 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2003 -ENCODING 8195 -SWIDTH 1000 0 -DWIDTH 19 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2004 -ENCODING 8196 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2005 -ENCODING 8197 -SWIDTH 250 0 -DWIDTH 5 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2006 -ENCODING 8198 -SWIDTH 167 0 -DWIDTH 3 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2007 -ENCODING 8199 -SWIDTH 574 0 -DWIDTH 11 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2008 -ENCODING 8200 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2009 -ENCODING 8201 -SWIDTH 200 0 -DWIDTH 4 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni200A -ENCODING 8202 -SWIDTH 100 0 -DWIDTH 2 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni200B -ENCODING 8203 -SWIDTH 0 0 -DWIDTH 0 0 -BBX 1 1 0 0 -BITMAP -00 -ENDCHAR -STARTCHAR uni2010 -ENCODING 8208 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 5 2 0 4 -BITMAP -F8 -F8 -ENDCHAR -STARTCHAR uni2011 -ENCODING 8209 -SWIDTH 333 0 -DWIDTH 6 0 -BBX 5 2 0 4 -BITMAP -F8 -F8 -ENDCHAR -STARTCHAR figuredash -ENCODING 8210 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 9 2 0 4 -BITMAP -FF80 -FF80 -ENDCHAR -STARTCHAR endash -ENCODING 8211 -SWIDTH 500 0 -DWIDTH 9 0 -BBX 9 2 0 4 -BITMAP -FF80 -FF80 -ENDCHAR -STARTCHAR emdash -ENCODING 8212 -SWIDTH 1000 0 -DWIDTH 18 0 -BBX 18 2 0 4 -BITMAP -FFFFC0 -FFFFC0 -ENDCHAR -STARTCHAR afii00208 -ENCODING 8213 -SWIDTH 1000 0 -DWIDTH 18 0 -BBX 18 2 0 4 -BITMAP -FFFFC0 -FFFFC0 -ENDCHAR -STARTCHAR quoteleft -ENCODING 8216 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -10 -20 -40 -E0 -F0 -F0 -60 -ENDCHAR -STARTCHAR quoteright -ENCODING 8217 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR quotesinglbase -ENCODING 8218 -SWIDTH 241 0 -DWIDTH 6 0 -BBX 4 7 1 -3 -BITMAP -60 -F0 -F0 -70 -20 -40 -80 -ENDCHAR -STARTCHAR quotereversed -ENCODING 8219 -SWIDTH 241 0 -DWIDTH 5 0 -BBX 4 7 0 7 -BITMAP -60 -F0 -F0 -E0 -40 -20 -10 -ENDCHAR -STARTCHAR quotedblleft -ENCODING 8220 -SWIDTH 481 0 -DWIDTH 10 0 -BBX 9 7 0 7 -BITMAP -1080 -2100 -4200 -E700 -F780 -F780 -6300 -ENDCHAR -STARTCHAR quotedblright -ENCODING 8221 -SWIDTH 481 0 -DWIDTH 10 0 -BBX 9 7 0 7 -BITMAP -6300 -F780 -F780 -7380 -2100 -4200 -8400 -ENDCHAR -STARTCHAR quotedblbase -ENCODING 8222 -SWIDTH 481 0 -DWIDTH 11 0 -BBX 9 7 1 -3 -BITMAP -6300 -F780 -F780 -7380 -2100 -4200 -8400 -ENDCHAR -STARTCHAR uni201F -ENCODING 8223 -SWIDTH 481 0 -DWIDTH 10 0 -BBX 9 7 0 7 -BITMAP -6300 -F780 -F780 -E700 -4200 -2100 -1080 -ENDCHAR -STARTCHAR dagger -ENCODING 8224 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 16 0 -2 -BITMAP -1C00 -1C00 -0800 -C980 -FF80 -C980 -0800 -1C00 -1C00 -0800 -0800 -0800 -0800 -0800 -0800 -0800 -ENDCHAR -STARTCHAR daggerdbl -ENCODING 8225 -SWIDTH 500 0 -DWIDTH 10 0 -BBX 9 16 0 -2 -BITMAP -1C00 -1C00 -0800 -C980 -FF80 -C980 -0800 -1C00 -1C00 -0800 -C980 -FF80 -C980 -0800 -1C00 -1C00 -ENDCHAR -STARTCHAR bullet -ENCODING 8226 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 6 6 2 4 -BITMAP -78 -FC -FC -FC -FC -78 -ENDCHAR -STARTCHAR ellipsis -ENCODING 8230 -SWIDTH 1000 0 -DWIDTH 18 0 -BBX 16 4 1 0 -BITMAP -6186 -F3CF -F3CF -6186 -ENDCHAR -STARTCHAR perthousand -ENCODING 8240 -SWIDTH 1000 0 -DWIDTH 22 0 -BBX 21 15 0 -1 -BITMAP -38C000 -674000 -C4C000 -C48000 -C58000 -C90000 -730000 -023870 -0664C8 -04C588 -0CC588 -08C588 -18C990 -1070E0 -100000 -ENDCHAR -STARTCHAR guilsinglleft -ENCODING 8249 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 4 5 0 3 -BITMAP -30 -60 -C0 -60 -30 -ENDCHAR -STARTCHAR guilsinglright -ENCODING 8250 -SWIDTH 333 0 -DWIDTH 5 0 -BBX 4 5 0 3 -BITMAP -C0 -60 -30 -60 -C0 -ENDCHAR -STARTCHAR fraction -ENCODING 8260 -SWIDTH 167 0 -DWIDTH 3 0 -BBX 8 14 -3 0 -BITMAP -03 -03 -06 -06 -0C -0C -18 -18 -30 -30 -60 -60 -C0 -C0 -ENDCHAR -STARTCHAR oneinferior -ENCODING 8321 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 -4 -BITMAP -30 -F0 -30 -30 -30 -30 -30 -FC -ENDCHAR -STARTCHAR twoinferior -ENCODING 8322 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 -4 -BITMAP -78 -CC -CC -18 -30 -60 -C4 -FC -ENDCHAR -STARTCHAR threeinferior -ENCODING 8323 -SWIDTH 344 0 -DWIDTH 6 0 -BBX 6 8 0 -4 -BITMAP -78 -CC -0C -38 -0C -CC -CC -78 -ENDCHAR -STARTCHAR uni20A5 -ENCODING 8357 -SWIDTH 963 0 -DWIDTH 20 0 -BBX 19 14 0 -2 -BITMAP -001800 -001800 -001800 -F7FF80 -79F3C0 -70F1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -70E1C0 -F9F3E0 -018000 -018000 -ENDCHAR -STARTCHAR uni20A6 -ENCODING 8358 -SWIDTH 833 0 -DWIDTH 16 0 -BBX 15 14 1 0 -BITMAP -F83E -7C1C -3C08 -3E08 -3FF8 -3FF8 -2388 -21C8 -3FF8 -3FF8 -2078 -2078 -7038 -F818 -ENDCHAR -STARTCHAR uni20A9 -ENCODING 8361 -SWIDTH 981 0 -DWIDTH 19 0 -BBX 19 14 0 0 -BITMAP -FBF3E0 -71E1C0 -70E180 -78E100 -3FFD00 -3FFF00 -3D7200 -1D3A00 -1FFE00 -1FFC00 -0E1C00 -0E1C00 -0C1800 -040800 -ENDCHAR -STARTCHAR Euro -ENCODING 8364 -SWIDTH 778 0 -DWIDTH 14 0 -BBX 14 14 -1 0 -BITMAP -03E4 -0F1C -1E0C -1C0C -FF84 -FF84 -3800 -3800 -FF80 -FF84 -1C04 -1E08 -0F18 -03E0 -ENDCHAR -STARTCHAR uni20AD -ENCODING 8365 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 14 1 0 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -FFFE -FFFE -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -ENDCHAR -STARTCHAR uni2103 -ENCODING 8451 -SWIDTH 1158 0 -DWIDTH 21 0 -BBX 20 14 0 0 -BITMAP -780F90 -CC3C70 -847830 -847030 -CCF010 -78E010 -00E000 -00E000 -00E000 -00F010 -007010 -007820 -003C60 -000F80 -ENDCHAR -STARTCHAR uni2109 -ENCODING 8457 -SWIDTH 1102 0 -DWIDTH 20 0 -BBX 19 14 0 0 -BITMAP -78FFE0 -CC70E0 -847060 -847120 -CC7120 -787320 -007F00 -007300 -007100 -007100 -007000 -007000 -007000 -00F800 -ENDCHAR -STARTCHAR trademark -ENCODING 8482 -SWIDTH 1000 0 -DWIDTH 20 0 -BBX 19 8 0 6 -BITMAP -FFF1E0 -9971C0 -185AC0 -185AC0 -185AC0 -184CC0 -184CC0 -3CEDE0 -ENDCHAR -STARTCHAR uni212A -ENCODING 8490 -SWIDTH 815 0 -DWIDTH 16 0 -BBX 15 14 1 0 -BITMAP -FC7C -7030 -7060 -70C0 -7180 -7300 -7780 -7FC0 -7BC0 -71E0 -70F0 -70F8 -707C -FCFE -ENDCHAR -STARTCHAR uni212B -ENCODING 8491 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 18 0 0 -BITMAP -0300 -0480 -0480 -0300 -0300 -0300 -0780 -0780 -0F80 -09C0 -09C0 -19E0 -10E0 -3FE0 -20F0 -6070 -4078 -E0FC -ENDCHAR -STARTCHAR uni2132 -ENCODING 8498 -SWIDTH 722 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -03E0 -01C0 -01C0 -01C0 -11C0 -11C0 -19C0 -1FC0 -99C0 -91C0 -91C0 -C1C0 -E1C0 -FFE0 -ENDCHAR -STARTCHAR universal -ENCODING 8704 -SWIDTH 759 0 -DWIDTH 14 0 -BBX 14 14 0 0 -BITMAP -E0FC -4078 -6070 -20F0 -3FE0 -10E0 -19E0 -09C0 -09C0 -0F80 -0780 -0780 -0300 -0300 -ENDCHAR -STARTCHAR existential -ENCODING 8707 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -E1C0 -C1C0 -91C0 -91C0 -19C0 -1FC0 -19C0 -11C0 -91C0 -81C0 -C1C0 -E1C0 -FFE0 -ENDCHAR -STARTCHAR uni2204 -ENCODING 8708 -SWIDTH 759 0 -DWIDTH 13 0 -BBX 11 14 1 0 -BITMAP -FFE0 -E1C0 -C1C0 -93C0 -93C0 -1BC0 -1FC0 -1FC0 -17C0 -9DC0 -8DC0 -CDC0 -F9C0 -FFE0 -ENDCHAR -STARTCHAR minus -ENCODING 8722 -SWIDTH 606 0 -DWIDTH 10 0 -BBX 9 2 0 4 -BITMAP -FF80 -FF80 -ENDCHAR -STARTCHAR fraction -ENCODING 8725 -SWIDTH 167 0 -DWIDTH 3 0 -BBX 8 14 -3 0 -BITMAP -03 -03 -06 -06 -0C -0C -18 -18 -30 -30 -60 -60 -C0 -C0 -ENDCHAR -STARTCHAR periodcentered -ENCODING 8729 -SWIDTH 278 0 -DWIDTH 5 0 -BBX 4 4 0 3 -BITMAP -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR uni2236 -ENCODING 8758 -SWIDTH 278 0 -DWIDTH 6 0 -BBX 4 9 1 0 -BITMAP -60 -F0 -F0 -60 -00 -60 -F0 -F0 -60 -ENDCHAR -STARTCHAR uni2259 -ENCODING 8793 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 11 1 2 -BITMAP -0800 -1C00 -3E00 -6300 -0000 -FF80 -FF80 -0000 -0000 -FF80 -FF80 -ENDCHAR -STARTCHAR uni225A -ENCODING 8794 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 11 1 2 -BITMAP -6300 -3E00 -1C00 -0800 -0000 -FF80 -FF80 -0000 -0000 -FF80 -FF80 -ENDCHAR -STARTCHAR notequal -ENCODING 8800 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 14 1 -2 -BITMAP -0300 -0300 -0300 -0600 -FF80 -FF80 -0C00 -0C00 -FF80 -FF80 -1800 -1800 -3000 -3000 -ENDCHAR -STARTCHAR equivalence -ENCODING 8801 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 8 0 1 -BITMAP -FF80 -FF80 -0000 -FF80 -FF80 -0000 -FF80 -FF80 -ENDCHAR -STARTCHAR uni2262 -ENCODING 8802 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 9 14 0 -2 -BITMAP -0300 -0300 -0300 -FF80 -FF80 -0600 -FF80 -FF80 -0C00 -FF80 -FF80 -1800 -3000 -3000 -ENDCHAR -STARTCHAR lessequal -ENCODING 8804 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 13 0 -3 -BITMAP -00C0 -03C0 -0F00 -3C00 -F000 -F000 -3C00 -0F00 -03C0 -00C0 -0000 -FFC0 -FFC0 -ENDCHAR -STARTCHAR greaterequal -ENCODING 8805 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 13 0 -3 -BITMAP -C000 -F000 -3C00 -0F00 -03C0 -03C0 -0F00 -3C00 -F000 -C000 -0000 -FFC0 -FFC0 -ENDCHAR -STARTCHAR uni226E -ENCODING 8814 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 14 0 -2 -BITMAP -0300 -0300 -03C0 -07C0 -0F00 -3E00 -FC00 -FC00 -3C00 -1F00 -1BC0 -18C0 -3000 -3000 -ENDCHAR -STARTCHAR uni226F -ENCODING 8815 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 14 0 -2 -BITMAP -0300 -0300 -C300 -F600 -3E00 -0F00 -0FC0 -0FC0 -0F00 -3C00 -F800 -D800 -3000 -3000 -ENDCHAR -STARTCHAR uni2270 -ENCODING 8816 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 14 0 -3 -BITMAP -0300 -03C0 -03C0 -0F00 -3E00 -F600 -FC00 -3C00 -0F00 -1BC0 -18C0 -1800 -FFC0 -FFC0 -ENDCHAR -STARTCHAR uni2271 -ENCODING 8817 -SWIDTH 606 0 -DWIDTH 11 0 -BBX 10 14 0 -3 -BITMAP -0300 -C300 -F300 -3E00 -0F00 -07C0 -0FC0 -0F00 -3C00 -F800 -D800 -1800 -FFC0 -FFC0 -ENDCHAR -STARTCHAR fi -ENCODING -1 -SWIDTH 685 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -0F80 -39C0 -31C0 -7000 -7000 -FFC0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -FBE0 -ENDCHAR -STARTCHAR fl -ENCODING -1 -SWIDTH 685 0 -DWIDTH 12 0 -BBX 11 14 0 0 -BITMAP -1EC0 -33C0 -71C0 -71C0 -71C0 -FFC0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -71C0 -FBE0 -ENDCHAR -ENDFONT diff --git a/fs/battfs.c b/fs/battfs.c deleted file mode 100644 index fd8fe1c6..00000000 --- a/fs/battfs.c +++ /dev/null @@ -1,826 +0,0 @@ -/** - * \file - * - * - * \version $Id:$ - * - * \author Francesco Sacchi - * - * \brief BattFS: a filesystem for embedded platforms (implementation). - */ - -#include "battfs.h" - -#include -#include /* MIN, MAX */ -#include /* cpu_to_xx */ - - -#include /* memset, memmove */ - - -/** - * Convert from memory representation to disk structure. - * \note filesystem is in little-endian format. - */ -INLINE void battfs_to_disk(struct BattFsPageHeader *hdr, uint8_t *buf) -{ - STATIC_ASSERT(BATTFS_HEADER_LEN == 12); - buf[0] = hdr->inode; - - buf[1] = hdr->fill; - buf[2] = hdr->fill >> 8; - - buf[3] = hdr->pgoff; - buf[4] = hdr->pgoff >> 8; - - /* - * Mark is at least 1 bit longer than page address. - * Needed to take care of wraparonds. - */ - buf[5] = hdr->mark; - buf[6] = hdr->mark >> 8; - - /* - * First bit used by mark, last 2 bits used by seq. - * Since only 2 pages with the same inode and pgoff - * can exist at the same time, 2 bit for seq are enough. - * Unused bits are set to 1. - */ - buf[7] = ((hdr->mark >> 16) & 0x01) | (hdr->seq << 6) | ~(BV(7) | BV(6) | BV(0)); - - /* - * This field must be the before the last one! - */ - buf[8] = hdr->fcs_free; - buf[9] = hdr->fcs_free >> 8; - - /* - * This field must be the last one! - * This is needed because if the page is only partially - * written, we can use this to detect it. - */ - buf[10] = hdr->fcs; - buf[11] = hdr->fcs >> 8; -} - -/** - * Convert from disk structure to memory representation. - * \note filesystem is in little-endian format. - */ -INLINE void disk_to_battfs(uint8_t *buf, struct BattFsPageHeader *hdr) -{ - STATIC_ASSERT(BATTFS_HEADER_LEN == 12); - hdr->inode = buf[0]; - hdr->fill = buf[2] << 8 | buf[1]; - hdr->pgoff = buf[4] << 8 | buf[3]; - hdr->mark = (mark_t)(buf[7] & 0x01) << 16 | buf[6] << 8 | buf[5]; - hdr->seq = buf[7] >> 6; - hdr->fcs_free = buf[9] << 8 | buf[8]; - hdr->fcs = buf[11] << 8 | buf[10]; -} - -/** - * Compute the fcs of the header. - */ -static fcs_t computeFcs(struct BattFsPageHeader *hdr) -{ - uint8_t buf[BATTFS_HEADER_LEN]; - fcs_t cks; - - battfs_to_disk(hdr, buf); - rotating_init(&cks); - /* fcs is at the end of whole header */ - rotating_update(buf, BATTFS_HEADER_LEN - sizeof(fcs_t), &cks); - return cks; -} - -/** - * Compute the fcs of the header marked as free. - */ -static fcs_t computeFcsFree(struct BattFsPageHeader *hdr) -{ - uint8_t buf[BATTFS_HEADER_LEN]; - fcs_t cks; - - battfs_to_disk(hdr, buf); - rotating_init(&cks); - /* fcs_free is just before fcs of whole header */ - rotating_update(buf, BATTFS_HEADER_LEN - 2 * sizeof(fcs_t), &cks); - return cks; -} - - -/** - * Read header of page \a page. - * \return true on success, false otherwise. - * \note \a hdr is dirtyed even on errors. - */ -static bool battfs_readHeader(struct BattFsSuper *disk, pgcnt_t page, struct BattFsPageHeader *hdr) -{ - uint8_t buf[BATTFS_HEADER_LEN]; - /* - * Read header from disk. - * Header is actually a footer, and so - * resides at page end. - */ - if (disk->read(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) - != BATTFS_HEADER_LEN) - { - TRACEMSG("Error: page[%d]\n", page); - return false; - } - - /* Fill header */ - disk_to_battfs(buf, hdr); - - return true; -} - -/** - * Write header of page \a page. - * \return true on success, false otherwise. - * \note \a hdr is dirtyed even on errors. - */ -static bool battfs_writeHeader(struct BattFsSuper *disk, pgcnt_t page, struct BattFsPageHeader *hdr) -{ - uint8_t buf[BATTFS_HEADER_LEN]; - - /* Fill buffer */ - battfs_to_disk(hdr, buf); - - /* - * write header to disk. - * Header is actually a footer, and so - * resides at page end. - */ - if (disk->write(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN) - != BATTFS_HEADER_LEN) - { - TRACEMSG("Error: page[%d]\n", page); - return false; - } - return true; -} - -/** - * Count the number of pages from - * inode 0 to \a inode in \a filelen_table. - */ -static pgcnt_t countPages(pgoff_t *filelen_table, inode_t inode) -{ - pgcnt_t cnt = 0; - - for (inode_t i = 0; i < inode; i++) - cnt += filelen_table[i]; - - return cnt; -} - -/** - * Move all pages in page allocation array from \a src to \a src + \a offset. - * The number of pages moved is page_count - MAX(dst, src). - */ -static void movePages(struct BattFsSuper *disk, pgcnt_t src, int offset) -{ - pgcnt_t dst = src + offset; - memmove(&disk->page_array[dst], &disk->page_array[src], (disk->page_count - MAX(dst, src)) * sizeof(pgcnt_t)); - - if (offset < 0) - { - /* Fill empty space in array with sentinel */ - for (pgcnt_t page = disk->page_count + offset; page < disk->page_count; page++) - disk->page_array[page] = PAGE_UNSET_SENTINEL; - } -} - -/** - * Insert \a page into page allocation array of \a disk, - * using \a mark to compute position. - */ -static void insertFreePage(struct BattFsSuper *disk, mark_t mark, pgcnt_t page) -{ - ASSERT(mark - disk->free_start < disk->free_next - disk->free_start); - - pgcnt_t free_pos = disk->page_count - disk->free_next + mark; - ASSERT(free_pos < disk->page_count); - - TRACEMSG("mark:%u, page:%u, free_start:%u, free_next:%u, free_pos:%u\n", - mark, page, disk->free_start, disk->free_next, free_pos); - - ASSERT(disk->page_array[free_pos] == PAGE_UNSET_SENTINEL); - disk->page_array[free_pos] = page; -} - -/** - * Mark \a page of \a disk as free. - * \note free_next of \a disk is used as \a page free marker - * and is increased by 1. - */ -static bool battfs_markFree(struct BattFsSuper *disk, struct BattFsPageHeader *hdr, pgcnt_t page) -{ - uint8_t buf[BATTFS_HEADER_LEN]; - - hdr->mark = disk->free_next; - hdr->fcs_free = computeFcsFree(hdr); - battfs_to_disk(hdr, buf); - - if (!disk->write(disk, page, disk->page_size - BATTFS_HEADER_LEN, buf, BATTFS_HEADER_LEN)) - { - TRACEMSG("error marking page [%d]\n", page); - return false; - } - else - { - disk->free_next++; - return true; - } -} - -/** - * Determine free_start and free_next blocks for \a disk - * using \a minl, \a maxl, \a minh, \a maxh. - * - * Mark_t is a type that has at least 1 bit more than - * pgaddr_t. So all free blocks can be numbered using - * at most half numbers of a mark_t type. - * The free blocks algorithm increments by 1 the disk->free_next - * every time a page becomes free. So the free block sequence is - * guaranteed to be countiguous. - * Only wrap arounds may happen, but due to half size sequence limitation, - * there are only 4 possible situations: - * - * \verbatim - * |------lower half------|-------upper half-------| - * - * 1) |------minl*****maxl---|------------------------| - * 2) |------minl********maxl|minh******maxh----------| - * 3) |----------------------|----minh*******maxh-----| - * 4) |minl******maxl--------|------------minh****maxh| - * \endverbatim - * - * Situations 1 and 3 are easy to detect, while 2 and 4 require more care. - */ -static void findFreeStartNext(struct BattFsSuper *disk, mark_t minl, mark_t maxl, mark_t minh, mark_t maxh) -{ - /* Determine free_start & free_next */ - if (maxl >= minl) - { - /* Valid interval found in lower half */ - if (maxh >= minh) - { - /* Valid interval also found in upper half */ - if (maxl == minh - 1) - { - /* Interval starts in lower half and ends in upper */ - disk->free_start = minl; - disk->free_next = maxh; - } - else - { - /* Interval starts in upper half and ends in lower */ - ASSERT(minl == 0); - ASSERT(maxh == (MAX_PAGE_ADDR | MARK_HALF_SIZE)); - - disk->free_start = minh; - disk->free_next = maxl; - } - } - else - { - /* - * Upper interval is invalid. - * Use lower values. - */ - - disk->free_start = minl; - disk->free_next = maxl; - } - } - else if (maxh >= minh) - { - /* - * Lower interval is invalid. - * Use upper values. - */ - disk->free_start = minh; - disk->free_next = maxh; - } - else - { - /* - * No valid interval found. - * Hopefully the disk is brand new (or full). - */ - TRACEMSG("No valid marked free block found, new disk or disk full\n"); - disk->free_start = 0; - disk->free_next = -1; //to be increased later - } - - /* free_next should contain the first usable address */ - disk->free_next++; - - TRACEMSG("Free markers:\n minl %u\n maxl %u\n minh %u\n maxh %u\n free_start %u\n free_next %u\n", - minl, maxl, minh, maxh, disk->free_start, disk->free_next); -} - -/** - * Count number of pages per file on \a disk. - * This information is registered in \a filelen_table. - * Array index represent file inode, while value contained - * is the number of pages used by that file. - * - * \return true if ok, false on disk read errors. - * \note The whole disk is scanned once. - */ -static bool countDiskFilePages(struct BattFsSuper *disk, pgoff_t *filelen_table) -{ - BattFsPageHeader hdr; - mark_t minl, maxl, minh, maxh; - - /* Initialize min and max counters to keep trace od free blocks */ - minl = MAX_PAGE_ADDR; - maxl = 0; - minh = MAX_PAGE_ADDR | MARK_HALF_SIZE; - maxh = 0 | MARK_HALF_SIZE; - - - /* Count the number of disk page per file */ - for (pgcnt_t page = 0; page < disk->page_count; page++) - { - if (!battfs_readHeader(disk, page, &hdr)) - return false; - - /* Check header FCS */ - if (hdr.fcs == computeFcs(&hdr)) - { - ASSERT(hdr.mark == MARK_PAGE_VALID); - ASSERT(hdr.fcs_free == FCS_FREE_VALID); - ASSERT(hdr.fill <= disk->page_size - BATTFS_HEADER_LEN); - - /* Page is valid and is owned by a file */ - filelen_table[hdr.inode]++; - - /* Keep trace of free space */ - disk->free_bytes += disk->page_size - BATTFS_HEADER_LEN - hdr.fill; - } - else - { - /* Increase free space */ - disk->free_bytes += disk->page_size - BATTFS_HEADER_LEN; - - /* Check if page is marked free */ - if (hdr.fcs_free == computeFcsFree(&hdr)) - { - /* - * This page is a valid and marked free page. - * Update min and max free page markers. - */ - if (hdr.mark < MARK_HALF_SIZE) - { - minl = MIN(minl, hdr.mark); - maxl = MAX(maxl, hdr.mark); - } - else - { - minh = MIN(minh, hdr.mark); - maxh = MAX(maxh, hdr.mark); - } - } - else - TRACEMSG("page [%d] invalid, keeping as free\n", page); - } - } - findFreeStartNext(disk, minl, maxl, minh, maxh); - return true; -} - -/** - * Fill page allocation array of \a disk - * using file lenghts in \a filelen_table. - * - * The page allocation array is an array containings all file infos. - * Is ordered by file, and within each file is ordered by page offset - * inside file. - * e.g. : at page array[0] you will find page address of the first page - * of the first file (if present). - * Free blocks are allocated after the last file, starting from invalid ones - * and continuing with the marked free ones. - * - * \return true if ok, false on disk read errors. - * \note The whole disk is scanned once. - */ -static bool fillPageArray(struct BattFsSuper *disk, pgoff_t *filelen_table) -{ - BattFsPageHeader hdr; - /* Fill page allocation array */ - for (pgcnt_t page = 0; page < disk->page_count; page++) - { - if (!battfs_readHeader(disk, page, &hdr)) - return false; - - /* Check header FCS */ - if (hdr.fcs == computeFcs(&hdr)) - { - /* Page is valid and is owned by a file */ - ASSERT(hdr.mark == MARK_PAGE_VALID); - ASSERT(hdr.fcs_free == FCS_FREE_VALID); - - /* Compute array position */ - pgcnt_t array_pos = countPages(filelen_table, hdr.inode); - array_pos += hdr.pgoff; - - /* Check if position is already used by another page of the same file */ - if (LIKELY(disk->page_array[array_pos] == PAGE_UNSET_SENTINEL)) - disk->page_array[array_pos] = page; - else - { - BattFsPageHeader hdr_old; - - if (!battfs_readHeader(disk, disk->page_array[array_pos], &hdr_old)) - return false; - - /* Check header FCS */ - ASSERT(hdr_old.fcs == computeFcs(&hdr_old)); - - /* Only the very same page with a different seq number can be here */ - ASSERT(hdr.inode == hdr_old.inode); - ASSERT(hdr.pgoff == hdr_old.pgoff); - ASSERT(hdr.mark == hdr_old.mark); - ASSERT(hdr.fcs_free == hdr_old.fcs_free); - ASSERT(hdr.seq != hdr_old.seq); - - pgcnt_t new_page, old_page; - fill_t old_fill; - - /* Fancy check to handle seq wraparound (2 bits only) */ - if (((hdr.seq - hdr_old.seq) & 0x03) < 2) - { - /* Current header is newer than the previuos one */ - old_page = disk->page_array[array_pos]; - new_page = page; - old_fill = hdr_old.fill; - } - else - { - /* Previous header is newer than the current one */ - old_page = page; - new_page = disk->page_array[array_pos]; - old_fill = hdr.fill; - } - - /* Set new page */ - disk->page_array[array_pos] = new_page; - - /* Add free space */ - disk->free_bytes += old_fill; - - /* Shift all array one position to the left, overwriting duplicate page */ - array_pos -= hdr.pgoff; - array_pos += filelen_table[hdr.inode]; - movePages(disk, array_pos, -1); - - /* Decrease file page count */ - filelen_table[hdr.inode]--; - - /* Add old page to free pages pool */ - if (!battfs_markFree(disk, &hdr, old_page)) - return false; - - insertFreePage(disk, hdr.mark, old_page); - } - } - else - { - /* Check if page is free */ - if (hdr.fcs_free != computeFcsFree(&hdr)) - /* Page is not a valid marked page, insert at list beginning */ - hdr.mark = --disk->free_start; - - insertFreePage(disk, hdr.mark, page); - } - } - return true; -} - -/** - * Initialize and mount disk described by - * \a disk. - * \return false on errors, true otherwise. - */ -bool battfs_init(struct BattFsSuper *disk) -{ - pgoff_t filelen_table[BATTFS_MAX_FILES]; - - /* Sanity check */ - ASSERT(disk->open); - - /* Init disk device */ - if (!disk->open(disk)) - { - TRACEMSG("open error\n"); - return false; - } - - /* Disk open must set all of these */ - ASSERT(disk->read); - ASSERT(disk->write); - ASSERT(disk->erase); - ASSERT(disk->close); - ASSERT(disk->page_size); - ASSERT(disk->page_count); - ASSERT(disk->page_count < PAGE_UNSET_SENTINEL - 1); - ASSERT(disk->page_array); - - memset(filelen_table, 0, BATTFS_MAX_FILES * sizeof(pgoff_t)); - - disk->free_bytes = 0; - disk->disk_size = (disk_size_t)(disk->page_size - BATTFS_HEADER_LEN) * disk->page_count; - - /* Count pages per file */ - if (!countDiskFilePages(disk, filelen_table)) - { - TRACEMSG("error counting file pages\n"); - return false; - } - - /* Once here, we have filelen_table filled with file lengths */ - - /* Fill page array with sentinel */ - for (pgcnt_t page = 0; page < disk->page_count; page++) - disk->page_array[page] = PAGE_UNSET_SENTINEL; - - /* Fill page allocation array using filelen_table */ - if (!fillPageArray(disk, filelen_table)) - { - TRACEMSG("error filling page array\n"); - return false; - } - - /* Init list for opened files. */ - LIST_INIT(&disk->file_opened_list); - return true; -} - -/** - * Flush file \a fd. - * \return 0 if ok, EOF on errors. - */ -static int battfs_flush(struct KFile *fd) -{ - (void)fd; - #warning TODO - return 0; -} - -/** - * Close file \a fd. - * \return 0 if ok, EOF on errors. - */ -static int battfs_fileclose(struct KFile *fd) -{ - KFileBattFs *fdb = KFILEBATTFS(fd); - - battfs_flush(fd); - REMOVE(&fdb->link); - return 0; -} - -/** - * Read from file \a fd \a size bytes in \a buf. - * \return The number of bytes read. - */ -static size_t battfs_read(struct KFile *fd, void *_buf, size_t size) -{ - KFileBattFs *fdb = KFILEBATTFS(fd); - uint8_t *buf = (uint8_t *)_buf; - - size_t total_read = 0; - pgoff_t pg_offset; - pgaddr_t addr_offset; - pgaddr_t read_len; - - size = MIN(size, fd->size - fd->seek_pos); - - while (size) - { - pg_offset = fd->seek_pos / (fdb->disk->page_size - BATTFS_HEADER_LEN); - addr_offset = fd->seek_pos % (fdb->disk->page_size - BATTFS_HEADER_LEN); - read_len = MIN(size, (size_t)(fdb->disk->page_size - BATTFS_HEADER_LEN - addr_offset)); - - /* Read from disk */ - if (fdb->disk->read(fdb->disk, fdb->start[pg_offset], addr_offset, buf, read_len) != read_len) - { - #warning TODO set error? - } - - size -= read_len; - fd->seek_pos += read_len; - total_read += read_len; - buf += read_len; - } - return total_read; -} - - -/** - * Search file \a inode in \a disk using a binary search. - * \return pointer to file start in disk->page_array - * if file exists, NULL otherwise. - */ -static pgcnt_t *findFile(BattFsSuper *disk, inode_t inode) -{ - BattFsPageHeader hdr; - pgcnt_t first = 0, page, last = disk->page_count -1; - fcs_t fcs; - - while (first <= last) - { - page = (first + last) / 2; - - if (!battfs_readHeader(disk, disk->page_array[page], &hdr)) - return NULL; - - fcs = computeFcs(&hdr); - if (hdr.fcs == fcs && hdr.inode == inode) - return (&disk->page_array[page]) - hdr.pgoff; - else if (hdr.fcs == fcs && hdr.inode < inode) - first = page + 1; - else - last = page - 1; - } - - return NULL; -} - -/** - * \return true if file \a inode exists on \a disk, false otherwise. - */ -bool battfs_fileExists(BattFsSuper *disk, inode_t inode) -{ - return findFile(disk, inode) != NULL; -} - -/** - * Count size of file \a inode on \a disk, starting at pointer \a start - * in disk->page_array. Size is written in \a size. - * \return true if all s ok, false on disk read errors. - */ -static bool countFileSize(BattFsSuper *disk, pgcnt_t *start, inode_t inode, file_size_t *size) -{ - *size = 0; - BattFsPageHeader hdr; - - for (;;) - { - if (!battfs_readHeader(disk, *start++, &hdr)) - return false; - if (hdr.fcs == computeFcs(&hdr) && hdr.inode == inode) - *size += hdr.fill; - else - return true; - } -} - -/** - * Open file \a inode from \a disk in \a mode. - * File context is stored in \a fd. - * \return true if ok, false otherwise. - */ -bool battfs_fileopen(BattFsSuper *disk, KFileBattFs *fd, inode_t inode, filemode_t mode) -{ - Node *n; - - memset(fd, 0, sizeof(*fd)); - - /* Search file start point in disk page array */ - fd->start = findFile(disk, inode); - if (fd->start == NULL) - { - if (!(mode & BATTFS_CREATE)) - return false; - - /* File does not exist, create it */ - BattFsPageHeader hdr; - hdr.inode = inode; - hdr.seq = 0; - hdr.fill = 0; - hdr.pgoff = 0; - hdr.mark = MARK_PAGE_VALID; - hdr.fcs_free = FCS_FREE_VALID; - hdr.fcs = computeFcs(&hdr); - #warning TODO: get a free block and write on disk! - } - - /* Fill file size */ - if (!countFileSize(disk, fd->start, inode, &fd->fd.size)) - return false; - - /* Reset seek position */ - fd->fd.seek_pos = 0; - - /* Insert file handle in list, ordered by inode, ascending. */ - FOREACH_NODE(n, &disk->file_opened_list) - { - KFileBattFs *file = containerof(n, KFileBattFs, link); - if (file->inode >= inode) - break; - } - INSERT_BEFORE(&fd->link, n); - - /* Fill in data */ - fd->inode = inode; - fd->mode = mode; - fd->disk = disk; - - fd->fd.close = battfs_fileclose; - fd->fd.flush = battfs_flush; - fd->fd.read = battfs_read; - fd->fd.reopen = kfile_genericReopen; - fd->fd.seek = kfile_genericSeek; - -#warning TODO battfs_write, battfs_error, battfs_clearerr -#if 0 - fd->fd.write = battfs_write; - fd->fd.error = battfs_error; - fd->fd.clearerr = battfs_clearerr; -#endif - - DB(fd->fd._type = KFT_BATTFS); - - return true; -} - -/** - * Close \a disk. - */ -bool battfs_close(struct BattFsSuper *disk) -{ - Node *n; - int res = 0; - - /* Close all open files */ - FOREACH_NODE(n, &disk->file_opened_list) - { - KFileBattFs *file = containerof(n, KFileBattFs, link); - res += battfs_fileclose(&file->fd); - } - - /* Close disk */ - return disk->close(disk) && (res == 0); -} - - -bool battfs_writeTestBlock(struct BattFsSuper *disk, pgcnt_t page, inode_t inode, seq_t seq, fill_t fill, pgoff_t pgoff, mark_t mark) -{ - BattFsPageHeader hdr; - - hdr.inode = inode; - hdr.seq = seq; - hdr.fill = fill; - hdr.pgoff = pgoff; - hdr.mark = MARK_PAGE_VALID; - hdr.fcs_free = FCS_FREE_VALID; - hdr.fcs = computeFcs(&hdr); - if (mark != MARK_PAGE_VALID) - { - hdr.mark = mark; - hdr.fcs_free = computeFcsFree(&hdr); - } - - if (!battfs_writeHeader(disk, page, &hdr)) - { - TRACEMSG("error writing hdr\n"); - return false; - } - - return true; -} diff --git a/fs/battfs.h b/fs/battfs.h deleted file mode 100644 index 59d8fece..00000000 --- a/fs/battfs.h +++ /dev/null @@ -1,264 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Francesco Sacchi - * - * \brief BattFS: a filesystem for embedded platforms (interface). - * TODO: Add detailed filesystem description. - */ - -#ifndef FS_BATTFS_H -#define FS_BATTFS_H - -#include // uintXX_t; STATIC_ASSERT -#include // CPU_BITS_PER_CHAR -#include -#include -#include - -typedef uint16_t fill_t; ///< Type for keeping trace of space filled inside a page -typedef fill_t pgaddr_t; ///< Type for addressing space inside a page -typedef uint16_t pgcnt_t; ///< Type for counting pages on disk -typedef pgcnt_t pgoff_t; ///< Type for counting pages inside a file -typedef uint32_t mark_t; ///< Type for marking pages as free -typedef uint8_t inode_t; ///< Type for file inodes -typedef uint8_t seq_t; ///< Type for page seq number -typedef rotating_t fcs_t; ///< Type for header FCS. - -/** - * Size required for free block allocation is at least 1 bit more - * than page addressing. - */ -STATIC_ASSERT(sizeof(mark_t) > sizeof(pgcnt_t)); - -/** - * BattFS page header, used to represent a page - * header in memory. - * To see how this is stored on disk: - * \see battfs_to_disk - * \see disk_to_battfs - */ -typedef struct BattFsPageHeader -{ - inode_t inode; ///< File inode (file identifier). - seq_t seq; ///< Page sequence number. - fill_t fill; ///< Filled bytes in page. - pgoff_t pgoff; ///< Page offset inside file. - mark_t mark; ///< Marker used to keep trace of free/used pages. - - /** - * FCS (Frame Check Sequence) of the page header once the page - * as been marked as free. - */ - fcs_t fcs_free; - - /** - * FCS (Frame Check Sequence) of the page header. - */ - fcs_t fcs; -} BattFsPageHeader; - -/** - * Size of the header once saved on disk. - * \see battfs_to_disk - * \see disk_to_battfs - */ -#define BATTFS_HEADER_LEN 12 - -/** - * Marks for valid pages. - * Simply set to 1 all field bits. - * \{ - */ -#define MARK_PAGE_VALID ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t) + 1)) - 1) -#define FCS_FREE_VALID ((1 << (CPU_BITS_PER_CHAR * sizeof(fcs_t))) - 1) -/* \} */ - - -/** - * Half-size of free page marker. - * Used to keep trace of free marker wrap-arounds. - */ -#define MARK_HALF_SIZE (1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t) + 1)) - -/** - * Maximum page address. - */ -#define MAX_PAGE_ADDR ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t))) - 1) - -/** - * Max number of files. - */ -#define BATTFS_MAX_FILES (1 << (CPU_BITS_PER_CHAR * sizeof(inode_t))) - -/* Fwd decl */ -struct BattFsSuper; - -/** - * Sentinel used to keep trace of unset pages in disk->page_array. - */ -#define PAGE_UNSET_SENTINEL ((1 << (CPU_BITS_PER_CHAR * sizeof(pgcnt_t))) - 1) - -/** - * Type interface for disk init function. - * \return true if all is ok, false otherwise. - */ -typedef bool (*disk_open_t) (struct BattFsSuper *d); - -/** - * Type interface for disk page read function. - * \a page is the page address, \a addr the address inside the page, - * \a size the lenght to be read. - * \return the number of bytes read. - */ -typedef size_t (*disk_page_read_t) (struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, void *buf, size_t); - -/** - * Type interface for disk page write function. - * \a page is the page address, \a addr the address inside the page, - * \a size the lenght to be written. - * \return the number of bytes written. - */ -typedef size_t (*disk_page_write_t) (struct BattFsSuper *d, pgcnt_t page, pgaddr_t addr, const void *buf, size_t); - -/** - * Type interface for disk page erase function. - * \a page is the page address. - * \return true if all is ok, false otherwise. - */ -typedef bool (*disk_page_erase_t) (struct BattFsSuper *d, pgcnt_t page); - -/** - * Type interface for disk deinit function. - * \return true if all is ok, false otherwise. - */ -typedef bool (*disk_close_t) (struct BattFsSuper *d); - - -typedef uint32_t disk_size_t; ///< Type for disk sizes. - -/** - * Context used to describe a disk. - * This context structure will be used to access disk. - * Must be initialized by hw memory driver. - */ -typedef struct BattFsSuper -{ - disk_open_t open; ///< Disk init. - disk_page_read_t read; ///< Page read. - disk_page_write_t write; ///< Page write. - disk_page_erase_t erase; ///< Page erase. - disk_close_t close; ///< Disk deinit. - - pgaddr_t page_size; ///< Size of a disk page, in bytes. - pgcnt_t page_count; ///< Number of pages on disk. - - /** - * Page allocation array. - * This array must be allocated somewhere and - * must have enough space for page_count elements. - * Is used by the filesystem to represent - * the entire disk in memory. - */ - pgcnt_t *page_array; - - /** - * Lowest free page counter. - * This is the counter of the first availble free page. - */ - mark_t free_start; - - /** - * Highest free page counter. - * This value is the next to be used to mark a block as free. - */ - mark_t free_next; - - disk_size_t disk_size; ///< Size of the disk, in bytes (page_count * page_size). - disk_size_t free_bytes; ///< Free space on the disk. - - List file_opened_list; ///< List used to keep trace of open files. - /* TODO add other fields. */ -} BattFsSuper; - -typedef uint8_t filemode_t; ///< Type for file open modes. -typedef uint32_t file_size_t; ///< Type for file sizes. - -/** - * Modes for battfs_fileopen. - * \{ - */ -#define BATTFS_CREATE BV(0) ///< Create file if does not exist -#define BATTFS_RD BV(1) ///< Open file for reading -#define BATTFS_WR BV(2) ///< Open file fir writing -/*/}*/ - - -/** - * Describe a BattFs file usign a KFile. - */ -typedef struct KFileBattFs -{ - KFile fd; ///< KFile context - Node link; ///< Link for inserting in opened file list - inode_t inode; ///< inode of the opened file - BattFsSuper *disk; ///< Disk context - filemode_t mode; ///< File open mode - pgcnt_t *start; ///< Pointer to page_array file start position. -} KFileBattFs; - -/** - * Id for battfs file descriptors. - */ -#define KFT_BATTFS MAKE_ID('B', 'T', 'F', 'S') - -/** - * Macro used to cast a KFile to a KFileBattFs. - * Also perform dynamic type check. - */ -INLINE KFileBattFs * KFILEBATTFS(KFile *fd) -{ - ASSERT(fd->_type == KFT_BATTFS); - return (KFileBattFs *)fd; -} - -bool battfs_init(struct BattFsSuper *d); -bool battfs_close(struct BattFsSuper *disk); - -bool battfs_fileExists(BattFsSuper *disk, inode_t inode); -bool battfs_fileopen(BattFsSuper *disk, KFileBattFs *fd, inode_t inode, filemode_t mode); - -bool battfs_writeTestBlock(struct BattFsSuper *disk, pgcnt_t page, inode_t inode, seq_t seq, fill_t fill, pgoff_t pgoff, mark_t mark); - -#endif /* FS_BATTFS_H */ diff --git a/gfx/bitmap.c b/gfx/bitmap.c deleted file mode 100644 index d4c447e6..00000000 --- a/gfx/bitmap.c +++ /dev/null @@ -1,265 +0,0 @@ -/** - * \file - * - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief Bitmap manipulation routines. - */ - -#include "gfx.h" -#include "gfx_p.h" - -#include /* ASSERT() */ -#include /* CPU_HARVARD */ -#include /* MIN() */ -#include /* CONFIG_GFX_CLIPPING */ - -#include /* memset() */ - -#if CONFIG_GFX_TEXT -#include /* default_font */ -#endif - - -/** - * Initialize a Bitmap structure with the provided parameters. - * - * \note The pen position is reset to the origin. - */ -void gfx_bitmapInit(Bitmap *bm, uint8_t *raster, coord_t w, coord_t h) -{ - bm->raster = raster; - bm->width = w; - bm->height = h; - #if (CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB) - bm->stride = (w + 7) / 8; - #elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB - bm->stride = w; - #else - #error Unknown value of CONFIG_BITMAP_FMT - #endif /* CONFIG_BITMAP_FMT */ - bm->penX = 0; - bm->penY = 0; - -#if CONFIG_GFX_TEXT - gfx_setFont(bm, &default_font); - bm->styles = 0; -#endif - -#if CONFIG_GFX_CLIPPING - bm->cr.xmin = 0; - bm->cr.ymin = 0; - bm->cr.xmax = w; - bm->cr.ymax = h; -#endif /* CONFIG_GFX_CLIPPING */ -} - - -/** - * Clear the whole bitmap surface to the background color. - * - * \note This function does \b not update the current pen position. - * \note This function bypasses the current clipping area. - */ -void gfx_bitmapClear(Bitmap *bm) -{ - memset(bm->raster, 0, RAST_SIZE(bm->width, bm->height)); -} - - -#if CPU_HARVARD - -#include /* FIXME: memcpy_P() */ - -/** - * 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. - * - * \note This function does \b not update the current pen position - */ -void gfx_blit_P(Bitmap *bm, const pgm_uint8_t *raster) -{ - memcpy_P(bm->raster, raster, RAST_SIZE(bm->width, bm->height)); -} -#endif /* CPU_HARVARD */ - -#if CONFIG_GFX_CLIPPING - /** - * Clip destination coordinates inside a clipping range. - * - * This macro helps a drawing operation to adjust its - * destination X and Y coordinates inside the destination - * clipping range. - * - * The source start coordinate is adjusted as well - * when destination start clipping occurs. - */ - #define gfx_clip(dmin, dmax, smin, cmin, cmax) \ - do { \ - if ((dmin) < (cmin)) \ - { \ - (smin) += (cmin) - (dmin); \ - (dmin) = (cmin); \ - } \ - (dmax) = MIN((dmax), (cmax)); \ - } while(0) - -#else /* !CONFIG_GFX_CLIPPING */ - - #define gfx_clip(dmin, dmax, smin, cmin, cmax) do { } while (0) - -#endif /* !CONFIG_GFX_CLIPPING */ - - -/** - * Copy a rectangular area of a bitmap on another bitmap. - * - * Blitting is a common copy operation involving two bitmaps. - * A rectangular area of the source bitmap is copied bit-wise - * to a different position in the destination bitmap. - * - * \note Using the same bitmap for \a src and \a dst is unsupported. - * - * \param dst Bitmap where the operation writes. - * \param rect The (xmin;ymin) coordinates provide the top/left offset - * for drawing in the destination bitmap. If the source - * bitmap is larger than the rectangle, drawing is clipped. - * \param src Bitmap containing the source pixels. - * \param srcx Starting X offset in the source bitmap. - * \param srcy Starting Y offset in the source bitmap. - */ -void gfx_blit(Bitmap *dst, const Rect *rect, const Bitmap *src, coord_t srcx, coord_t srcy) -{ - coord_t dxmin, dymin, dxmax, dymax; - coord_t dx, dy, sx, sy; - - /* - * Pre-clip coordinates inside src->width/height. - */ - dxmin = rect->xmin; - dymin = rect->ymin; - dxmax = MIN(rect->xmax, rect->xmin + src->width); - dymax = MIN(rect->ymax, rect->ymin + src->height); - - /* Perform regular clipping */ - gfx_clip(dxmin, dxmax, srcx, dst->cr.xmin, dst->cr.xmax); - gfx_clip(dymin, dymax, srcy, dst->cr.ymin, dst->cr.ymax); - - //kprintf("dxmin=%d, sxmin=%d, dxmax=%d; ", dxmin, sxmin, dxmax); - //kprintf("dymin=%d, symin=%d, dymax=%d\n", dymin, symin, dymax); - - /* TODO: make it not as dog slow as this */ - for (dx = dxmin, sx = srcx; dx < dxmax; ++dx, ++sx) - for (dy = dymin, sy = srcy; dy < dymax; ++dy, ++sy) - BM_DRAWPIXEL(dst, dx, dy, BM_READPIXEL(src, sx, sy)); -} - -/** - * Blit a raster to a Bitmap. - * - * \todo Merge this function into gfx_blit() - * - * \see gfx_blit() - */ -void gfx_blitRaster(Bitmap *dst, coord_t dxmin, coord_t dymin, - const uint8_t *raster, coord_t w, coord_t h, coord_t stride) -{ - coord_t dxmax = dxmin + w, dymax = dymin + h; - coord_t sxmin = 0, symin = 0; - coord_t dx, dy, sx, sy; - - /* Perform regular clipping */ - gfx_clip(dxmin, dxmax, sxmin, dst->cr.xmin, dst->cr.xmax); - gfx_clip(dymin, dymax, symin, dst->cr.ymin, dst->cr.ymax); - - //kprintf("dxmin=%d, sxmin=%d, dxmax=%d; ", dxmin, sxmin, dxmax); - //kprintf("dymin=%d, symin=%d, dymax=%d\n", dymin, symin, dymax); - - /* TODO: make it not as dog slow as this */ - for (dx = dxmin, sx = sxmin; dx < dxmax; ++dx, ++sx) - for (dy = dymin, sy = symin; dy < dymax; ++dy, ++sy) - BM_DRAWPIXEL(dst, dx, dy, RAST_READPIXEL(raster, sx, sy, stride)); -} - -/** - * Blit an Image to a Bitmap. - * - * \see gfx_blit() - */ -void gfx_blitImage(Bitmap *dst, coord_t dxmin, coord_t dymin, const Image *image) -{ - ASSERT(image); - - gfx_blitRaster(dst, dxmin, dymin, - image->raster, image->width, image->height, image->stride); -} - - -#if CONFIG_GFX_CLIPPING || CONFIG_GFX_VCOORDS - -/** - * Set the bitmap clipping rectangle to the specified coordinates. - * - * All drawing performed on the bitmap will be clipped inside this - * rectangle. - * - * The clipping rectangle is also used as a bounding box for the - * logical view of the virtual coordinate system. - * - * \note Following the convention used for all other operations, the - * top-left pixels of the rectangle are included, while the - * bottom-right pixels are considered outside the clipping region. - * - * \see gfx_setViewRect - */ -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; - -// 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); -} - -#endif /* CONFIG_GFX_CLIPPING */ - diff --git a/gfx/charts.c b/gfx/charts.c deleted file mode 100644 index b4abbea0..00000000 --- a/gfx/charts.c +++ /dev/null @@ -1,195 +0,0 @@ -/** - * \file - * - * - * \brief Simple charts on top of mware/gfx routines (implementation). - * - * Sample usage: - * - * \code - * bm = chart_init(0, ymax, N_POINTS_CURVE, ymin); - * - * chart_drawCurve(bm, curve_y, curve_points + 1); - * gfx_setViewRect(bm, xmin, ymax, xmax, ymin); - * chart_drawDots(bm, samples_x, samples_y, samples_cnt); - * - * print_bitmap(bm); - * \endcode - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2005/11/27 23:33:29 bernie - *#* Reorder includes. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.7 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.6 2004/11/16 21:04:23 bernie - *#* Update to new naming scheme in mware/gfx.c. - *#* - *#* Revision 1.5 2004/09/14 20:56:39 bernie - *#* Make more generic and adapt to new gfx functions. - *#* - *#* Revision 1.3 2004/08/11 19:39:12 bernie - *#* Use chart_x_t and chart_y_t for the input dataset. - *#* - *#* Revision 1.1 2004/08/04 03:16:30 bernie - *#* Import simple chart drawing code. - *#* - *#*/ - -#include "charts.h" -#include - - -#ifndef CONFIG_CHART_ARROWS -#define CONFIG_CHART_ARROWS 0 -#endif - - -void chart_init(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax) -{ - /* Clear the chart area */ - gfx_rectClear(bm, xmin, ymin, xmax, ymax); - - gfx_setClipRect(bm, xmin + CHART_BORDERLEFT, ymin + CHART_BORDERTOP, - xmax - CHART_BORDERRIGHT, ymax - CHART_BORDERBOTTOM); - - chart_drawAxis(bm); -} - - -void chart_setScale(Bitmap *bm, chart_x_t xmin, chart_y_t ymin, chart_x_t xmax, chart_y_t ymax) -{ - gfx_setViewRect(bm, xmin, ymin, xmax, ymax); -} - - -/** - * Draw the chart axes - */ -void chart_drawAxis(Bitmap *bm) -{ -#if CONFIG_CHART_ARROWS - - /* Draw axis */ - gfx_moveTo(bm, bm->cr.xmin, bm->cr.ymin + 4); - gfx_lineTo(bm, bm->cr.xmin, bm->cr.ymax - 1); - gfx_lineTo(bm, bm->cr.xmax - 4 - 1, bm->cr.ymax - 1); - - /* Draw up arrow */ - gfx_moveTo(bm, bm->cr.xmin - 2, bm->cr.ymin + 3); - gfx_lineTo(bm, bm->cr.xmin + 2, bm->cr.ymin + 3); - gfx_lineTo(bm, bm->cr.xmin, bm->cr.ymin); - gfx_lineTo(bm, bm->cr.xmin - 2, bm->cr.ymin + 3); - - /* Draw right arrow */ - gfx_moveTo(bm, bm->cr.xmax - 4, bm->cr.ymax - 3); - gfx_lineTo(bm, bm->cr.xmax - 4, bm->cr.ymax + 1); - gfx_lineTo(bm, bm->cr.xmax - 1, bm->cr.ymax - 1); - gfx_lineTo(bm, bm->cr.xmax - 4, bm->cr.ymax - 3); - -#else /* CONFIG_CHART_ARROWS */ - - /* Draw a box around the chart */ - gfx_rectDraw(bm, bm->cr.xmin, bm->cr.ymin, bm->cr.xmax, bm->cr.ymax); - -#endif /* CONFIG_CHART_ARROWS */ - - //CHECK_WALL(wall_before_raster, WALL_SIZE); - //CHECK_WALL(wall_after_raster, WALL_SIZE); -} - - -/** - * Draw a set of \a curve_cnt connected segments, whose Y coordinates - * are identified by the \a curve_y array and X-coordinates are - * are evenly spaced by one virtual unit. - */ -void chart_drawCurve(Bitmap *bm, const chart_y_t *curve_y, int curve_cnt) -{ - int i; - - gfx_moveTo(bm, gfx_transformX(bm, 0), gfx_transformY(bm, curve_y[0])); - - for (i = 1; i < curve_cnt; i++) - gfx_lineTo(bm, gfx_transformX(bm, i), gfx_transformY(bm, curve_y[i])); - - //CHECK_WALL(wall_before_raster, WALL_SIZE); - //CHECK_WALL(wall_after_raster, WALL_SIZE); -} - - -/** - * Disegna dei dot in corrispondenza delle coppie (dotsx[i];dotsy[i]) - * Se dotsx e' NULL, i punti vengono disegnati ad intervalli regolari. - */ -void chart_drawDots(Bitmap *bm, const chart_x_t *dots_x, const chart_y_t *dots_y, int cnt) -{ - int i; - coord_t x, y; - - for (i = 0; i < cnt; i++) - { - if (dots_x) - x = gfx_transformX(bm, dots_x[i]); - else - x = gfx_transformX(bm, i); - - y = gfx_transformY(bm, dots_y[i]); - - /* Draw tick over the curve */ - gfx_rectFill(bm, - x - TICKS_WIDTH / 2, y - TICKS_HEIGHT / 2, - x + (TICKS_WIDTH + 1) / 2, y + (TICKS_HEIGHT + 1) / 2); - - /* Draw vertical line from the curve to the X-axis */ - //gfx_drawLine(bm, x, y, x, bm->cr.ymax - 1); - } - - //CHECK_WALL(wall_before_raster, WALL_SIZE); - //CHECK_WALL(wall_after_raster, WALL_SIZE); -} - diff --git a/gfx/charts.h b/gfx/charts.h deleted file mode 100644 index ce4bd883..00000000 --- a/gfx/charts.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file - * - * - * \brief Simple charts on top of mware/gfx routines (interface). - * - * Configuration: - * - \c CONFIG_CHART_TYPE_X: type for the input dataset of X-coordinates - * - \c CONFIG_CHART_TYPE_Y: type for the input dataset of Y-coordinates - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.5 2006/08/01 12:23:03 bernie - *#* Indentation fix. - *#* - *#* Revision 1.4 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2005/11/27 23:36:18 bernie - *#* Use appconfig.h instead of cfg/config.h. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.7 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.6 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.5 2004/09/14 20:56:39 bernie - *#* Make more generic and adapt to new gfx functions. - *#* - *#* Revision 1.3 2004/08/11 19:39:12 bernie - *#* Use chart_x_t and chart_y_t for the input dataset. - *#* - *#* Revision 1.1 2004/08/04 03:16:30 bernie - *#* Import simple chart drawing code. - *#* - *#*/ -#ifndef GFX_CHARTS_H -#define GFX_CHARTS_H - -#include /* vcoord_t */ -#include /* CONFIG_ stuff */ - -/** - * \name Width/height of the small ticks drawn over the axes - * \{ - */ -#define TICKS_HEIGHT 2 -#define TICKS_WIDTH 2 -/*\}*/ - -/** - * \name Chart frame dimensions - * \{ - */ -#define CHART_BORDERTOP 0 -#define CHART_BORDERBOTTOM 0 -#define CHART_BORDERLEFT 0 -#define CHART_BORDERRIGHT 0 -/*\}*/ - -#ifndef CONFIG_CHART_TYPE_X -#define CONFIG_CHART_TYPE_X vcoord_t -#endif -#ifndef CONFIG_CHART_TYPE_Y -#define CONFIG_CHART_TYPE_Y vcoord_t -#endif - - -typedef CONFIG_CHART_TYPE_X chart_x_t; -typedef CONFIG_CHART_TYPE_Y chart_y_t; - - -/* Public function protos */ -void chart_init(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax); -void chart_setScale(Bitmap *bm, chart_x_t xmin, chart_y_t ymin, chart_x_t xmax, chart_y_t ymax); -void chart_drawAxis(Bitmap *bm); -void chart_drawCurve(Bitmap *bm, const chart_y_t *curve_y, int curve_cnt); -void chart_drawDots(Bitmap *bm, const chart_x_t *dots_x, const chart_y_t *dots_y, int cnt); - -#endif /* GFX_CHARTS_H */ diff --git a/gfx/fillpoly.cpp b/gfx/fillpoly.cpp deleted file mode 100644 index 36483bf6..00000000 --- a/gfx/fillpoly.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * \author Massimiliano Corsini - * - * - * \brief Low-level drawing routines. - * - * This file contains the implementation of the low-level drawing routines - * to draw fill rectangle, fill triangle and so on. - * - */ - -/*#* - *#* $Log$ - *#* Revision 1.1 2006/07/19 13:00:01 bernie - *#* Import into DevLib. - *#* - *#* Revision 1.10 2005/10/15 15:03:43 rasky - *#* Remove per-pixel clipping from line(). - *#* Use clipLine() also for a-scope. - *#* - *#* Revision 1.9 2005/10/14 15:21:32 eldes - *#* Implement the cohen-sutherland clipping on the buffer - *#* - *#* Revision 1.8 2005/09/27 13:28:10 rasky - *#* Add clipping capabilities to line() - *#* Fix off-by-one computation of rectangles of drawing. - *#* - *#* Revision 1.7 2005/09/27 10:41:35 rasky - *#* Import line-drawing routine from Devlib - *#* - *#* Revision 1.6 2005/09/19 16:36:05 chad - *#* Fix doxygen autobrief - *#* - *#* Revision 1.5 2005/07/06 12:51:47 chad - *#* Make the fillRectangle() independent of the order of the points of the rectangle - *#* - *#* Revision 1.4 2005/06/17 15:06:36 chad - *#* Remove conversion warning - *#* - *#* Revision 1.3 2005/06/17 15:04:47 chad - *#* Add line clipping capability - *#* - *#* Revision 1.2 2005/06/15 14:04:43 chad - *#* Add line routine - *#* - *#* Revision 1.1 2005/06/15 13:34:34 chad - *#* Low-level drawing routines - *#* - *#*/ - -// Qt-specific headers -#include - - -/** - * Low-level routine to draw a line. - * - * This routine is based on the Bresenham Line-Drawing Algorithm. - * - * The \a stride represents the width of the image buffer. - * (\a x1, \a y1) are the coordinates of the starting point. - * (\a x2, \a y2) are the coordinates of the ending point. - * - * The line has no anti-alias, and clipping is not performed. The line - * must be fully contained in the buffer (use clipLine() if you need - * to clip it). - */ -void line(unsigned char *buf, - unsigned long bufw, unsigned long bufh, unsigned long stride, - int x1, int y1, int x2, int y2, unsigned char color) -{ - int x, y, e, len, adx, ady, signx, signy; - - 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 */ - assert(y >= 0 && y < static_cast(bufh) && - x >= 0 && x < static_cast(bufw)); - buf[y * stride + x] = color; - 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 */ - assert(y >= 0 && y < static_cast(bufh) && - x >= 0 && x < static_cast(bufw)); - buf[y * stride + x] = color; - y += signy; - e += adx; - if (e >= 0) - { - x += signx; - e -= ady; - } - } - } -} - -/// Helper routine for clipLine(). -static int region(int x, int y, int w, int h) -{ - int code = 0; - - if (y >= h) - code |= 1; // top - else if (y < 0) - code |= 2; // bottom - - if (x >= w) - code |= 4; // right - else if (x < 0) - code |= 8; // left - - return code; -} - -/** - * Low-level routine to draw a line, clipped to the buffer extents. - * - * This routine executes the clipping, and then invokes line(). - * Parameters are the same of line(). The clipping is performed - * using the Cohen-Sutherland algorithm, which is very fast. - */ -void clipLine(unsigned char *buf, - unsigned long w, unsigned long h, unsigned long stride, - int x1, int y1, int x2, int y2, unsigned char color) -{ - int code1 = region(x1, y1, w, h); - int code2 = region(x2, y2, w, h); - - // Loop while there is at least one point outside - while (code1 | code2) - { - // Check for line totally outside - if (code1 & code2) - return; - - int c = code1 ? code1 : code2; - int x, y; - - if (c & 1) // top - { - x = x1 + (x2 - x1) * (h - y1) / (y2 - y1); - y = h - 1; - } - else if (c & 2) //bottom - { - x = x1 + (x2 - x1) * -y1 / (y2 - y1); - y = 0; - } - else if (c & 4) //right - { - y = y1 + (y2 - y1) * (w - x1) / (x2 - x1); - x = w - 1; - } - else //left - { - y = y1 + (y2 - y1) * -x1 / (x2 - x1); - x = 0; - } - - if (c == code1) // first endpoint was clipped - { - x1 = x; y1 = y; - code1 = region(x1, y1, w, h); - } - else //second endpoint was clipped - { - x2 = x; y2 = y; - code2 = region(x2, y2, w, h); - } - } - - line(buf, w, h, stride, x1, y1, x2, y2, color); -} - - -/** - * Low-level routine to draw a filled rectangle. - * - * The triangle is filled with the given color. - * - * The \a stride represents the width of the image buffer. - * The points \a p1 and \a p2 are two opposite corners of the - * rectangle. - */ -void fillRectangle(unsigned char *buf, unsigned long stride, - QPoint p1, QPoint p2, unsigned char color) -{ - QPoint ul; // upper-left corner - QPoint lr; // lower-right corner - - if (p2.x() > p1.x()) - { - ul.setX(p1.x()); - lr.setX(p2.x()); - } - else - { - ul.setX(p2.x()); - lr.setX(p1.x()); - } - - if (p2.y() > p1.y()) - { - ul.setY(p1.y()); - lr.setY(p2.y()); - } - else - { - ul.setY(p2.y()); - lr.setY(p1.y()); - } - - int width = lr.x() - ul.x(); - unsigned long offset = ul.x() + ul.y()*stride; - - for (int h = ul.y(); h < lr.y(); h++) - { - memset(buf+offset, color, width); - offset += stride; - } -} - -/** - * Low-level routines to draw a filled triangle. - * - * The triangle is filled with the given \a color. - * The \a stride represents the width of the image buffer (\a buf). - * - * The routine use fixed-point arithmetic. - */ -void fillTriangle(unsigned char* buf, unsigned long stride, - QPoint v1, QPoint v2, QPoint v3, unsigned char color) -{ - int altezza[3]; - - // Sort by vertical coordinate - if (v1.y() > v2.y()) - std::swap(v1, v2); - if (v1.y() > v3.y()) - std::swap(v1, v3); - if (v2.y() > v3.y()) - std::swap(v2, v3); - - altezza[0] = v3.y() - v1.y(); - if (!altezza[0]) - return; - - int sezioni = 2; - int sezione = 1; - - buf += v1.y() * stride; - - altezza[1] = v2.y() - v1.y(); - altezza[2] = v3.y() - v2.y(); - - int sinistra = v1.x(); - int destra = sinistra; - - if (v1.y() == v2.y()) - { - if (v1.x() < v2.x()) - destra = v2.x(); - else - sinistra = v2.x(); - } - - sinistra <<= 16; - destra <<= 16; - - int stmp1, stmp2, stmp3; - - stmp1 = (altezza[1] << 16) / altezza[0]; - int lunghezza = stmp1 * (v3.x() - v1.x()) + ((v1.x() - v2.x()) << 16); - - if (!lunghezza ) - return; - - int delta_sinistra[2]; - int delta_destra[2]; - - stmp1 = ((v3.x() - v1.x()) << 16) / altezza[0]; - - if (altezza[1]) - stmp2 = ((v2.x() - v1.x()) << 16) / altezza[1]; - if (altezza[2]) - stmp3 = ((v3.x() - v2.x()) << 16) / altezza[2]; - - if (lunghezza < 0) // Il secondo vertice ~J a destra - { - delta_sinistra[0] = stmp1; - delta_sinistra[1] = stmp1; - delta_destra[0] = stmp2; - delta_destra[1] = stmp3; - } - else // Il secondo vertice ~J a sinistra - { - delta_sinistra[0] = stmp2; - delta_sinistra[1] = stmp3; - delta_destra[0] = stmp1; - delta_destra[1] = stmp1; - } - - int len2 = lunghezza; - - do - { - while (altezza [sezione]) - { - unsigned char* curpos = buf + ((sinistra )>> 16); - lunghezza = ((destra ) >> 16) - ((sinistra ) >> 16); - assert(lunghezza >= 0); - if (lunghezza) - memset(curpos, color, lunghezza); - buf += stride; - destra += delta_destra[sezione - 1]; - sinistra += delta_sinistra[sezione - 1]; - altezza[sezione]--; - } - if (len2 < 0) - destra = v2.x() << 16; - else - sinistra = v2.x() << 16; - sezione++; - } while (--sezioni); -} diff --git a/gfx/font.h b/gfx/font.h deleted file mode 100644 index b62b0b7c..00000000 --- a/gfx/font.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Stefano Fedrigo - * - * \brief Font 8x6 IBM-PC 8bit - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/05/27 22:31:34 bernie - *#* Switch to a smaller default fount. - *#* - *#* Revision 1.5 2006/03/13 02:06:04 bernie - *#* FONT_HAS_GLYPH(): New macro. - *#* - *#* Revision 1.4 2006/02/15 09:10:15 bernie - *#* Implement prop fonts; Fix algo styles. - *#* - *#* Revision 1.3 2006/02/10 12:29:05 bernie - *#* Add multiple font support in bitmaps. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.6 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.5 2005/03/01 23:26:45 bernie - *#* Use new CPU-neutral program-memory API. - *#* - *#* Revision 1.4 2004/12/31 16:42:55 bernie - *#* Sanitize for non-Harvard processors. - *#* - *#* Revision 1.3 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* 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 GFX_FONT_H -#define GFX_FONT_H - -#include /* uint8_t */ -#include /* PROGMEM */ - -typedef struct Font -{ - /** - * Pointer to glyph data. - * - * Data is an array of at most 256 glyphs packed together. - * Raster format must be the same of the bitmap. - */ - const PROGMEM uint8_t *glyph; - - uint8_t width; /**< Pixel width of character cell. */ - uint8_t height; /**< Pixel height of character cell. */ - - uint8_t first; /**< First encoded character in glyph array. */ - uint8_t last; /**< Last encoded character in glyph array (inclusive). */ - - /** Array of glyph offsets in bytes. NULL for fixed-width fonts. */ - const PROGMEM uint16_t *offset; - const PROGMEM uint8_t *widths; - -} Font; - - -/** Return true if glyph \a c is available in \a font. */ -#define FONT_HAS_GLYPH(font, c) ((c) >= (font)->first && (c) <= (font)->last) - - -/** The default font. */ -#define default_font font_luBS14 -extern const struct Font default_font; - -#endif /* GFX_FONT_H */ diff --git a/gfx/font_10x20.c b/gfx/font_10x20.c deleted file mode 100644 index 35cb9ad0..00000000 --- a/gfx/font_10x20.c +++ /dev/null @@ -1,5736 +0,0 @@ -/* Generated by convbdf on Fri Feb 10 01:05:15 CET 2006. */ -#include "font.h" - -/* Font information: - - name: -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO8859-1 - pixel size: 20 - ascent: 16 - descent: 4 -*/ - -/* Font character bitmap data. */ -static const PROGMEM uint8_t font_10x20_glyphs[] = { - -/* Character (0x00): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | *** *** | - | * * | - | * * | - | | - | | - | * * | - | * * | - | * * | - | | - | | - | * * | - | * * | - | *** *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0073, 0x0080, -0x0040, 0x0080, -0x0040, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0040, 0x0080, -0x0040, 0x0080, -0x0040, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0040, 0x0080, -0x0040, 0x0080, -0x0073, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x01): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | ** | - | **** | - | ****** | - | ******** | - | ******** | - | ****** | - | **** | - | ** | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x003f, 0x0000, -0x007f, 0x0080, -0x007f, 0x0080, -0x003f, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x02): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - | * * * * * | - |* * * * * | - +----------------+ */ -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, -0x0055, 0x0040, -0x00aa, 0x0080, - -/* Character (0x03): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x007e, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x0000, 0x0000, -0x001f, 0x0080, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x04): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | ***** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | ***** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x007c, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0078, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x000f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000f, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x05): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | **** | - | ** ** | - | ** | - | ** | - | ** ** | - | **** | - | | - | ***** | - | ** ** | - | ** ** | - | ***** | - | **** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x003c, 0x0000, -0x0066, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0066, 0x0000, -0x003c, 0x0000, -0x0000, 0x0000, -0x001f, 0x0000, -0x0019, 0x0080, -0x0019, 0x0080, -0x001f, 0x0000, -0x001e, 0x0000, -0x001b, 0x0000, -0x0019, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x06): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ***** | - | | - | ***** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x003e, 0x0000, -0x0000, 0x0000, -0x000f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000f, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x07): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | **** | - | ** ** | - | ** ** | - | **** | - | ** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x08): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | ** | - | ** | - | ******** | - | ** | - | ** | - | | - | ******** | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x09): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | ** ** | - | *** ** | - | ****** | - | ****** | - | ** *** | - | ** ** | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ***** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0066, 0x0000, -0x0076, 0x0000, -0x007e, 0x0000, -0x007e, 0x0000, -0x006e, 0x0000, -0x0066, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x0a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | ** ** | - | ** ** | - | ** ** | - | **** | - | **** | - | ** | - | ** | - | | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x003c, 0x0000, -0x003c, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0000, 0x0000, -0x001f, 0x0080, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x0b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - |***** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x00f8, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x0c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - |***** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00f8, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x0d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | ****** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000f, 0x00c0, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x0e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | ****** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x000f, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x0f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - |********** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x00ff, 0x00c0, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x10): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - |********** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x00ff, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x11): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - |********** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x12): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - |********** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x13): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - |********** | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x14): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - |********** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x00c0, - -/* Character (0x15): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | ****** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x000f, 0x00c0, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x16): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - |***** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x00f8, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x17): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - |********** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x00ff, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x18): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - |********** | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x00c0, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x19): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +----------------+ */ -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, -0x0008, 0x0000, - -/* Character (0x1a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | *** | - |*** | - | *** | - | *** | - | *** | - | | - | | - |********* | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0003, 0x0080, -0x000e, 0x0000, -0x0038, 0x0000, -0x00e0, 0x0000, -0x0038, 0x0000, -0x000e, 0x0000, -0x0003, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x1b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - |*** | - | *** | - | *** | - | *** | - | *** | - | *** | - |*** | - | | - | | - |********* | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00e0, 0x0000, -0x0038, 0x0000, -0x000e, 0x0000, -0x0003, 0x0080, -0x000e, 0x0000, -0x0038, 0x0000, -0x00e0, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x00ff, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x1c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ******** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x1d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | ** | - | ** | - | ** | - | ******** | - | ** | - | ** | - | ******** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0006, 0x0000, -0x007f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x0018, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x1e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** | - | ** | - | ****** | - | ** | - | ** | - | ** | - | ***** | - | * * ** ** | - | *** *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000f, 0x0000, -0x0019, 0x0080, -0x0019, 0x0080, -0x0018, 0x0000, -0x0018, 0x0000, -0x007e, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x007c, 0x0000, -0x0056, 0x00c0, -0x0073, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x1f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | *** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x20): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x21): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x22): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | * * | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0012, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x23): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ******** | - | ** ** | - | ** ** | - | ** ** | - | ******** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000d, 0x0080, -0x000d, 0x0080, -0x000d, 0x0080, -0x003f, 0x00c0, -0x001b, 0x0000, -0x001b, 0x0000, -0x001b, 0x0000, -0x007f, 0x0080, -0x0036, 0x0000, -0x0036, 0x0000, -0x0036, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x24): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ****** | - | ** ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** ** | - | ****** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x003f, 0x0000, -0x006d, 0x0080, -0x006c, 0x0000, -0x006c, 0x0000, -0x006c, 0x0000, -0x003f, 0x0000, -0x000d, 0x0080, -0x000d, 0x0080, -0x000d, 0x0080, -0x006d, 0x0080, -0x003f, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x25): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | *** ** | - | ** ** ** | - | ** **** | - | *** ** | - | ** | - | ** | - | ** | - | ** | - | ** *** | - | **** ** | - | ** ** ** | - | ** *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0039, 0x0080, -0x006d, 0x0080, -0x006f, 0x0000, -0x003b, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x001b, 0x0080, -0x001e, 0x00c0, -0x0036, 0x00c0, -0x0033, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x26): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | *** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | ** | - | *** | - | ** ** | - | ** ** ** | - | ** *** | - | ** ** | - | *** **** | - | **** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001c, 0x0000, -0x0036, 0x0000, -0x0036, 0x0000, -0x0036, 0x0000, -0x003c, 0x0000, -0x0018, 0x0000, -0x0038, 0x0000, -0x006c, 0x0000, -0x0066, 0x00c0, -0x0063, 0x0080, -0x0063, 0x0000, -0x0077, 0x0080, -0x003c, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x27): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | * | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0008, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x28): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0003, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0003, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x29): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0030, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | **** | - | ******** | - | **** | - | ** ** | - | ** ** | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x007f, 0x0080, -0x001e, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | ** | - | ** | - | ** | - | ******** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | *** | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x001c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | ******** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x2f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x0003, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x30): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x31): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | *** | - | **** | - | ** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001c, 0x0000, -0x003c, 0x0000, -0x006c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x32): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** | - | ** | - | ** | - | *** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x000e, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x33): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** | - | ** | - | *** | - | ** | - | ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x000e, 0x0000, -0x0003, 0x0000, -0x0001, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x34): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | * | - | ** | - | *** | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ******** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0001, 0x0000, -0x0003, 0x0000, -0x0007, 0x0000, -0x000f, 0x0000, -0x001b, 0x0000, -0x0033, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x007f, 0x0080, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x35): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** *** | - | *** ** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x36): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** * | - | ** | - | ** | - | ** *** | - | *** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x37): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x0003, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x38): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x39): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | *** ** | - | ** | - | ** | - | * ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001d, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0021, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | | - | | - | | - | | - | *** | - | *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | *** | - | *** | - | | - | | - | | - | | - | *** | - | *** | - | *** | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000e, 0x0000, -0x000e, 0x0000, -0x001c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | * | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | * | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0001, 0x0000, -0x0003, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0060, 0x0000, -0x0030, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0003, 0x0000, -0x0001, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | ******** | - | | - | | - | | - | | - | ******** | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | * | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | * | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0020, 0x0000, -0x0030, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0003, 0x0000, -0x0001, 0x0080, -0x0003, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0020, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x3f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0003, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x40): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** **** | - | ** ***** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** **** | - | ** ** | - | ** | - | ** ** | - | ***** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0067, 0x0080, -0x006f, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006f, 0x0000, -0x0066, 0x0000, -0x0060, 0x0000, -0x0031, 0x0080, -0x001f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x41): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ******** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x007f, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x42): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ***** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007c, 0x0000, -0x0066, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x0066, 0x0000, -0x007e, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0063, 0x0000, -0x007e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x43): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x44): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007e, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0063, 0x0000, -0x007e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x45): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007e, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x46): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007e, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x47): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** | - | ** | - | ** | - | ** **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | **** * | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0067, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001e, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x48): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ******** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x007f, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x49): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | ** ** | - | *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000f, 0x00c0, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x0036, 0x0000, -0x001c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ***** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0063, 0x0000, -0x0063, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x007c, 0x0000, -0x0066, 0x0000, -0x0066, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | *** *** | - | *** *** | - | ******** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0073, 0x0080, -0x0073, 0x0080, -0x007f, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | *** ** | - | *** ** | - | **** ** | - | **** ** | - | ** ** ** | - | ** ** ** | - | ** **** | - | ** **** | - | ** *** | - | ** *** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0071, 0x0080, -0x0071, 0x0080, -0x0079, 0x0080, -0x0079, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x0067, 0x0080, -0x0067, 0x0080, -0x0063, 0x0080, -0x0063, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x4f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x50): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007e, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0063, 0x0000, -0x007e, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x51): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** ** | - | ** **** | - | ** ** | - | ***** | - | ** | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x006d, 0x0080, -0x0067, 0x0080, -0x0033, 0x0000, -0x001f, 0x0000, -0x0001, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x52): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007e, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0063, 0x0000, -0x007e, 0x0000, -0x0066, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x53): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0030, 0x0000, -0x001e, 0x0000, -0x0003, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x54): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x55): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x56): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | **** | - | **** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x57): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | *** *** | - | *** *** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x0073, 0x0080, -0x0073, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x58): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | **** | - | ** | - | **** | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x59): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ******** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ****** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003f, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x003f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0006, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ****** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003f, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x0003, 0x0000, -0x003f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | **** | - | ** ** | - | ** ** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x5f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | ********* | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x007f, 0x00c0, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x60): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0018, 0x0000, -0x000c, 0x0000, -0x0006, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x61): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ***** | - | ** ** | - | ** | - | ******* | - | ** ** | - | ** ** | - | ** ** | - | ***** * | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001f, 0x0000, -0x0031, 0x0080, -0x0001, 0x0080, -0x003f, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x003e, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x62): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** *** | - | *** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | *** ** | - | ** *** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0073, 0x0000, -0x006e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x63): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ***** | - | ** ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | ***** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001f, 0x0000, -0x0031, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0031, 0x0080, -0x001f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x64): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | *** ** | - | ** *** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | *** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x001d, 0x0080, -0x0033, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001d, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x65): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ******** | - | ** | - | ** | - | ** ** | - | ***** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x007f, 0x0080, -0x0060, 0x0000, -0x0060, 0x0000, -0x0031, 0x0080, -0x001f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x66): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** | - | ** | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000f, 0x0000, -0x0019, 0x0080, -0x0019, 0x0080, -0x0018, 0x0000, -0x0018, 0x0000, -0x007e, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x67): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ***** * | - | ** *** | - | ** ** | - | ** ** | - | ** ** | - | ***** | - | ** | - | ****** | - | ** ** | - | ** ** | - | ** ** | - | ****** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003e, 0x0080, -0x0063, 0x0080, -0x0063, 0x0000, -0x0063, 0x0000, -0x0063, 0x0000, -0x003e, 0x0000, -0x0060, 0x0000, -0x003f, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x003f, 0x0000, - -/* Character (0x68): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** *** | - | *** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x69): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | ** | - | ** | - | | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x003c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x6a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | ** | - | ** | - | | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | ** ** | - | ***** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0000, 0x0000, -0x0007, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0031, 0x0080, -0x0031, 0x0080, -0x0031, 0x0080, -0x001f, 0x0000, - -/* Character (0x6b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | ***** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0063, 0x0000, -0x0066, 0x0000, -0x006c, 0x0000, -0x0078, 0x0000, -0x007c, 0x0000, -0x0066, 0x0000, -0x0063, 0x0000, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x6c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x007f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x6d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | * ** ** | - | ******** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x005b, 0x0000, -0x007f, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x6e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** *** | - | *** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x6f): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | **** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x70): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** *** | - | *** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | *** ** | - | ** *** | - | ** | - | ** | - | ** | - | ** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x006e, 0x0000, -0x0073, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0073, 0x0000, -0x006e, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, -0x0060, 0x0000, - -/* Character (0x71): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | *** ** | - | ** *** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | *** ** | - | ** | - | ** | - | ** | - | ** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x001d, 0x0080, -0x0033, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001d, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, -0x0001, 0x0080, - -/* Character (0x72): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** **** | - | *** ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x006f, 0x0000, -0x0039, 0x0080, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0030, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x73): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ****** | - | ** ** | - | ** | - | ****** | - | ** | - | ** | - | ** ** | - | ****** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003f, 0x0000, -0x0061, 0x0080, -0x0060, 0x0000, -0x003f, 0x0000, -0x0001, 0x0080, -0x0001, 0x0080, -0x0061, 0x0080, -0x003f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x74): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | ** | - | ** | - | ** | - | ****** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x007e, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0018, 0x0000, -0x0019, 0x0080, -0x000f, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x75): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | *** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001d, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x76): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | **** | - | **** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x0033, 0x0000, -0x001e, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x77): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** ** | - | ** ** ** | - | ** ** ** | - | ******** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x006d, 0x0080, -0x007f, 0x0080, -0x0033, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x78): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | **** | - | ** | - | ** | - | **** | - | ** ** | - | ** ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x001e, 0x0000, -0x0033, 0x0000, -0x0061, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x79): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** ** | - | ** *** | - | *** ** | - | ** | - | ** ** | - | ** ** | - | **** | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0061, 0x0080, -0x0033, 0x0080, -0x001d, 0x0080, -0x0001, 0x0080, -0x0061, 0x0080, -0x0033, 0x0000, -0x001e, 0x0000, - -/* Character (0x7a): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | | - | | - | | - | | - | | - | ******* | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ******* | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x003f, 0x0080, -0x0001, 0x0080, -0x0003, 0x0000, -0x0006, 0x0000, -0x000c, 0x0000, -0x0018, 0x0000, -0x0030, 0x0000, -0x003f, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x7b): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0007, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0078, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0007, 0x0080, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x7c): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | ** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x7d): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | **** | - | ** | - | ** | - | ** | - | ** | - | ** | - | **** | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0078, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0007, 0x0080, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x000c, 0x0000, -0x0078, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, - -/* Character (0x7e): - bbw=10, bbh=20, bbx=0, bby=-4, width=10 - +----------------+ - | | - | | - | | - | *** ** | - | ** ** ** | - | ** *** | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +----------------+ */ -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0039, 0x0080, -0x006d, 0x0080, -0x0067, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -0x0000, 0x0000, -}; - -/* Exported structure definition. */ -Font font_10x20 = { - font_10x20_glyphs, - 10, - 20 -}; diff --git a/gfx/gfx.h b/gfx/gfx.h deleted file mode 100644 index a852c54d..00000000 --- a/gfx/gfx.h +++ /dev/null @@ -1,204 +0,0 @@ -/** - * \file - * Copyright 2003, 2004, 2005, 2006 Develer S.r.l. (http://www.develer.com/) - * Copyright 1999 Bernardo Innocenti - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief General pourpose graphics routines - */ - -#ifndef GFX_GFX_H -#define GFX_GFX_H - -#include -#include /* CPU_HARVARD */ - -#include /* CONFIG_GFX_* */ - -/** - * \name Known pixel formats for bitmap representation. - * \{ - */ -#define BITMAP_FMT_PLANAR_H_MSB 1 /**< Planar pixels, horizontal bytes, MSB left. */ -#define BITMAP_FMT_PLANAR_V_LSB 2 /**< Planar pixels, vertical bytes, LSB top. */ -/* \} */ - -#if !defined(CONFIG_BITMAP_FMT) || (CONFIG_BITMAP_FMT != BITMAP_FMT_PLANAR_H_MSB && CONFIG_BITMAP_FMT != BITMAP_FMT_PLANAR_V_LSB) - #error CONFIG_BITMAP_FMT must be defined to either BITMAP_FMT_PLANAR_H_LSB or BITMAP_FMT_PLANAR_V_LSB -#endif -#if !defined(CONFIG_GFX_CLIPPING) || (CONFIG_GFX_CLIPPING != 0 && CONFIG_GFX_CLIPPING != 1) - #error CONFIG_GFX_CLIPPING must be defined to either 0 or 1 -#endif -#if !defined(CONFIG_GFX_TEXT) || (CONFIG_GFX_TEXT != 0 && CONFIG_GFX_TEXT != 1) - #error CONFIG_GFX_TEXT must be defined to either 0 or 1 -#endif - -EXTERN_C_BEGIN - -/** Common type for coordinates expressed in pixel units */ -typedef int coord_t; -typedef unsigned int ucoord_t; - -#if CONFIG_GFX_VCOORDS -/** Common type for coordinates expressed in logical units */ -typedef float vcoord_t; -#endif /* CONFIG_GFX_VCOORDS */ - - -/** - * Describe a rectangular area with coordinates expressed in pixels. - * - * The rectangle is represented in terms of its top/left and - * right/bottom borders. - * - * In some cases, rectangles are assumed to obey to the - * following invariants: - * - * xmin <= xmax - * ymin <= ymax - * - * Oddly, the xmin and ymin coordinates are inclusive, while the - * xmax and ymax coordinates are non-inclusive. This design - * decision makes several computations simpler and lets you - * specify empty (0x0) rectangles without breaking the - * invariants. - * - * Computing the size of a rectangle can be done by simply - * subtracting the maximum X or Y coordinate from the minimum - * X or Y coordinate. - */ -typedef struct Rect { coord_t xmin, ymin, xmax, ymax; } Rect; - -/** - * Return the width of a rectangle in pixels. - * - * \note The argument \a r is evaluated twice. - */ -#define RECT_WIDTH(r) ((r)->xmax - (r)->xmin) - -/** - * Return the height of a rectangle in pixels. - * - * \note The argument \a r is evaluated twice. - */ -#define RECT_HEIGHT(r) ((r)->ymax - (r)->ymin) - -/* Fwd decl */ -struct Font; - -/** - * Control structure to draw in a bitmap - * - * \todo For better ortogonality, split this structure into - * an Image and a plain drawing context called Painter. - */ -typedef struct Bitmap -{ - uint8_t *raster; /**< Pointer to byte array to hold the data */ - coord_t width, height; /**< Width/Height in pixels */ - coord_t stride; /**< Bytes per row. */ - coord_t penX, penY; /**< Current pen position MoveTo()/LineTo() */ - -#if CONFIG_GFX_CLIPPING || CONFIG_GFX_VCOORDS - Rect cr; /**< Clip drawing inside this rectangle */ -#endif - -#if CONFIG_GFX_TEXT - const struct Font *font;/**< Current font for text rendering. */ - - /** - * Algorithmic text style flags. - * - * The text rendering routine can apply a few simple transformations - * to the current font in order to generate common styles such as - * bold, italic and underline from plain glyphs. - * - * \see text_style() - */ - uint8_t styles; -#endif /* CONFIG_GFX_TEXT */ - -#if CONFIG_GFX_VCOORDS - /** - * \name Logical coordinate system - * \{ - */ - vcoord_t orgX, orgY; - vcoord_t scaleX, scaleY; - /*\}*/ -#endif /* CONFIG_GFX_VCOORDS */ - -} Bitmap; - -/** - * Hold image pixels. - * - * \todo Use this as Bitmap and change Bitmap to Drawable. - */ -typedef struct Image -{ - const uint8_t *raster; /**< Pointer to byte array to hold the data. */ - coord_t width; /**< Raster width in pixels. */ - coord_t height; /**< Raster height in pixels. */ - coord_t stride; /**< Bytes per row. */ -} Image; - -#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB - /** - * Compute the size in bytes of a raster suitable for - * holding a bitmap of \a width x \a height pixels. - */ - #define RAST_SIZE(width, height) ( ((width) + 7 / 8) * (height) ) - -#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB - /** - * Compute the size in bytes of a raster suitable for - * holding a bitmap of \a width x \a height pixels. - */ - #define RAST_SIZE(width, height) ( (width) * (((height) + 7) / 8) ) -#else - #error Unknown value of CONFIG_BITMAP_FMT -#endif /* CONFIG_BITMAP_FMT */ - -/* Function prototypes */ -void gfx_bitmapInit (Bitmap *bm, uint8_t *raster, coord_t w, coord_t h); -void gfx_bitmapClear(Bitmap *bm); -void gfx_blit (Bitmap *dst, const Rect *rect, const Bitmap *src, coord_t srcx, coord_t srcy); -void gfx_blitRaster (Bitmap *dst, coord_t dx, coord_t dy, const uint8_t *raster, coord_t w, coord_t h, coord_t stride); -void gfx_blitImage (Bitmap *dst, coord_t dx, coord_t dy, const Image *image); -void gfx_line (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); -void gfx_rectDraw (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); -void gfx_rectFillC (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t color); -void gfx_rectFill (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); -void gfx_rectClear (Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2); -void gfx_moveTo (Bitmap *bm, coord_t x, coord_t y); -void gfx_lineTo (Bitmap *bm, coord_t x, coord_t y); -void gfx_setClipRect(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax); - -#if CPU_HARVARD - #include - void gfx_blit_P(Bitmap *bm, const pgm_uint8_t *raster); -#endif - -#if CONFIG_GFX_TEXT -INLINE void gfx_setFont(Bitmap *bm, const struct Font *font) -{ - bm->font = font; -} -#endif - -#if CONFIG_GFX_VCOORDS -void gfx_setViewRect(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2); -coord_t gfx_transformX(Bitmap *bm, vcoord_t x); -coord_t gfx_transformY(Bitmap *bm, vcoord_t y); -void gfx_vline(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2); -#endif /* CONFIG_GFX_VCOORDS */ - -EXTERN_C_END - -#endif /* GFX_GFX_H */ diff --git a/gfx/gfx_p.h b/gfx/gfx_p.h deleted file mode 100644 index c2f10b49..00000000 --- a/gfx/gfx_p.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Graphics private header. - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/05/27 17:17:34 bernie - *#* Optimize away divisions in RAST_ADDR/MASK macros. - *#* - *#* Revision 1.5 2006/05/25 23:35:40 bernie - *#* Cleanup. - *#* - *#* Revision 1.4 2006/03/22 09:50:37 bernie - *#* Use the same format for fonts and rasters. - *#* - *#* Revision 1.3 2006/02/15 09:10:15 bernie - *#* Implement prop fonts; Fix algo styles. - *#* - *#* Revision 1.2 2006/02/10 12:28:33 bernie - *#* Add font support in bitmaps; Make bitmap formats public. - *#* - *#* Revision 1.1 2006/01/26 00:32:49 bernie - *#* Graphics private header. - *#* - *#*/ - -#ifndef GFX_GFX_P_H -#define GFX_GFX_P_H - -#include - -#if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB - - /* We use ucoord_t to let the compiler optimize away the division/modulo. */ - #define RAST_ADDR(raster, x, y, stride) \ - ((raster) + (ucoord_t)(y) * (ucoord_t)(stride) + (ucoord_t)(x) / 8) - #define RAST_MASK(raster, x, y) \ - (1 << (7 - (ucoord_t)(x) % 8)) - -#elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB - - /* We use ucoord_t to let the compiler optimize away the division/modulo. */ - #define RAST_ADDR(raster, x, y, stride) \ - ((raster) + ((ucoord_t)(y) / 8) * (ucoord_t)(stride) + (ucoord_t)(x)) - #define RAST_MASK(raster, x, y) \ - (1 << ((ucoord_t)(y) % 8)) - -#else - #error Unknown value of CONFIG_BITMAP_FMT -#endif /* CONFIG_BITMAP_FMT */ - -#define BM_ADDR(bm, x, y) RAST_ADDR((bm)->raster, (x), (y), (bm)->stride) -#define BM_MASK(bm, x, y) RAST_MASK((bm)->raster, (x), (y)) - -/** - * Plot a pixel in bitmap \a bm. - * - * \note bm is evaluated twice. - * \see BM_CLEAR BM_DRAWPIXEL - */ -#define BM_PLOT(bm, x, y) \ - ( *BM_ADDR(bm, x, y) |= BM_MASK(bm, x, y) ) - -/** - * Clear a pixel in bitmap \a bm. - * - * \note bm is evaluated twice. - * \see BM_PLOT BM_DRAWPIXEL - */ -#define BM_CLEAR(bm, x, y) \ - ( *BM_ADDR(bm, x, y) &= ~BM_MASK(bm, x, y) ) - -/** - * Set a pixel in bitmap \a bm to the specified color. - * - * \note bm is evaluated twice. - * \note This macro is somewhat slower than BM_PLOT and BM_CLEAR. - * \see BM_PLOT BM_CLEAR - */ -#define BM_DRAWPIXEL(bm, x, y, fg_pen) \ - do { \ - uint8_t *p = BM_ADDR(bm, x, y); \ - uint8_t mask = BM_MASK(bm, x, y); \ - *p = (*p & ~mask) | ((fg_pen) ? mask : 0); \ - } while (0) - -/** - * Get the value of the pixel in bitmap \a bm. - * - * \return The returned value is either 0 or 1. - * - * \note bm is evaluated twice. - * \see BM_DRAWPIXEL - */ -#define BM_READPIXEL(bm, x, y) \ - ( *BM_ADDR(bm, x, y) & BM_MASK(bm, x, y) ? 1 : 0 ) - -#define RAST_READPIXEL(raster, x, y, stride) \ - ( *RAST_ADDR(raster, x, y, stride) & RAST_MASK(raster, x, y) ? 1 : 0 ) - -#endif /* GFX_GFX_P_H */ diff --git a/gfx/line.c b/gfx/line.c deleted file mode 100644 index f3909b15..00000000 --- a/gfx/line.c +++ /dev/null @@ -1,408 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief Line drawing graphics routines - */ - -#include "gfx.h" -#include "gfx_p.h" - -#include /* ASSERT() */ -#include /* SWAP() */ -#include /* CONFIG_GFX_CLIPPING */ - -/* Configuration sanity checks */ -#if !defined(CONFIG_GFX_CLIPPING) || (CONFIG_GFX_CLIPPING != 0 && CONFIG_GFX_CLIPPING != 1) - #error CONFIG_GFX_CLIPPING must be defined to either 0 or 1 -#endif -#if !defined(CONFIG_GFX_VCOORDS) || (CONFIG_GFX_VCOORDS != 0 && CONFIG_GFX_VCOORDS != 1) - #error CONFIG_GFX_VCOORDS must be defined to either 0 or 1 -#endif - -/** - * Draw a sloped line without performing clipping. - * - * Parameters are the same of gfx_line(). - * This routine is based on the Bresenham Line-Drawing Algorithm. - * - * \note Passing coordinates outside the bitmap boundaries will - * result in memory trashing. - * - * \todo Optimize for vertical and horiziontal lines. - * - * \sa gfx_line() - */ -static void gfx_lineUnclipped(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ - int x, y, e, len, adx, ady, signx, signy; - - 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 */ - ASSERT((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 */ - ASSERT ((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; - } - } - } -} - -#if CONFIG_GFX_CLIPPING - -/// Helper routine for gfx_line(). -static int gfx_findRegion(int x, int y, Rect *cr) -{ - int code = 0; - - if (y >= cr->ymax) - code |= 1; /* below */ - else if (y < cr->ymin) - code |= 2; /* above */ - - if (x >= cr->xmax) - code |= 4; /* right */ - else if (x < cr->xmin) - code |= 8; /* left */ - - return code; -} - -#endif /* CONFIG_CLIPPING */ - -/** - * Draw a sloped line segment. - * - * Draw a sloped line segment identified by the provided - * start and end coordinates on the bitmap \a bm. - * - * The line endpoints are clipped inside the current bitmap - * clipping rectangle using the Cohen-Sutherland algorithm, - * which is very fast. - * - * \note The point at coordinates \a x2 \a y2 is not drawn. - * - * \note This function does \b not update the current pen position. - * - * \todo Compute updated Bresenham error term. - */ -void gfx_line(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ -#if CONFIG_GFX_CLIPPING - int clip1 = gfx_findRegion(x1, y1, &bm->cr); - int clip2 = gfx_findRegion(x2, y2, &bm->cr); - - /* Loop while there is at least one point outside */ - while (clip1 | clip2) - { - /* Check for line totally outside */ - if (clip1 & clip2) - return; - - int c = clip1 ? clip1 : clip2; - int x, y; - - if (c & 1) /* Below */ - { - x = x1 + (x2 - x1) * (bm->cr.ymax - y1) / (y2 - y1); - y = bm->cr.ymax - 1; - } - else if (c & 2) /* Above */ - { - x = x1 + (x2 - x1) * (bm->cr.ymin - y1) / (y2 - y1); - y = bm->cr.ymin; - } - else if (c & 4) /* Right */ - { - y = y1 + (y2 - y1) * (bm->cr.xmax - x1) / (x2 - x1); - x = bm->cr.xmax - 1; - } - else /* Left */ - { - y = y1 + (y2 - y1) * (bm->cr.xmin - x1) / (x2 - x1); - x = bm->cr.xmin; - } - - if (c == clip1) /* First endpoint was clipped */ - { - // TODO: adjust Bresenham error term - //coord_t clipdx = ABS(x - x1); - //coord_t clipdy = ABS(y - y1); - //e += (clipdy * e2) + ((clipdx - clipdy) * e1); - - x1 = x; - y1 = y; - clip1 = gfx_findRegion(x1, y1, &bm->cr); - } - else /* Second endpoint was clipped */ - { - x2 = x; - y2 = y; - clip2 = gfx_findRegion(x2, y2, &bm->cr); - } - } -#endif /* CONFIG_GFX_CLIPPING */ - - gfx_lineUnclipped(bm, x1, y1, x2, y2); -} - -/** - * Move the current pen position to the specified coordinates. - * - * The pen position is used for drawing operations such as - * gfx_lineTo(), which can be used to draw polygons. - */ -void gfx_moveTo(Bitmap *bm, coord_t x, coord_t y) -{ - bm->penX = x; - bm->penY = y; -} - -/** - * Draw a line from the current pen position to the new coordinates. - * - * \note This function moves the current pen position to the - * new coordinates. - * - * \sa gfx_line() - */ -void gfx_lineTo(Bitmap *bm, coord_t x, coord_t y) -{ - gfx_line(bm, bm->penX, bm->penY, x, y); - gfx_moveTo(bm, x, y); -} - - -/** - * Draw the perimeter of an hollow rectangle. - * - * \note The bottom-right corner of the rectangle is drawn at (x2-1;y2-1). - * \note This function does \b not update the current pen position. - */ -void gfx_rectDraw(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ - /* Sort coords (needed for correct bottom-right semantics) */ - if (x1 > x2) SWAP(x1, x2); - if (y1 > y2) SWAP(y1, y2); - - /* Draw rectangle */ - gfx_line(bm, x1, y1, x2-1, y1); - gfx_line(bm, x2-1, y1, x2-1, y2-1); - gfx_line(bm, x2-1, y2-1, x1, y2-1); - gfx_line(bm, x1, y2-1, x1, y1); -} - - -/** - * Fill a rectangular area with \a color. - * - * \note The bottom-right border of the rectangle is not drawn. - * - * \note This function does \b not update the current pen position. - */ -void gfx_rectFillC(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t color) -{ - coord_t x, y; - - /* Sort coords */ - if (x1 > x2) SWAP(x1, x2); - if (y1 > y2) SWAP(y1, y2); - -#if CONFIG_GFX_CLIPPING - /* Clip rect to bitmap clip region */ - if (x1 < bm->cr.xmin) x1 = bm->cr.xmin; - if (x2 < bm->cr.xmin) x2 = bm->cr.xmin; - if (x1 > bm->cr.xmax) x1 = bm->cr.xmax; - if (x2 > bm->cr.xmax) x2 = bm->cr.xmax; - if (y1 < bm->cr.ymin) y1 = bm->cr.ymin; - if (y2 < bm->cr.ymin) y2 = bm->cr.ymin; - if (y1 > bm->cr.ymax) y1 = bm->cr.ymax; - if (y2 > bm->cr.ymax) y2 = bm->cr.ymax; -#endif /* CONFIG_GFX_CLIPPING */ - - /* NOTE: Code paths are duplicated for efficiency */ - if (color) /* fill */ - { - for (x = x1; x < x2; x++) - for (y = y1; y < y2; y++) - BM_PLOT(bm, x, y); - } - else /* clear */ - { - for (x = x1; x < x2; x++) - for (y = y1; y < y2; y++) - BM_CLEAR(bm, x, y); - } -} - - -/** - * Draw a filled rectangle. - * - * \note The bottom-right border of the rectangle is not drawn. - * - * \note This function does \b not update the current pen position. - */ -void gfx_rectFill(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ - gfx_rectFillC(bm, x1, y1, x2, y2, 0xFF); -} - - -/** - * Clear a rectangular area. - * - * \note The bottom-right border of the rectangle is not cleared. - * - * \note This function does \b not update the current pen position. - */ -void gfx_rectClear(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ - gfx_rectFillC(bm, x1, y1, x2, y2, 0x00); -} - - -#if CONFIG_GFX_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 - 1) / (vcoord_t)(x2 - x1); - bm->scaleY = (vcoord_t)(bm->cr.ymax - bm->cr.ymin - 1) / (vcoord_t)(y2 - y1); - -/* 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_vline(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2) -{ - gfx_line(bm, - gfx_transformX(bm, x1), gfx_transformY(bm, y1), - gfx_transformY(bm, x2), gfx_transformY(bm, y2)); -} -#endif /* CONFIG_GFX_VCOORDS */ diff --git a/gfx/text.c b/gfx/text.c deleted file mode 100644 index c37e871e..00000000 --- a/gfx/text.c +++ /dev/null @@ -1,418 +0,0 @@ -/** - * \file - * - * - * \brief Text graphic routines - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.13 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.12 2006/05/25 23:35:22 bernie - *#* Implement correct and faster clipping for algo text. - *#* - *#* Revision 1.11 2006/05/15 07:21:06 bernie - *#* Doxygen fix. - *#* - *#* Revision 1.10 2006/04/27 05:39:23 bernie - *#* Enhance text rendering to arbitrary x,y coords. - *#* - *#* Revision 1.9 2006/04/11 00:08:24 bernie - *#* text_offset(): New function, but I'm not quite confident with the design. - *#* - *#* Revision 1.8 2006/03/22 09:50:37 bernie - *#* Use the same format for fonts and rasters. - *#* - *#* Revision 1.7 2006/03/20 17:51:55 bernie - *#* Cleanups. - *#* - *#* Revision 1.6 2006/03/13 02:05:54 bernie - *#* Mark slow paths as UNLIKELY. - *#* - *#* Revision 1.5 2006/03/07 22:18:04 bernie - *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute. - *#* - *#* Revision 1.4 2006/02/15 09:10:15 bernie - *#* Implement prop fonts; Fix algo styles. - *#* - *#* Revision 1.3 2006/02/10 12:31:55 bernie - *#* Add multiple font support in bitmaps. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.13 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.12 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.11 2005/01/20 18:46:31 aleph - *#* Fix progmem includes. - *#* - *#* Revision 1.10 2005/01/08 09:20:12 bernie - *#* Really make it work on both architectures. - *#* - *#* Revision 1.9 2004/12/31 16:44:29 bernie - *#* Sanitize for non-Harvard processors. - *#* - *#* Revision 1.8 2004/11/16 21:16:28 bernie - *#* Update to new naming scheme in mware/gfx.c. - *#* - *#* Revision 1.7 2004/09/20 03:28:28 bernie - *#* Fix header. - *#* - *#* Revision 1.6 2004/09/14 20:57:15 bernie - *#* Use debug.h instead of kdebug.h. - *#* - *#* Revision 1.5 2004/09/06 21:51:26 bernie - *#* Extend interface to allow any algorithmic style. - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* 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 -#include -#include -#include - -#include // FIXME: BM_DRAWPIXEL - -#include - - -/** - * ANSI escape sequences flag: true for ESC state on. - * - * \todo Move to Bitmap.flags. - */ -static bool ansi_mode = false; - -/** - * Move (imaginary) cursor to coordinates specified. - */ -void text_setCoord(struct Bitmap *bm, int x, int y) -{ - bm->penX = x; - bm->penY = y; -} - - -/** - * 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 / bm->font->width); - ASSERT(row >= 0); - ASSERT(row < bm->height / bm->font->height); - - text_setCoord(bm, col * bm->font->width, row * bm->font->height); -} - - -/** - * Render char \a c on Bitmap \a bm. - */ -static int text_putglyph(char c, struct Bitmap *bm) -{ - const uint8_t * PROGMEM glyph; /* font is in progmem */ - uint8_t glyph_width, glyph_height, glyph_height_bytes; - unsigned char index = (unsigned char)c; - - /* Check for out of range char and replace with '?' or first char in font. */ - if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index))) - { - kprintf("Illegal char '%c' (0x%02x)\n", index, index); - if (FONT_HAS_GLYPH(bm->font, '?')) - index = '?'; - else - index = bm->font->first; - } - - /* Make character relative to font start */ - index -= bm->font->first; - - glyph_height = bm->font->height; - // FIXME: for vertical fonts only - glyph_height_bytes = (glyph_height + 7) / 8; - - if (bm->font->offset) - { - /* Proportional font */ - glyph_width = bm->font->widths[index]; /* TODO: optimize away */ - glyph = bm->font->glyph + bm->font->offset[index]; - } - else - { - /* - * Fixed-width font: compute the first column of pixels - * of the selected glyph using the character code to index - * the glyph array. - */ - glyph_width = bm->font->width; - - //For horizontal fonts - //glyph = bm->font->glyph + index * (((glyph_width + 7) / 8) * glyph_height); - glyph = bm->font->glyph + index * glyph_height_bytes * glyph_width; - } - - /* Slow path for styled glyphs */ - if (UNLIKELY(bm->styles)) - { - uint8_t styles = bm->styles; - uint8_t prev_dots = 0, italic_prev_dots = 0; - uint8_t dots; - uint8_t row, col, row_bit; - - /* - * To avoid repeating clipping and other expensive computations, - * we cluster calls to gfx_blitRaster() using a small buffer. - */ - #define CONFIG_TEXT_RENDER_OPTIMIZE 1 - #if CONFIG_TEXT_RENDER_OPTIMIZE - #define RENDER_BUF_WIDTH 12 - #define RENDER_BUF_HEIGHT 8 - uint8_t render_buf[RAST_SIZE(RENDER_BUF_WIDTH, RENDER_BUF_HEIGHT)]; - uint8_t render_xpos = 0; - #endif - - /* This style alone could be handled by the fast path too */ - if (bm->styles & STYLEF_CONDENSED) - --glyph_width; - - if (bm->styles & STYLEF_EXPANDED) - glyph_width *= 2; - - for (row = 0, row_bit = 0; row < glyph_height_bytes; ++row, row_bit += 8) - { - /* For each dot column in the glyph... */ - for (col = 0; col < glyph_width; ++col) - { - uint8_t src_col = col; - - /* Expanded style: advances only once every two columns. */ - if (styles & STYLEF_EXPANDED) - src_col /= 2; - - /* Fetch a column of dots from glyph. */ - dots = PGM_READ_CHAR(RAST_ADDR(glyph, src_col, row_bit, glyph_width)); - - /* Italic: get lower 4 dots from previous column */ - if (styles & STYLEF_ITALIC) - { - uint8_t new_dots = dots; - dots = (dots & 0xF0) | italic_prev_dots; - italic_prev_dots = new_dots & 0x0F; - } - - /* Bold: "or" pixels with the previous column */ - if (styles & STYLEF_BOLD) - { - uint8_t new_dots = dots; - dots |= prev_dots; - prev_dots = new_dots; - } - - /* Underlined: turn on base pixel */ - if ((styles & STYLEF_UNDERLINE) - && (row == glyph_height_bytes - 1)) - dots |= (1 << (glyph_height - row_bit - 1)); - - /* Inverted: invert pixels */ - if (styles & STYLEF_INVERT) - dots = ~dots; - - /* Output dots */ - #if CONFIG_TEXT_RENDER_OPTIMIZE - render_buf[render_xpos++] = dots; - if (render_xpos == RENDER_BUF_WIDTH) - { - gfx_blitRaster(bm, bm->penX + col - render_xpos + 1, bm->penY + row_bit, - render_buf, render_xpos, - MIN((uint8_t)RENDER_BUF_HEIGHT, (uint8_t)(glyph_height - row_bit)), - RENDER_BUF_WIDTH); - render_xpos = 0; - } - #else - gfx_blitRaster(bm, bm->penX + col, bm->penY + row_bit, - &dots, 1, MIN((uint8_t)8, glyph_height - row_bit), 1); - #endif - } - - #if CONFIG_TEXT_RENDER_OPTIMIZE - /* Flush out rest of render buffer */ - if (render_xpos != 0) - { - gfx_blitRaster(bm, bm->penX + col - render_xpos, bm->penY + row_bit, - render_buf, render_xpos, - MIN((uint8_t)RENDER_BUF_HEIGHT, (uint8_t)(glyph_height - row_bit)), - RENDER_BUF_WIDTH); - render_xpos = 0; - } - #endif - } - } - else - { - /* No style: fast vanilla copy of glyph to bitmap */ - gfx_blitRaster(bm, bm->penX, bm->penY, glyph, glyph_width, glyph_height, glyph_width); - } - - /* Update current pen position */ - bm->penX += glyph_width; - - 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 (UNLIKELY(ansi_mode)) - { - switch (c) - { - case ANSI_ESC_CLEARSCREEN: - gfx_bitmapClear(bm); - bm->penX = 0; - bm->penY = 0; - text_style(bm, 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 + bm->font->height < bm->height) - { - bm->penY += bm->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); -} - - -void text_clearLine(struct Bitmap *bm, int line) -{ - gfx_rectClear(bm, 0, line * bm->font->height, bm->width, (line + 1) * bm->font->height); -} - - -/** - * Set/clear algorithmic font style bits. - * - * \param bm Pointer to Bitmap to affect. - * \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 text_style(bm, STYLEF_BOLD, STYLEF_BOLD); \endcode - * - * Turn off bold and turn on italic, leave others as they are - * \code text_style(bm, STYLEF_ITALIC, STYLEF_BOLD | STYLEF_ITALIC); \endcode - * - * Query current style without chaning it - * \code style = text_style(bm, 0, 0); \endcode - * - * Reset all styles (plain text) - * \code text_style(bm, 0, STYLE_MASK); \endcode - */ -uint8_t text_style(struct Bitmap *bm, uint8_t flags, uint8_t mask) -{ - uint8_t old = bm->styles; - bm->styles = (bm->styles & ~mask) | flags; - return old; -} diff --git a/gfx/text.h b/gfx/text.h deleted file mode 100644 index 59f65ea0..00000000 --- a/gfx/text.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * \file - * - * - * \brief Text graphic routines (interface) - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \version $Id$ - */ - -#ifndef GFX_TEXT_H -#define GFX_TEXT_H - -#include -#include /* BV() */ -#include /* CPU_HARVARD */ -#include /* coord_t */ - -#include - -/** - * \name Style flags - * \see text_style() - * \{ - */ -#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) /* -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, uint16_t mode, const char * PROGMEM fmt, ...) FORMAT(__printf__, 5, 6); -int text_vwidthf_P(struct Bitmap *bm, const char * PROGMEM fmt, va_list ap); -int text_widthf_P(struct Bitmap *bm, const char * PROGMEM fmt, ...); -#endif /* CPU_HARVARD */ - -#endif /* GFX_TEXT_H */ diff --git a/gfx/text_format.c b/gfx/text_format.c deleted file mode 100644 index 7c204725..00000000 --- a/gfx/text_format.c +++ /dev/null @@ -1,360 +0,0 @@ -/** - * \file - * - * - * \brief printf-family routines for text output - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.10 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.9 2006/04/27 05:39:24 bernie - *#* Enhance text rendering to arbitrary x,y coords. - *#* - *#* Revision 1.8 2006/03/22 09:50:11 bernie - *#* Don't use C99 stuff. - *#* - *#* Revision 1.7 2006/03/20 17:51:55 bernie - *#* Cleanups. - *#* - *#* Revision 1.6 2006/03/13 02:05:54 bernie - *#* Mark slow paths as UNLIKELY. - *#* - *#* Revision 1.5 2006/03/07 22:18:04 bernie - *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute. - *#* - *#* Revision 1.4 2006/02/10 12:31:33 bernie - *#* Add multiple font support in bitmaps. - *#* - *#* Revision 1.3 2005/11/27 23:31:58 bernie - *#* Reorder includes. - *#* - *#* Revision 1.2 2005/11/04 18:17:45 bernie - *#* Fix header guards and includes for new location of gfx module. - *#* - *#* Revision 1.1 2005/11/04 18:11:35 bernie - *#* Move graphics stuff from mware/ to gfx/. - *#* - *#* Revision 1.10 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.9 2004/12/31 17:47:45 bernie - *#* Rename UNUSED() to UNUSED_ARG(). - *#* - *#* Revision 1.8 2004/11/16 21:16:56 bernie - *#* Update to new naming scheme in mware/gfx.c. - *#* - *#* Revision 1.7 2004/10/03 19:05:04 bernie - *#* text_widthf(), text_vwidthf(): New functions. - *#* - *#* Revision 1.6 2004/09/14 20:59:04 bernie - *#* text_xprintf(): Support all styles; Pixel-wise text centering. - *#* - *#* Revision 1.5 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.4 2004/08/05 18:46:44 bernie - *#* Documentation improvements. - *#* - *#* Revision 1.3 2004/08/03 15:57:18 aleph - *#* Add include to fix warning for vsprintf() - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* 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 /* _formatted_write() */ -#include -#include - -#include /* vsprintf() */ -#include -#include /* strlen() */ - -/** - * Render string \a str in Bitmap \a bm at current cursor position - * - * \note Text formatting functions are also available with an _P suffix - * accepting the source string from program memory. This feature - * is only available (and useful) on Harvard microprocessors such - * as the AVR. - * - * \see text_putchar() - */ -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; -} - - -/** - * vprintf()-like formatter to render text in a Bitmap. - * - * Perform vprintf()-like formatting on the \a fmt format string using the - * variable-argument list \a ap. - * Render the resulting string in Bitmap \a bm starting at the current - * cursor position. - * - * \see text_puts() text_putchar() text_printf() - */ -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); -} - -/** - * printf()-like formatter to render text in a Bitmap. - * - * Perform printf()-like formatting on the \a fmt format string. - * Render the resulting string in Bitmap \a bm starting at the - * current cursor position. - * - * \see text_puts() text_putchar() text_vprintf() - */ -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; -} - -/** - * Render text with vprintf()-like formatting at a specified pixel position. - * - * \see text_xyprintf() - */ -int PGM_FUNC(text_xyvprintf)(struct Bitmap *bm, - coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, va_list ap) -{ - int len; - uint8_t oldstyle = 0; - - text_setCoord(bm, x, y); - - if (style & STYLEF_MASK) - oldstyle = text_style(bm, style, STYLEF_MASK); - - if (style & (TEXT_CENTER | TEXT_RIGHT)) - { - uint8_t pad = bm->width - PGM_FUNC(text_vwidthf)(bm, fmt, ap); - - if (style & TEXT_CENTER) - pad /= 2; - - if (style & TEXT_FILL) - gfx_rectFillC(bm, 0, y, pad, y + bm->font->height, - (style & STYLEF_INVERT) ? 0xFF : 0x00); - - text_setCoord(bm, pad, y); - } - - len = PGM_FUNC(text_vprintf)(bm, fmt, ap); - - if (style & TEXT_FILL) - gfx_rectFillC(bm, bm->penX, y, bm->width, y + bm->font->height, - (style & STYLEF_INVERT) ? 0xFF : 0x00); - - /* Restore old style */ - if (style & STYLEF_MASK) - text_style(bm, oldstyle, STYLEF_MASK); - - return len; -} - - -/** - * Render text with printf()-like formatting at a specified pixel position. - * - * \param bm Bitmap where to render the text - * \param x [pixels] Initial X coordinate of text. - * \param y [pixels] Coordinate of top border of text. - * \param style Formatting style to use. In addition to any STYLEF_ - * flag, it can be TEXT_NORMAL, TEXT_FILL, TEXT_INVERT or - * TEXT_RIGHT, or a combination of these flags ORed together. - * \param fmt String possibly containing printf() formatting commands. - * - * \see text_puts() text_putchar() text_printf() text_vprintf() - * \see text_moveTo() text_style() - */ -int PGM_FUNC(text_xyprintf)(struct Bitmap *bm, - coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, ...) -{ - int len; - va_list ap; - - va_start(ap, fmt); - len = PGM_FUNC(text_xyvprintf)(bm, x, y, style, fmt, ap); - va_end(ap); - - return len; -} - - -/** - * Render text with printf()-like formatting at a specified row/column position. - * - * \see text_xyprintf() - */ -int PGM_FUNC(text_xprintf)(struct Bitmap *bm, - uint8_t row, uint8_t col, uint16_t style, const char * PGM_ATTR fmt, ...) -{ - int len; - va_list ap; - - va_start(ap, fmt); - len = PGM_FUNC(text_xyvprintf)( - bm, col * bm->font->width, row * bm->font->height, - style, fmt, ap); - va_end(ap); - - return len; -} - - -struct TextWidthData -{ - Bitmap *bitmap; - coord_t width; -}; - -/** - * Compute width in pixels of a character. - * - * Compute the on screen width of a character, taking the - * current style and font into account. - * - * The width is accumulated in the WidthData structure - * passed as second argument. - * - * This is a formatted_write() callback used by text_vwidthf() - * to compute the length of a formatted string. - */ -static int text_charWidth(int c, struct TextWidthData *twd) -{ - unsigned char index = (unsigned char)c; - Bitmap *bm = twd->bitmap; - coord_t glyph_width; - - - if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index))) - { - if (!FONT_HAS_GLYPH(bm->font, '?')) - index = '?'; - else - index = bm->font->first; - } - - /* Make character relative to font start */ - index -= bm->font->first; - - if (bm->font->offset) - /* Proportional font */ - glyph_width = bm->font->widths[index]; /* TODO: optimize away */ - else - /* Fixed width font */ - glyph_width = bm->font->width; - - if (bm->styles & STYLEF_CONDENSED) - --glyph_width; - - if (bm->styles & STYLEF_EXPANDED) - glyph_width *= 2; - - twd->width += glyph_width; - - return c; -} - -/** - * Return the width in pixels of a vprintf()-formatted string. - */ -int PGM_FUNC(text_vwidthf)( - UNUSED_ARG(struct Bitmap *, bm), - const char * PGM_ATTR fmt, - va_list ap) -{ - /* Fixed font with no styles affecting the width? */ - if (!bm->font->offset && !(bm->styles & (STYLEF_CONDENSED | STYLEF_EXPANDED))) - return PGM_FUNC(vsprintf)(NULL, fmt, ap) * bm->font->width; - else - { - struct TextWidthData twd; - twd.bitmap = bm; - twd.width = 0; - _formatted_write(fmt, (void (*)(char, void *))text_charWidth, &twd, ap); - return twd.width; - } -} - - -/** - * Return the width in pixels of a printf()-formatted string. - */ -int PGM_FUNC(text_widthf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...) -{ - int width; - - va_list ap; - va_start(ap, fmt); - width = PGM_FUNC(text_vwidthf)(bm, fmt, ap); - va_end(ap); - - return width; -} diff --git a/gfx/win.c b/gfx/win.c deleted file mode 100644 index 4925ace6..00000000 --- a/gfx/win.c +++ /dev/null @@ -1,232 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Very simple hierarchical windowing system. - * - * All functions in this module are to be intended as methods - * of the Window class. Please see its documentation - * for a module-wise introduction. - * - * \see struct Window - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/08/01 17:26:04 batt - *#* Update docs. - *#* - *#* Revision 1.1 2006/08/01 15:43:01 batt - *#* Add in board_kd current edited channel visualization. - *#* - *#* Revision 1.4 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2006/02/10 12:25:41 bernie - *#* Add missing header. - *#* - *#* Revision 1.2 2006/01/26 00:36:48 bernie - *#* Const correctness for some new functions. - *#* - *#* Revision 1.1 2006/01/23 23:14:29 bernie - *#* Implement simple, but impressive windowing system. - *#* - *#*/ - -#include "win.h" -#include - -/** - * Map the contents of all child-windows into the bitmap of \a w. - * - * \note Recursively drawing children into their parent - * effectively damages the parent buffer. - */ -void win_compose(Window *w) -{ - Window *child; - - /* - * Walk over all children, in back to front order and tell them - * to compose into us. - */ - REVERSE_FOREACH_NODE(child, &w->children) - { - /* Recursively compose child first. */ - win_compose(child); - - /* Draw child into our bitmap. */ - if (w->bitmap) - gfx_blit(w->bitmap, &child->geom, child->bitmap, 0, 0); - } -} - -/** - * Map window \a w into \a parent. - * - * The new window becomes the topmost window. - * - * \note Opening a window twice is illegal. - * - * \see win_close() - */ -void win_open(Window *w, Window *parent) -{ - ASSERT(!w->parent); - w->parent = parent; - ADDHEAD(&parent->children, &w->link); -} - -/** - * Detach window from its parent. - * - * Closing a window causes it to become orphan of its - * parent. Its content will no longer appear in its - * parent after the next refresh cycle. - * - * \note Closing a window that has not been previously - * opened is illegal. - * - * \see win_open() - */ -void win_close(Window *w) -{ - ASSERT(w->parent); - REMOVE(&w->link); - w->parent = NULL; -} - -/** - * Move window to the topmost position relative to its sibling. - * - * \see win_move(), win_resize(), win_setGeometry() - */ -void win_raise(Window *w) -{ - ASSERT(w->parent); - REMOVE(&w->link); - ADDHEAD(&w->parent->children, &w->link); -} - -/** - * Set window position and size at the same time. - * - * This function is equivalent to subsequent calls to win_move() - * and win_resize() using the coordinates provided by the - * \a new_geom rectangle. - * - * \note The xmax and ymax members of \a new_geom are non-inclusive, - * as usual for the Rect interface. - * - * \see win_move() - * \see win_resize() - */ -void win_setGeometry(Window *w, const Rect *new_geom) -{ - // requires C99? - // memcpy(&w->geom, new_geom, sizeof(w->geom)); - w->geom = *new_geom; -} - -/** - * Move window to specified position. - * - * Move the window top-left corner to the pixel coordinates - * \a left and \a top, which are relative to the parent window. - * - * \note A window can also be moved outside the borders - * of its parent, or at negative coordinates. - * - * \note It is allowed to move an orphan window. - */ -void win_move(Window *w, coord_t left, coord_t top) -{ - Rect r; - - r.xmin = left; - r.ymin = top; - r.xmax = r.xmin + RECT_WIDTH(&w->geom); - r.ymax = r.ymin + RECT_WIDTH(&w->geom); - - win_setGeometry(w, &r); -} - -/** - * Resize the rectangle of a window. - * - * The window shrinks or grows to the specified size. - * - * \note Growing a window beyond the size of its - * backing bitmap results in unspecified behavior. - * - * \note It is allowed to resize an orphan window. - */ -void win_resize(Window *w, coord_t width, coord_t height) -{ - Rect r; - - r.xmin = w->geom.xmin; - r.ymin = w->geom.ymin; - r.xmax = r.xmin + width; - r.ymax = r.ymin + height; - - win_setGeometry(w, &r); -} - -/** - * Initialize a new window structure. - * - * The new window initial position is set to (0,0). - * The size is set to the size of the installed bitmap, - * or (0,0) if there's no backing store. - * - * \arg bm The bitmap to install as backing store - * for drawing into the window, or NULL if - * the window is not drawable. - */ -void win_create(Window *w, Bitmap *bm) -{ - w->parent = NULL; - w->bitmap = bm; - w->geom.xmin = 0; - w->geom.ymin = 0; - if (bm) - { - w->geom.xmax = bm->width; - w->geom.ymax = bm->height; - } - LIST_INIT(&w->children); -} - diff --git a/gfx/win.h b/gfx/win.h deleted file mode 100644 index 3dafc910..00000000 --- a/gfx/win.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Very simple hierarchical windowing system. - * - * All functions in this module are to be intended as methods - * of the Window class. Please see its documentation - * for a module-wise introduction. - * - * \see struct Window - */ - -/*#* - *#* $Log$ - *#* Revision 1.3 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.2 2006/01/26 00:36:48 bernie - *#* Const correctness for some new functions. - *#* - *#* Revision 1.1 2006/01/23 23:14:29 bernie - *#* Implement simple, but impressive windowing system. - *#* - *#*/ - -#ifndef GFX_WIN_H -#define GFX_WIN_H - -#include /* Node, List */ -#include /* coord_t */ - - -EXTERN_C_BEGIN - -/** - * Window handle and context structure. - * - * A window is a small rectangular area on the - * screen backed by its own bitmap where you - * can draw. - * - * A window can contain any number of children - * sub-windows that can be depth arranged with - * respect to their siblings. - * - * At any time, a window and all its children - * can be drawn into another bitmap to display - * a complete screen, taking depth and - * overlapping into account. - * - * This rendering model is commonly referred to as - * screen composition, and is quite popular among - * modern windowing systems. - */ -typedef struct Window -{ - Node link; /**< Link us with other siblings into our parent. */ - struct Window *parent; /**< Our parent window. NULL for the root window. */ - - Bitmap *bitmap; /**< Pixel storage for window contents. */ - Rect geom; /**< [px] Window size and position relative to parent. */ - - /** - * List of child windows, arranged by depth (front to back). - * - * Child top/left coordinates are relative to us. - */ - List children; - -} Window; - -/* - * Public function prototypes - */ -void win_compose(Window *w); -void win_open(Window *w, Window *parent); -void win_close(Window *w); -void win_raise(Window *w); -void win_setGeometry(Window *w, const Rect *new_geom); -void win_move(Window *w, coord_t left, coord_t top); -void win_resize(Window *w, coord_t width, coord_t height); -void win_create(Window *w, Bitmap *bm); - -EXTERN_C_END - -#endif /* GFX_WIN_H */ - diff --git a/gui/levelbar.c b/gui/levelbar.c deleted file mode 100644 index 8b75d15b..00000000 --- a/gui/levelbar.c +++ /dev/null @@ -1,106 +0,0 @@ -/** - * \file - * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) - * - * - * \brief Graphics user interface element to display a level bar. - * - * \version $Id$ - * \author Stefano Fedrigo - */ - -#include "levelbar.h" - - -/** - * Initialize the LevelBar widget with the bitmap associated, - * the value range and the coordinates in the bitmap. - * \note The levelbar should be at least 5 pixels wide and high - * for correct borders drawing. No check is done on this. - */ -void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos, - coord_t x1, coord_t y1, coord_t x2, coord_t y2) -{ - lb->bitmap = bmp; - lb->type = type; - lb->min = min; - lb->max = max; - lb->pos = pos; - lb->x1 = x1; - lb->y1 = y1; - lb->x2 = x2; - lb->y2 = y2; -} - - -/** - * Set the level. - */ -void lbar_setLevel(struct LevelBar *lb, int level) -{ - if (level < lb->min) - level = lb->min; - if (level > lb->max) - level = lb->max; - - lb->pos = level; -} - - -/** - * Get current level. - */ -int lbar_getLevel(struct LevelBar *lb) -{ - return lb->pos; -} - - -/** - * Change level with respect to previous value - * (delta can be negative). - */ -void lbar_changeLevel(struct LevelBar *lb, int delta) -{ - lbar_setLevel(lb, lb->pos + delta); -} - - -/** - * Change the top limit. - */ -void lbar_setMax(struct LevelBar *lb, int max) -{ - lb->max = max; -} - - -/** - * Render the LevelBar on the bitmap. - */ -void lbar_draw(struct LevelBar *lb) -{ -#define BORDERW 1 -#define BORDERH 1 - - /* Compute filled bar length in pixels */ - int totlen = (lb->type & LBAR_HORIZONTAL) ? lb->x2 - lb->x1 - BORDERW*4 : lb->y2 - lb->y1 - BORDERH*4; - int range = lb->max - lb->min; - int barlen = ((long)(lb->pos - lb->min) * (long)totlen + range - 1) / range; - - // Draw border - gfx_rectDraw(lb->bitmap, lb->x1, lb->y1, lb->x2, lb->y2); - - // Clear inside - gfx_rectClear(lb->bitmap, lb->x1 + BORDERW, lb->y1 + BORDERH, lb->x2 - BORDERW, lb->y2 - BORDERH); - - // Draw bar - if (lb->type & LBAR_HORIZONTAL) - gfx_rectFill(lb->bitmap, - lb->x1 + BORDERW*2, lb->y1 + BORDERH*2, - lb->x1 + BORDERW*2 + barlen, lb->y2 - BORDERH*2); - else - gfx_rectFill(lb->bitmap, - lb->x1 + BORDERW*2, lb->y2 - BORDERH*2 - barlen, - lb->x2 - BORDERW*2, lb->y2 - BORDERH*2); -} diff --git a/gui/levelbar.h b/gui/levelbar.h deleted file mode 100644 index 97b1a9a9..00000000 --- a/gui/levelbar.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * \file - * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) - * - * - * \version $Id$ - * - * \author Stefano Fedrigo - * - * \brief Graphics level bar widget - */ - -#ifndef GUI_LEVELBAR_H -#define GUI_LEVELBAR_H - -#include - - -/** Type of levelbar */ -#define LBAR_HORIZONTAL 1 -#define LBAR_VERTICAL 2 - -typedef struct LevelBar -{ - struct Bitmap *bitmap; - int type; - int pos; ///< Current level - int min; ///< Minimum level - int max; ///< Maximum level - coord_t x1, y1, x2, y2; ///< Position of widget in the bitmap -} LevelBar; - -void lbar_init(struct LevelBar *lb, struct Bitmap *bmp, int type, int min, int max, int pos, - coord_t x1, coord_t y1, coord_t x2, coord_t y2); -void lbar_setLevel(struct LevelBar *lb, int level); -int lbar_getLevel(struct LevelBar *lb); -void lbar_changeLevel(struct LevelBar *lb, int delta); -void lbar_setMax(struct LevelBar *lb, int max); -void lbar_draw(struct LevelBar *lb); - -#endif /* GUI_LEVELBAR_H */ diff --git a/gui/leveledit.c b/gui/leveledit.c deleted file mode 100644 index 902d7154..00000000 --- a/gui/leveledit.c +++ /dev/null @@ -1,330 +0,0 @@ -/** - * \file - * - * - * \brief Generic editor for (volume/gain/contrast/...) setting. - * - * \version $Id$ - * \author Stefano Fedrigo - */ - -#include "leveledit.h" - -#include /* MAX() */ -#include -#include -#include -#include -#include -#include -#include - -#if CONFIG_MENU_MENUBAR -#include -#endif - -// BEGIN project_grl LOCAL -#include -#include -// END project_grl LOCAL - -#define LBAR_HEIGHT 16 - -/** - * Allow user to change level. - */ -void level_edit(struct LevelEdit *lev) -{ -#if CONFIG_MENU_MENUBAR - /* Labels for menubars */ - enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 }; - const_iptr_t labels[] = - { - (const_iptr_t)LABEL_BACK, - (const_iptr_t)LABEL_MINUS, - (const_iptr_t)LABEL_PLUS, - (const_iptr_t)LABEL_EMPTY - }; - struct MenuBar mb; -#endif /* CONFIG_MENU_MENUBAR */ - - struct LevelBar bar1, bar2; - keymask_t keys, old_rpt_mask; - int step, rep_step; - - rep_step = MAX(lev->step, ((lev->max - lev->min) / 200)); - step = lev->step; - - // Allow keys repetition. - old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN); - - text_clear(lev->bitmap); - //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE); - text_puts(lev->title, lev->bitmap); - //text_style(0, STYLEF_UNDERLINE); - - if (lev->type & LEVELEDIT_DOUBLE) - { - int chn = 0; /* edit both channels */ - - /* Levelbars init */ - lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL, - lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23); - lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL, - lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23); - - #if CONFIG_MENU_MENUBAR - labels[3] = (const_iptr_t)ch_labels[chn]; - mbar_init(&mb, lev->bitmap, labels, countof(labels)); - mbar_draw(&mb); - #endif /* CONFIG_MENU_MENUBAR */ - - /* Input loop for double level setting */ - for (;;) - { - #if CONFIG_LEVELEDIT_TIMEOUT != 0 - ticks_t idle_timeout = timer_clock(); - #endif - do - { - if (lev->display_hook) - lev->display_hook(lev); - else - { - text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit); - PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val); - PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val); - - lbar_setLevel(&bar1, *lev->ch1_val); - lbar_setLevel(&bar2, *lev->ch2_val); - lbar_draw(&bar1); - lbar_draw(&bar2); - } - - #if CONFIG_LEVELEDIT_TIMEOUT != 0 - if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT)) - { - /* Accept input implicitly */ - keys = K_OK; - break; - } - #endif - } - while (!(keys = kbd_peek())); - - if (keys & K_CANCEL) - break; - - if (keys & K_OK) - { - chn = (chn + 1) % 3; - - #if CONFIG_MENU_MENUBAR - labels[3] = (const_iptr_t)ch_labels[chn]; - mbar_draw(&mb); - #endif /* CONFIG_MENU_MENUBAR */ - } - - /* Increment step to achieve greater accelerations on larger values */ - if (keys & K_REPEAT) - step = MIN(rep_step, step + 1); - else - step = lev->step; - - if (keys & (K_UP | K_DOWN)) - { - if (keys & K_UP) - { - /* If changing both channels (chn == 0), don't change - * level if one of two is at min or max */ - if (chn != 0 || - (*lev->ch1_val + step <= lev->max - && *lev->ch2_val + step <= lev->max)) - { - /* If chn == 0 change both channels */ - if (chn != 2) - { - *lev->ch1_val += step; - if (*lev->ch1_val > lev->max) - *lev->ch1_val = lev->max; - } - if (chn != 1) - { - *lev->ch2_val += step; - if (*lev->ch2_val > lev->max) - *lev->ch2_val = lev->max; - } - } - } - else - { - if (chn != 0 || - (*lev->ch1_val - step >= lev->min - && *lev->ch2_val - step >= lev->min)) - { - if (chn != 2) - { - *lev->ch1_val -= step; - if (*lev->ch1_val < lev->min) - *lev->ch1_val = lev->min; - } - if (chn != 1) - { - *lev->ch2_val -= step; - if (*lev->ch2_val < lev->min) - *lev->ch2_val = lev->min; - } - } - } - - if (lev->set_hook) - lev->set_hook(); - } - } // end for(;;) - } - else - { - const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d"); - -/* - const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit), - PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit)); - - const coord_t barlen = lev->bitmap->width - 6 - textw; -*/ - const coord_t barlen = lev->bitmap->width; - const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height; - lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL, - lev->min, lev->max, *lev->ch1_val, - 0, barvtop, barlen, barvtop + LBAR_HEIGHT); - - #if CONFIG_MENU_MENUBAR - mbar_init(&mb, lev->bitmap, labels, countof(labels)); - mbar_draw(&mb); - #endif /* CONFIG_MENU_MENUBAR */ - - /* Input loop for single level setting */ - for (;;) - { - #if CONFIG_LEVELEDIT_TIMEOUT != 0 - ticks_t idle_timeout = timer_clock(); - #endif - do - { - if (lev->display_hook) - lev->display_hook(lev); - else - { - if (lev->type != LEVELEDIT_NOBAR) - { - lbar_setLevel(&bar1, *lev->ch1_val); - lbar_draw(&bar1); - } - PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height, - TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit); - } - - #if CONFIG_LEVELEDIT_TIMEOUT != 0 - if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT) - { - /* Accept input implicitly */ - keys = K_CANCEL; - break; - } - #endif - -// BEGIN project_grl LOCAL -#if 1 - //FIXME: must to this only when needed - lcd_blitBitmap(&lcd_bitmap); - } - while (!(keys = GuiMan_KbdPeek())); -#else - } - while (!(keys = kbd_peek())); -#endif -// END project_grl LOCAL - - if (keys & K_CANCEL) - break; - - /* Increment step to achieve greater accelerations on larger values */ - if (keys & K_REPEAT) - step = MIN(rep_step, step + 1); - else - step = lev->step; - - if (keys & K_UP) - { - *lev->ch1_val += step; - if (*lev->ch1_val > lev->max) - *lev->ch1_val = lev->max; - } - - if (keys & K_DOWN) - { - *lev->ch1_val -= step; - if (*lev->ch1_val < lev->min) - *lev->ch1_val = lev->min; - } - - if (lev->set_hook) - lev->set_hook(); - } - } - - kbd_setRepeatMask(old_rpt_mask); -} - -/** - * LevelEdit structure initialization. - * Init data structure and init LevelEdit widgets. - */ -void level_init(struct LevelEdit *lev, - int type, - struct Bitmap *bmp, const char *title, const char *unit, - int min, int max, int step, - int *ch1_val, int *ch2_val, - level_set_callback *set_hook, display_callback *display_hook) -{ - lev->type = type; - lev->bitmap = bmp; - lev->title = title; - lev->unit = unit; - lev->min = min; - lev->max = max; - lev->step = step; - - lev->ch1_val = ch1_val; - lev->ch2_val = ch2_val; - lev->set_hook = set_hook; - lev->display_hook = display_hook; -} diff --git a/gui/leveledit.h b/gui/leveledit.h deleted file mode 100644 index b41df146..00000000 --- a/gui/leveledit.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * \file - * - * - * \brief Generic editor for (volume/gain/contrast/...) setting. - * - * \version $Id$ - * - * \author Stefano Fedrigo - */ -#ifndef GUI_LEVELEDIT_H -#define GUI_LEVELEDIT_H - -//#include - -/* Type for level_init */ -#define LEVELEDIT_NOBAR 0 /**< Edit number only, without bar nor units */ -#define LEVELEDIT_SINGLE 1 /**< Single channel editing */ -#define LEVELEDIT_DOUBLE 2 /**< Double channel editing */ - - - -/* Fwd decl */ -struct Bitmap; -struct LevelEdit; - -/** Type for callback used to set meter levels */ -typedef void level_set_callback(void); - -/** Type for callback used to customize display of units */ -typedef void display_callback(struct LevelEdit *); - -/** - * State of a level meter - */ -typedef struct LevelEdit { - int type; /* - * - * --> - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief General pourpose menu handling functions - */ - -/*#* - *#* $Log$ - *#* Revision 1.8 2006/09/13 13:58:32 bernie - *#* Add RenderHook support. - *#* - *#* Revision 1.7 2006/08/01 12:22:46 bernie - *#* Mention DevLib license. - *#* - *#* Revision 1.6 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.5 2006/06/03 13:58:01 bernie - *#* Fix recursive timeout and add exit status information. - *#* - *#* Revision 1.4 2006/06/02 12:26:18 bernie - *#* Draw graphical checkmarks. - *#* - *#* Revision 1.3 2006/05/28 15:03:31 bernie - *#* Avoid unnecessary rendering. - *#* - *#* Revision 1.2 2006/05/25 23:34:38 bernie - *#* Implement menu timeouts. - *#* - *#* Revision 1.1 2006/05/15 07:20:54 bernie - *#* Move menu to gui/. - *#* - *#* Revision 1.7 2006/04/27 05:39:24 bernie - *#* Enhance text rendering to arbitrary x,y coords. - *#* - *#* Revision 1.6 2006/04/11 00:07:32 bernie - *#* Implemenent MF_SAVESEL flag. - *#* - *#* Revision 1.5 2006/03/22 09:49:51 bernie - *#* Simplifications from project_grl. - *#* - *#* Revision 1.4 2006/03/20 17:48:35 bernie - *#* Implement support for ROM menus. - *#* - *#* Revision 1.3 2006/02/20 14:34:32 bernie - *#* Include appconfig.h before using its definitions. - *#* - *#* Revision 1.2 2006/02/15 09:10:51 bernie - *#* Make title bold; Fix height when we have no menubar. - *#*/ - -#include "menu.h" - -#include -#include -#include -#include -#include -#include -#include -#include /* strcpy() */ - -#if CPU_HARVARD -#include /* strncpy_P() */ -#endif - -#if CONFIG_MENU_SMOOTH -#include -#endif - -#if (CONFIG_MENU_TIMEOUT != 0) -#include -#endif - -#if CONFIG_MENU_MENUBAR -#include "menubar.h" -#endif - -#if defined(CONFIG_LOCALE) && (CONFIG_LOCALE == 1) -#include "msg.h" -#else -#define PTRMSG(x) ((const char *)x) -#endif - - -/* Temporary fake defines for ABORT stuff... */ -#define abort_top 0 -#define PUSH_ABORT false -#define POP_ABORT do {} while(0) -#define DO_ABORT do {} while(0) - - -/** - * Return the total number of items in in a menu. - */ -static int menu_count(const struct Menu *menu) -{ - int cnt = 0; - - for (cnt = 0; /*NOP*/; ++cnt) - { - const MenuItem *item = &menu->items[cnt]; -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif - if (!(item->label || item->hook)) - break; - } - - return cnt; -} - -#if CONFIG_MENU_MENUBAR - -/** - * Update the menu bar according to the selected item and redraw it. - */ -static void menu_update_menubar( - const struct Menu *menu, - struct MenuBar *mb, - int selected) -{ - int item_flags; -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[selected].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[selected].flags); - } - else -#endif - item_flags = menu->items[selected].flags; - - const_iptr_t newlabel = (const_iptr_t)LABEL_OK; - - if (item_flags & MIF_DISABLED) - newlabel = (const_iptr_t)LABEL_EMPTY; - else if (item_flags & MIF_TOGGLE) - newlabel = (const_iptr_t)LABEL_SEL; - else if (item_flags & MIF_CHECKIT) - { - newlabel = (item_flags & MIF_CHECKED) ? - (const_iptr_t)LABEL_EMPTY : (const_iptr_t)LABEL_SEL; - } - - mb->labels[3] = newlabel; - mbar_draw(mb); -} -#endif /* CONFIG_MENU_MENUBAR */ - - -static void menu_defaultRenderHook(struct Bitmap *bm, int ypos, bool selected, const struct MenuItem *item) -{ - if (item->flags & MIF_CHECKIT) - { - gfx_rectClear(bm, 0, ypos, - bm->font->height, ypos + bm->font->height); - - if (item->flags & MIF_TOGGLE) - gfx_rectDraw(bm, 2, ypos + 2, - bm->font->height - 2, ypos + bm->font->height - 2); - if (item->flags & MIF_CHECKED) - { - gfx_line(bm, - 3, ypos + 3, - bm->font->height - 3, ypos + bm->font->height - 3); - gfx_line(bm, - bm->font->height - 3, ypos + 3, - 3, ypos + bm->font->height - 3); - } - } - -#if CPU_HARVARD - ((item->flags & MIF_RAMLABEL) ? text_xyprintf : text_xyprintf_P) -#else - text_xyprintf -#endif - ( - bm, (item->flags & MIF_CHECKIT) ? bm->font->height : 0, ypos, - selected ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL, - PTRMSG(item->label) - ); -} - -/** - * Show a menu on the display. - */ -static void menu_layout( - const struct Menu *menu, - int first_item, - int selected, - bool redraw) -{ - coord_t ypos; - int i; - const char * PROGMEM title = PTRMSG(menu->title); - Bitmap *bm = menu->bitmap; - - ypos = bm->cr.ymin; - -#if 0 - if (redraw) - { - /* Clear screen */ - text_clear(menu->bitmap); - } -#endif - - if (title) - { - if (redraw) - text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title); - ypos += bm->font->height; - } - -#if CONFIG_MENU_SMOOTH - static coord_t yoffset = 0; - static int old_first_item = 0; - static int speed; - coord_t old_ymin = bm->cr.ymin; - - /* Clip drawing inside menu items area */ - gfx_setClipRect(bm, - bm->cr.xmin, bm->cr.ymin + ypos, - bm->cr.xmax, bm->cr.ymax); - - if (old_first_item != first_item) - { - /* Speed proportional to distance */ - speed = ABS(old_first_item - first_item) * 3; - - if (old_first_item > first_item) - { - yoffset += speed; - if (yoffset > bm->font->height) - { - yoffset = 0; - --old_first_item; - } - } - else - { - yoffset -= speed; - if (yoffset < -bm->font->height) - { - yoffset = 0; - ++old_first_item; - } - } - first_item = MIN(old_first_item, menu_count(menu)); - - ypos += yoffset; - redraw = true; - } -#endif /* CONFIG_MENU_SMOOTH */ - - if (redraw) for (i = first_item; /**/; ++i) - { - const MenuItem *item = &menu->items[i]; -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif /* CPU_HARVARD */ - - /* Check for end of room */ - if (ypos > bm->cr.ymax) - break; - - /* Check for end of menu */ - if (!(item->label || item->hook)) - break; - - /* Only print visible items */ - if (!(item->flags & MIF_HIDDEN)) - { - /* Check if a special render function is supplied, otherwise use defaults */ - RenderHook renderhook = (item->flags & MIF_RENDERHOOK) ? (RenderHook)item->label : menu_defaultRenderHook; - - /* Render menuitem */ - renderhook(menu->bitmap, ypos++, (i == selected), item); - - ypos += bm->font->height; - } - } - -#if CONFIG_MENU_SMOOTH - if (redraw) - { - /* Clear rest of area */ - gfx_rectClear(bm, bm->cr.xmin, ypos, bm->cr.xmax, bm->cr.ymax); - - lcd_blitBitmap(&lcd_bitmap); - } - - /* Restore old cliprect */ - gfx_setClipRect(bm, - bm->cr.xmin, old_ymin, - bm->cr.xmax, bm->cr.ymax); - -#endif /* CONFIG_MENU_SMOOTH */ -} - - -/** - * Handle menu item selection - */ -static iptr_t menu_doselect(const struct Menu *menu, struct MenuItem *item) -{ - iptr_t result = 0; - - /* Exclude other items */ - int mask, i; - for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i) - { - if (mask & 1) - menu->items[i].flags &= ~MIF_CHECKED; - } - - if (item->flags & MIF_DISABLED) - return MENU_DISABLED; - - /* Handle checkable items */ - if (item->flags & MIF_TOGGLE) - item->flags ^= MIF_CHECKED; - else if (item->flags & MIF_CHECKIT) - item->flags |= MIF_CHECKED; - - /* Handle items with callback hooks */ - if (item->hook) - { - /* Push a jmp buffer to abort the operation with the STOP/CANCEL key */ - if (!PUSH_ABORT) - { - result = item->hook(item->userdata); - POP_ABORT; - } - } - else - result = item->userdata; - - return result; -} - - -/** - * Return the next visible item (rolls back to the first item) - */ -static int menu_next_visible_item(const struct Menu *menu, int index) -{ - int total = menu_count(menu); - int item_flags; - - do - { - if (++index >= total) - index = 0; - -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[index].flags); - } - else -#endif - item_flags = menu->items[index].flags; - } - while (item_flags & MIF_HIDDEN); - - return index; -} - - -/** - * Return the previous visible item (rolls back to the last item) - */ -static int menu_prev_visible_item(const struct Menu *menu, int index) -{ - int total = menu_count(menu); - int item_flags; - - do - { - if (--index < 0) - index = total - 1; - -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[index].flags); - } - else -#endif - item_flags = menu->items[index].flags; - } - while (item_flags & MIF_HIDDEN); - - return index; -} - - -/** - * Handle a menu and invoke hook functions for the selected menu items. - */ -iptr_t menu_handle(const struct Menu *menu) -{ - uint8_t items_per_page; - uint8_t first_item = 0; - uint8_t selected; - iptr_t result = 0; - bool redraw = true; - -#if (CONFIG_MENU_TIMEOUT != 0) - ticks_t now, menu_idle_time = timer_clock(); -#endif - -#if CONFIG_MENU_MENUBAR - struct MenuBar mb; - const_iptr_t labels[] = - { - (const_iptr_t)LABEL_BACK, - (const_iptr_t)LABEL_UPARROW, - (const_iptr_t)LABEL_DOWNARROW, - (const_iptr_t)0 - }; - - /* - * Initialize menu bar - */ - if (menu->flags & MF_TOPLEVEL) - labels[0] = (const_iptr_t)LABEL_EMPTY; - - mbar_init(&mb, menu->bitmap, labels, countof(labels)); -#endif /* CONFIG_MENU_MENUBAR */ - - - items_per_page = - (menu->bitmap->height / menu->bitmap->font->height) -#if CONFIG_MENU_MENUBAR - - 1 /* menu bar labels */ -#endif - - (menu->title ? 1 : 0); - - /* Selected item should be a visible entry */ - //first_item = selected = menu_next_visible_item(menu, menu->selected - 1); - selected = menu->selected; - first_item = 0; - - for(;;) - { - keymask_t key; - - /* - * Keep selected item visible - */ - while (selected < first_item) - first_item = menu_prev_visible_item(menu, first_item); - while (selected >= first_item + items_per_page) - first_item = menu_next_visible_item(menu, first_item); - - menu_layout(menu, first_item, selected, redraw); - redraw = false; - - #if CONFIG_MENU_MENUBAR - menu_update_menubar(menu, &mb, selected); - #endif - - #if CONFIG_MENU_SMOOTH || (CONFIG_MENU_TIMEOUT != 0) - key = kbd_peek(); - #else - key = kbd_get(); - #endif - - #if (CONFIG_MENU_TIMEOUT != 0) - /* Reset idle timer on key press. */ - now = timer_clock(); - if (key) - menu_idle_time = now; - #endif - - if (key & K_OK) - { - struct MenuItem *item = &(menu->items[selected]); -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif - result = menu_doselect(menu, item); - redraw = true; - - /* Return immediately */ - if (!(menu->flags & MF_STICKY)) - break; - - #if (CONFIG_MENU_TIMEOUT != 0) - /* Chain timeout */ - if ((result == MENU_TIMEOUT) && !(menu->flags & MF_TOPLEVEL)) - break; - - /* Reset timeout */ - menu_idle_time = timer_clock(); - #endif - } - else if (key & K_UP) - { - selected = menu_prev_visible_item(menu, selected); - redraw = true; - } - else if (key & K_DOWN) - { - selected = menu_next_visible_item(menu, selected); - redraw = true; - } - else if (!(menu->flags & MF_TOPLEVEL)) - { - if (key & K_CANCEL) - { - result = MENU_CANCEL; - break; - } - - #if CONFIG_MENU_TIMEOUT != 0 - if (now - menu_idle_time > ms_to_ticks(CONFIG_MENU_TIMEOUT)) - { - result = MENU_TIMEOUT; - break; - } - #endif - } - } - - /* Store currently selected item before leaving. */ - if (menu->flags & MF_SAVESEL) - CONST_CAST(struct Menu *, menu)->selected = selected; - - return result; -} - - -/** - * Set flags on a menuitem. - * - * \param menu Menu owner of the item to change. - * \param idx Index of the menu item. - * \param flags Bit mask of the flags to set. - * - * \return Old flags. - */ -int menu_setFlags(struct Menu *menu, int idx, int flags) -{ - ASSERT(idx < menu_count(menu)); - ASSERT(!(menu->flags & MF_ROMITEMS)); - - int old = menu->items[idx].flags; - menu->items[idx].flags |= flags; - return old; -} - - -/** - * Clear flags on a menuitem. - * - * \param menu Menu owner of the item to change. - * \param idx Index of the menu item. - * \param flags Bit mask of the flags to clear. - * - * \return Old flags. - */ -int menu_clearFlags(struct Menu *menu, int idx, int flags) -{ - ASSERT(idx < menu_count(menu)); - ASSERT(!(menu->flags & MF_ROMITEMS)); - - int old = menu->items[idx].flags; - menu->items[idx].flags &= ~flags; - return old; -} diff --git a/gui/menu.h b/gui/menu.h deleted file mode 100644 index 31b33f62..00000000 --- a/gui/menu.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief Common menu handling API - */ - -/*#* - *#* $Log$ - *#* Revision 1.5 2007/09/19 16:23:27 batt - *#* Fix doxygen warnings. - *#* - *#* Revision 1.4 2006/09/13 13:58:33 bernie - *#* Add RenderHook support. - *#* - *#* Revision 1.3 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.2 2006/06/03 13:58:02 bernie - *#* Fix recursive timeout and add exit status information. - *#* - *#* Revision 1.1 2006/05/15 07:20:54 bernie - *#* Move menu to gui/. - *#* - *#* Revision 1.4 2006/04/11 00:07:32 bernie - *#* Implemenent MF_SAVESEL flag. - *#* - *#* Revision 1.3 2006/03/22 09:49:51 bernie - *#* Simplifications from project_grl. - *#* - *#* Revision 1.2 2006/03/20 17:48:35 bernie - *#* Implement support for ROM menus. - *#* - *#* Revision 1.1 2006/02/10 12:29:36 bernie - *#* Add menu system. - *#* - *#* Revision 1.20 2005/11/16 18:10:19 bernie - *#* Move top-level headers to cfg/ as in DevLib. - *#* - *#* Revision 1.19 2005/02/11 19:11:38 aleph - *#* Move menu_displaymsg() in new displaymsg module - *#* - *#* Revision 1.18 2005/01/13 16:56:36 aleph - *#* Fix progmem includes. - *#* - *#* Revision 1.17 2004/12/14 12:52:45 aleph - *#* Add exclude menu flags - *#* - *#* Revision 1.16 2004/10/01 14:04:59 customer_pw - *#* Add accessor functions for menu flags - *#* - *#* Revision 1.15 2004/09/09 08:31:36 customer_pw - *#* Add disabled item type - *#* - *#* Revision 1.14 2004/08/29 21:46:12 bernie - *#* CVSSILENT: Mark CVS log blocks. - *#* - *#* Revision 1.13 2004/08/25 15:35:23 customer_pw - *#* IPTR -> iptr_t conversion. - *#* - *#* Revision 1.12 2004/08/25 13:23:45 bernie - *#* IPTR -> iptr_t conversion. - *#*/ -#ifndef MWARE_MENU_H -#define MWARE_MENU_H - -#include - -/* Fwd decl */ -struct Bitmap; - -/** Menu callback function */ -typedef iptr_t (*MenuHook)(iptr_t userdata); - -/** - * Menu item description. - */ -typedef struct MenuItem -{ - const_iptr_t label; /**< Item label (ID or ptr to string, 0 to disable) */ - int flags; /**< See MIF_#? definitions below */ - MenuHook hook; /**< Callback function (NULL to terminate item list) */ - iptr_t userdata; /**< User data to be passed back to the hook */ -} MenuItem; - -/** Render hook callback function prototype */ -typedef void (*RenderHook)(struct Bitmap *bitmap, int ypos, bool selected, const struct MenuItem *item); - -/** - * \name Flags for MenuItem.flags. - * \{ - */ -#define MIF_EXCLUDE_MASK 0x00FF /**< Mask for mutual exclusion map (shared with priority). */ -#define MIF_PRI_MASK 0x00FF /**< Mask for priority value (shared with mutual exclusion). */ -#define MIF_PRI(x) ((x) & MIF_PRI_MASK) /**< Set menu item priority. */ -#define MIF_EXCLUDE_0 BV(0) /**< Exclude item 0 when this item is checked */ -#define MIF_EXCLUDE_1 BV(1) /**< Exclude item 1 when this item is checked */ -#define MIF_EXCLUDE_2 BV(2) /**< Exclude item 2 when this item is checked */ -#define MIF_EXCLUDE_3 BV(3) /**< Exclude item 3 when this item is checked */ -#define MIF_EXCLUDE_4 BV(4) /**< Exclude item 4 when this item is checked */ -#define MIF_EXCLUDE_5 BV(5) /**< Exclude item 5 when this item is checked */ -#define MIF_EXCLUDE_6 BV(6) /**< Exclude item 6 when this item is checked */ -#define MIF_EXCLUDE_7 BV(7) /**< Exclude item 7 when this item is checked */ -#define MIF_CHECKED BV(8) /**< Item is currently checked */ -#define MIF_CHECKIT BV(9) /**< Automatically check this item when selected */ -#define MIF_TOGGLE BV(10) /**< Toggle MIF_CHECKED when item is selected */ -#define MIF_HIDDEN BV(11) /**< This menu item is not visible */ -#define MIF_DISABLED BV(12) /**< This menu item is not visible */ -#define MIF_RAMLABEL BV(13) /**< Item label is stored in RAM, not in program memory */ -#define MIF_RENDERHOOK BV(14) /**< Menu render function is passed in label field */ -/* \} */ - -/** - * Menu description. - */ -typedef struct Menu -{ - MenuItem *items; /**< Array of items (end with a NULL hook) */ - const_iptr_t title; /**< Menu title (ID or ptr to string, 0 to disable) */ - int flags; /**< See MF_#? definitions below */ - struct Bitmap *bitmap; /**< Bitmap where the menu is rendered */ - int selected; /**< Initial selection (written to if MF_SAVESEL is set). */ -} Menu; - -/** - * \name Flags for Menu.flags. - * \{ - */ -#define MF_STICKY BV(0) /**< Stay in the menu when the items called return */ -#define MF_TOPLEVEL BV(1) /**< Top-level menu (do not display "back" label) */ -#define MF_ROMITEMS BV(2) /**< Menu items are stored in ROM (default is RAM) */ -#define MF_SAVESEL BV(3) /**< Remember the selected item across invocations. */ -/* \} */ - -/** - * \name Special result codes for menu_handle(). - * \{ - */ -#define MENU_OK ((iptr_t)0) -#define MENU_CANCEL ((iptr_t)-1) -#define MENU_TIMEOUT ((iptr_t)-2) -#define MENU_ABORT ((iptr_t)-3) -#define MENU_DISABLED ((iptr_t)-4) -/* \} */ - -/* Function prototypes */ -iptr_t menu_handle(const struct Menu *menu); -int menu_setFlags(struct Menu *menu, int idx, int flags); -int menu_clearFlags(struct Menu *menu, int idx, int flags); - -#endif /* MWARE_MENU_H */ diff --git a/hw/hw_buzzer.h b/hw/hw_buzzer.h deleted file mode 100644 index d4ec5f74..00000000 --- a/hw/hw_buzzer.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * \file - * - * - * \brief Buzzer hardware-specific definitions - * - * \version $Id$ - * - * \author Francesco Sacchi - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/02/10 12:31:03 bernie - *#* Add templates for hw definitions. - *#* - *#*/ - -#ifndef HW_BUZZER_H -#define HW_BUZZER_H - -#define BUZZER_BIT BV(1) -#define IS_BUZZER_ON 0 -#define BUZZER_HW_INIT do { } while (0) -#define BUZZER_ON do { } while (0) -#define BUZZER_OFF do { } while (0) - -#endif /* HW_BUZZER_H */ diff --git a/hw/hw_kbd.h b/hw/hw_kbd.h deleted file mode 100644 index 7e82cb05..00000000 --- a/hw/hw_kbd.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file - * - * - * \brief Keyboard hardware-specific definitions - * - * \version $Id$ - * - * \author Francesco Sacchi - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2006/03/22 09:51:27 bernie - *#* Wrap C++ stuff. - *#* - *#* Revision 1.2 2006/02/15 09:13:42 bernie - *#* Add keyboard emulator. - *#* - *#* Revision 1.1 2006/02/10 12:31:03 bernie - *#* Add templates for hw definitions. - *#* - *#*/ - -#ifndef HW_KBD_H -#define HW_KBD_H - -#include "kbd_map.h" -#include - -#define K_RPT_MASK (K_UP | K_DOWN | K_OK | K_CANCEL) - -#define KBD_HW_INIT \ - do { \ - } while (0) - -EXTERN_C int emul_kbdReadCols(void); - -/** - * Read the keyboard ports and return the mask of - * depressed keys. - */ -INLINE keymask_t kbd_readkeys(void) -{ - return (keymask_t)emul_kbdReadCols(); -} - -#endif /* HW_KBD_H */ diff --git a/hw/hw_lcd.h b/hw/hw_lcd.h deleted file mode 100644 index b7cf5f89..00000000 --- a/hw/hw_lcd.h +++ /dev/null @@ -1,162 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief LCD low-level hardware macros - */ - -#ifndef HW_LCD_H -#define HW_LCD_H - -#include -//#include - -#include -#include -#include - -#include /* BV() */ -#include - -#include -#include -#include - -/** - * \name LCD I/O pins/ports - * @{ - */ -#define LCD_RS BV(PG3) -#define LCD_RW BV(PG0) -#define LCD_E BV(PG2) -#define LCD_DB0 BV(PA0) -#define LCD_DB1 BV(PA1) -#define LCD_DB2 BV(PA2) -#define LCD_DB3 BV(PA3) -#define LCD_DB4 BV(PA4) -#define LCD_DB5 BV(PA5) -#define LCD_DB6 BV(PA6) -#define LCD_DB7 BV(PA7) -/*@}*/ - -/** - * \name DB high nibble (DB[4-7]) - * @{ - */ -#define LCD_PORT PORTG -#define LCD_DB_PORT PORTA -#define LCD_PIN PING -#define LCD_DB_PIN PINA -#define LCD_DDR DDRG -#define LCD_DB_DDR DDRA - -#if CONFIG_LCD_4BIT - #define LCD_MASK (LCD_DB7 | LCD_DB6 | LCD_DB5 | LCD_DB4) - #define LCD_SHIFT 4 -#else - #define LCD_MASK (uint8_t)0xff - #define LCD_SHIFT 0 -#endif -/*@}*/ - -/** - * \name LCD bus control macros - * @{ - */ -#define LCD_CLR_RS (LCD_PORT &= ~LCD_RS) -#define LCD_SET_RS (LCD_PORT |= LCD_RS) -#define LCD_CLR_RD (LCD_PORT &= ~LCD_RW) -#define LCD_SET_RD (LCD_PORT |= LCD_RW) -#define LCD_CLR_E (LCD_PORT &= ~LCD_E) -#define LCD_SET_E (LCD_PORT |= LCD_E) - -#if CONFIG_LCD_4BIT - #define LCD_WRITE_H(x) (LCD_DB_PORT = (LCD_DB_PORT & ~LCD_MASK) | (((x) >> (4 - LCD_SHIFT)) & LCD_MASK)) - #define LCD_WRITE_L(x) (LCD_DB_PORT = (LCD_DB_PORT & ~LCD_MASK) | (((x) << LCD_SHIFT) & LCD_MASK)) - #define LCD_READ_H ((LCD_DB_PIN & LCD_MASK) >> (4 - LCD_SHIFT)) - #define LCD_READ_L ((LCD_DB_PIN & LCD_MASK) >> LCD_SHIFT) -#else - #define LCD_WRITE(x) (LCD_DB_PORT = (x)) - #define LCD_READ (LCD_DB_PIN) -#endif -/*@}*/ - -/** Set data bus direction to output (write to display) */ -#define LCD_DB_OUT (LCD_DB_DDR |= LCD_MASK) - -/** Set data bus direction to input (read from display) */ -#define LCD_DB_IN (LCD_DB_DDR &= ~LCD_MASK) - -/** Delay for write (Enable pulse width, 220ns) */ -#define LCD_DELAY_WRITE \ - do { \ - NOP; \ - NOP; \ - NOP; \ - NOP; \ - NOP; \ - } while (0) - -/** Delay for read (Data ouput delay time, 120ns) */ -#define LCD_DELAY_READ \ - do { \ - NOP; \ - NOP; \ - NOP; \ - NOP; \ - } while (0) - - -INLINE void lcd_bus_init(void) -{ - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - LCD_PORT = (LCD_PORT & ~(LCD_E | LCD_RW)) | LCD_RS; - LCD_DDR |= LCD_RS | LCD_RW | LCD_E; - - /* - * Data bus is in output state most of the time: - * LCD r/w functions assume it is left in output state - */ - LCD_DB_OUT; - - - IRQ_RESTORE(flags); -} - -#endif /* HW_LCD_H */ diff --git a/hw/hw_mcp41.c b/hw/hw_mcp41.c deleted file mode 100644 index 88cd4ea0..00000000 --- a/hw/hw_mcp41.c +++ /dev/null @@ -1,55 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief MCP41 hardware-specific definitions - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#include - -#include -#include - -#include - - -const uint16_t mcp41_ports[MCP41_CNT] = { - _SFR_IO_ADDR(PORTB), /** Led pot */ - _SFR_IO_ADDR(PORTB), /** Photometer pot */ - }; -const uint8_t mcp41_pins [MCP41_CNT] = { - BV(PB7), - BV(PB6), - }; diff --git a/hw/hw_mcp41.h b/hw/hw_mcp41.h deleted file mode 100644 index 8dd6297e..00000000 --- a/hw/hw_mcp41.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief MCP41 hardware-specific definitions - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#ifndef HW_MCP41_H -#define HW_MCP41_H - -#include -#include -#include -#include - -extern const uint16_t mcp41_ports[MCP41_CNT]; -extern const uint8_t mcp41_pins[MCP41_CNT]; - -/** - * Set MCP41 port associated with \a dev to output. - */ -INLINE void SET_MCP41_DDR(Mcp41Dev dev) -{ - /* DDR port is 1 address before PORT */ - ATOMIC(_SFR_IO8(mcp41_ports[dev] - 1) |= mcp41_pins[dev]); -} - -INLINE void MCP41_ON(Mcp41Dev i) -{ - ATOMIC(_SFR_IO8(mcp41_ports[i]) &= ~mcp41_pins[i]); -} - -INLINE void MCP41_OFF(Mcp41Dev i) -{ - ATOMIC(_SFR_IO8(mcp41_ports[i]) |= mcp41_pins[i]); -} - - -#endif /* HW_MCP41_H */ diff --git a/hw/hw_tc520.h b/hw/hw_tc520.h deleted file mode 100644 index 34501ca5..00000000 --- a/hw/hw_tc520.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief TC520 hardware-specific definitions - * - * \version $Id$ - * \author Francesco Sacchi - */ - -#ifndef HW_TC520_H -#define HW_TC520_H - -#include -#include - -#define CE_PIN PE6 -#define DV_PIN PE5 -#define LOAD_PIN PE3 -#define READ_PIN PE4 - -#define TC520_DDR DDRE -#define TC520_PORT PORTE -#define TC520_PIN PINE - -#define DV_HIGH() (TC520_PIN & BV(DV_PIN)) -#define DV_LOW() (!DV_HIGH()) - -#define CE_HIGH() (TC520_PORT |= BV(CE_PIN)) -#define CE_LOW() (TC520_PORT &= ~BV(CE_PIN)) - -#define LOAD_HIGH() (TC520_PORT |= BV(LOAD_PIN)) -#define LOAD_LOW() (TC520_PORT &= ~BV(LOAD_PIN)) - -#define READ_HIGH() (TC520_PORT |= BV(READ_PIN)) -#define READ_LOW() (TC520_PORT &= ~BV(READ_PIN)) - -#define TC520_HW_INIT \ -do\ -{\ - TC520_PORT |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ - TC520_DDR |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ - TC520_DDR &= ~BV(DV_PIN);\ -}\ -while(0) - -#endif /* HW_TC520_H */ diff --git a/hw/kbd_map.h b/hw/kbd_map.h deleted file mode 100644 index f54bbc02..00000000 --- a/hw/kbd_map.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file - * - * - * \brief Keyboard map definitions. - * - * \version $Id$ - * - * \author Francesco Sacchi - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/02/10 12:31:03 bernie - *#* Add templates for hw definitions. - *#* - *#*/ - -#ifndef HW_KBD_MAP_H -#define HW_KBD_MAP_H - -#include - - -/** - * Type for keyboard mask. - */ -typedef uint16_t keymask_t; - -/** - * \name Keycodes. - */ -/*@{*/ -#define K_UP BV(0) -#define K_DOWN BV(1) -#define K_OK BV(2) -#define K_CANCEL BV(3) - -#define K_REPEAT BV(14) /**< This is a repeated keyevent. */ -#define K_TIMEOUT BV(15) /**< Fake key event for timeouts. */ -/*@}*/ - - -#endif /* HW_KBD_MAP_H */ diff --git a/hw/mcp41_map.h b/hw/mcp41_map.h deleted file mode 100644 index 5e083128..00000000 --- a/hw/mcp41_map.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * \file - * - * - * \brief MCP41 digital potentiometer map definitions. - * - * \version $Id$ - * - * \author Francesco Sacchi - */ - -#ifndef MCP41_MAP_H -#define MCP41_MAP_H - -/** \name Enum for mcp41 pot evices. - * \{ - */ -typedef enum Mcp41Dev -{ - MCP41_LED, - MCP41_PHOTO_GAIN, - - MCP41_CNT, -} Mcp41Dev; -/* \} */ - -#endif /* MCP41_MAP_H */ diff --git a/icons/Makefile b/icons/Makefile deleted file mode 100644 index 50469549..00000000 --- a/icons/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# -# $Id: Makefile 18234 2007-10-08 13:39:48Z rasky $ -# Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/) -# All rights reserved. -# -# Author: Stefano Fedrigo -# -# $Log$ -# Revision 1.2 2006/09/20 14:18:01 marco -# Use only icons neede by demo. -# -# Revision 1.1 2006/09/19 17:48:00 bernie -# Add temporary logo. -# -# - -# Set to 1 for debug builds -DEBUG = 1 - -RASTERS = logo.raster - -FLIPIMAGE = flipimage -flipimage_SRC = flipimage.cpp -flipimage_OBJ = $(flipimage_SRC:%.cpp=%.o) - -.PHONY: all -all: $(RASTERS) - -# Link rule -$(FLIPIMAGE): $(flipimage_OBJ) - $(CXX) $^ $(flipimage_LIBS) $(LDFLAGS) -o $@ - -.PHONY: clean -clean: - rm -f $(TRG) $(flipimage_OBJ) - rm -f $(RASTERS) - -.PHONY: rasters -rasters: $(FLIPIMAGE) $(RASTERS) - -%.raster: %.png $(FLIPIMAGE) - convert $< txt:- | ./flipimage >$@ - -# Include dependencies --include *.d diff --git a/icons/flipimage.cpp b/icons/flipimage.cpp deleted file mode 100644 index f28af7da..00000000 --- a/icons/flipimage.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * \author Stefano Fedrigo - * - * \brief Conversion tool from image TXT format to LCD bitmap - */ - -/* - * $Log$ - * Revision 1.1 2006/09/19 17:48:00 bernie - * Add temporary logo. - * - * Revision 1.3 2004/09/24 17:25:32 powersoft - * Fix for new version of ImageMagick. - * - * Revision 1.2 2004/03/13 22:52:54 aleph - * documentation fixes - * - * Revision 1.1 2004/01/26 15:31:17 aleph - * Add boot images and tools for importing them - * - */ - -#include -#include -#include - -#define RASTER_WIDTH 82 -#define RASTER_HEIGHT 64 - -// Minimum color level to consider a pixel on -#define COLOR_THRESHOLD 128 - - -using namespace std; - - -int main(void) -{ - char buf[64]; - int n; - unsigned char mask; - unsigned char line[RASTER_WIDTH]; - - for (int l = 0; l < RASTER_HEIGHT/8; l++) - { - mask = 1; - memset(line, 0, sizeof(line)); - - do - { - for (int x = 0; x < RASTER_WIDTH; x++) - { - if (!cin.getline(buf, sizeof(buf))) - goto print_line; - - istringstream ss(buf); - string s; - char c; - - ss - >> s // skip glob coord spec - >> c // skip open paren - >> n; // this is the red level - - //DEBUG - //cout << "s='" << s << "' n='" << n << "'" << endl; - - if (n < COLOR_THRESHOLD) - line[x] |= mask; - } - } - while (mask <<= 1); - -print_line: - cout << "\n\t"; - for (int x = 0; x < RASTER_WIDTH; x++) - { - printf("0x%02X", line[x]); - if (x % 8 == 7) - cout << ",\n\t"; - else - cout << ", "; - } - cout << endl; - } - - return 0; -} diff --git a/icons/logo.c b/icons/logo.c deleted file mode 100644 index 651f07bd..00000000 --- a/icons/logo.c +++ /dev/null @@ -1,116 +0,0 @@ - -#include "logo.h" -#include -#include - -/** - * BeRTOS logo - */ -const PROGMEM uint8_t bertos_logo_raster[] = { - - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - - 0x00, 0xF8, 0xF8, 0xF8, 0x78, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x78, 0x70, 0xF0, 0xF0, 0xE0, 0x80, 0x00, - 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x70, 0x70, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x70, 0xF0, 0xE0, 0xE0, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - - 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0xF1, 0x7F, 0x3F, 0x1F, 0x00, - 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x18, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3F, 0x3F, - 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - - 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x07, 0x1F, 0xFF, 0xFE, 0xFC, - 0x00, 0x00, 0x07, 0x1F, 0x9F, 0xBC, 0xB8, 0xB8, - 0x30, 0x30, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0xB0, 0xB0, 0xB8, 0xB8, 0xBC, 0x9E, 0x1F, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, - 0x80, 0x00, - - 0x32, 0x3F, 0x3F, 0x3F, 0x3C, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x3C, 0x1C, 0x1F, 0x1F, 0x0F, 0x03, - 0x00, 0x00, 0x00, 0x3F, 0x0D, 0x04, 0x04, 0x0C, - 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x31, - 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, - 0x24, 0x25, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - -}; - -EXTERN_CONST struct Image bertos_logo = -{ - /* .raster = */ bertos_logo_raster, - /* .width = */ 82, - /* .height = */ 64, - /* .stride = */ 82 -}; - diff --git a/icons/logo.h b/icons/logo.h deleted file mode 100644 index e0bbc636..00000000 --- a/icons/logo.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -extern const struct Image bertos_logo; diff --git a/icons/logo.png b/icons/logo.png deleted file mode 100755 index aecad002..00000000 Binary files a/icons/logo.png and /dev/null differ diff --git a/kern/kfile.c b/kern/kfile.c deleted file mode 100644 index 1ec32664..00000000 --- a/kern/kfile.c +++ /dev/null @@ -1,221 +0,0 @@ -/** - * \file - * - * - * \brief Virtual KFile I/O interface. - * This module implements some generic I/O interfaces for kfile. - * - * \version $Id$ - * \author Francesco Sacchi - * \author Daniele Basile - * - */ - - -#include "kfile.h" -#include - -#include -#include -#include - -/* - * Sanity check for config parameters required by this module. - */ -#if !defined(CONFIG_KFILE_GETS) || ((CONFIG_KFILE_GETS != 0) && CONFIG_KFILE_GETS != 1) - #error CONFIG_KFILE_GETS must be set to either 0 or 1 in appconfig.h -#endif -#if !defined(CONFIG_PRINTF) - #error CONFIG_PRINTF missing in appconfig.h -#endif - - -/** - * Generic putc() implementation using \a fd->write. - */ -int kfile_putc(int _c, struct KFile *fd) -{ - unsigned char c = (unsigned char)_c; - - if (kfile_write(fd, &c, sizeof(c)) == sizeof(c)) - return (int)((unsigned char)_c); - else - return EOF; -} - -/** - * Generic getc() implementation using \a fd->read. - */ -int kfile_getc(struct KFile *fd) -{ - unsigned char c; - - if (kfile_read(fd, &c, sizeof(c)) == sizeof(c)) - return (int)((unsigned char)c); - else - return EOF; -} - -#if CONFIG_PRINTF -/** - * Formatted write. - */ -int kfile_printf(struct KFile *fd, const char *format, ...) -{ - va_list ap; - int len; - - va_start(ap, format); - len = _formatted_write(format, (void (*)(char, void *))kfile_putc, fd, ap); - va_end(ap); - - return len; -} -#endif /* CONFIG_PRINTF */ - -/** - * Write a string to kfile \a fd. - * \return 0 if OK, EOF in case of error. - */ -int kfile_print(struct KFile *fd, const char *s) -{ - while (*s) - { - if (kfile_putc(*s++, fd) == EOF) - return EOF; - } - return 0; -} - -#if CONFIG_KFILE_GETS -/** - * Read a line long at most as size and put it - * in buf. - * \return number of chars read or EOF in case - * of error. - */ -int kfile_gets(struct KFile *fd, char *buf, int size) -{ - return kfile_gets_echo(fd, buf, size, false); -} - - -/** - * Read a line long at most as size and put it - * in buf, with optional echo. - * - * \return number of chars read, or EOF in case - * of error. - */ -int kfile_gets_echo(struct KFile *fd, char *buf, int size, bool echo) -{ - int i = 0; - int c; - - for (;;) - { - if ((c = kfile_getc(fd)) == EOF) - { - buf[i] = '\0'; - return -1; - } - - /* FIXME */ - if (c == '\r' || c == '\n' || i >= size-1) - { - buf[i] = '\0'; - if (echo) - kfile_print(fd, "\r\n"); - break; - } - buf[i++] = c; - if (echo) - kfile_putc(c, fd); - } - - return i; -} -#endif /* !CONFIG_KFILE_GETS */ - - -/** - * Move \a fd file seek position of \a offset bytes from \a whence. - * - * This is a generic implementation of seek function, you can redefine - * it in your local module if needed. - */ -kfile_off_t kfile_genericSeek(struct KFile *fd, kfile_off_t offset, KSeekMode whence) -{ - uint32_t seek_pos; - - switch (whence) - { - - case KSM_SEEK_SET: - seek_pos = 0; - break; - case KSM_SEEK_END: - seek_pos = fd->size; - break; - case KSM_SEEK_CUR: - seek_pos = fd->seek_pos; - break; - default: - ASSERT(0); - return EOF; - break; - } - - /* Bound check */ - if (seek_pos + offset > fd->size) - { - ASSERT(0); - return EOF; - } - - fd->seek_pos = seek_pos + offset; - - return fd->seek_pos; -} - -/** - * Reopen file \a fd. - * This is a generic implementation that only flush file - * and reset seek_pos to 0. - */ -struct KFile * kfile_genericReopen(struct KFile *fd) -{ - kfile_flush(fd); - kfile_seek(fd, 0, KSM_SEEK_SET); - return fd; -} - - diff --git a/kern/kfile.h b/kern/kfile.h deleted file mode 100644 index 4bb7a238..00000000 --- a/kern/kfile.h +++ /dev/null @@ -1,266 +0,0 @@ -/** - * \file - * - * - * \brief Virtual KFile I/O interface. - * KFile is a generic interface for file I/O. - * It uses an object-oriented model to supply - * a generic interface for drivers to communicate. - * This module contains only definitions, the instance structure - * and an API. - * Each KFile user should implement at least some methods. - * E.G. - * If you have a serial driver and want to comply to KFile interface, - * you have to declare your context structure: - * - * \code - * typedef struct KFileSerial - * { - * KFile fd; - * Serial *ser; - * } KFileSerial; - * \endcode - * - * You should also supply a macro for casting KFile to KFileSerial: - * - * \code - * INLINE KFileSerial * KFILESERIAL(KFile *fd) - * { - * ASSERT(fd->_type == KFT_SERIAL); - * return (KFileSerial *)fd; - * } - * \endcode - * - * Then you can implement as much interface functions as you like - * and leave the others to NULL. - * ser_close implementation example: - * - * \code - * static int ser_kfile_close(struct KFile *fd) - * { - * KFileSerial *fds = KFILESERIAL(fd); - * ser_close(fds->ser); - * return 0; - * } - * \endcode - * KFILESERIAL macro helps to ensure that obj passed is really a Serial. - * - * KFile interface do not supply the open function: this is deliberate, - * because in embedded systems each device has its own init parameters. - * For the same reason specific file settings (like baudrate for Serial, for example) - * are demanded to specific driver implementation. - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - * \author Daniele Basile - */ - -#ifndef KERN_KFILE_H -#define KERN_KFILE_H - -#include -#include -#include - -/* fwd decl */ -struct KFile; - -typedef int32_t kfile_off_t; ///< KFile offset type, used by kfile_seek function. - -/** - * Costants for repositioning read/write file offset. - * These are needed because on some embedded platforms - * ANSI I/O library may not be present. - */ -typedef enum KSeekMode -{ - KSM_SEEK_SET, ///< Seek from file beginning. - KSM_SEEK_CUR, ///< Seek from file current position. - KSM_SEEK_END, ///< Seek from file end. -} KSeekMode; - -/** - * Prototypes for KFile access functions. - * I/O file functions must be ANSI compliant. - * \note A KFile user can choose which function subset to implement, - * but has to set to NULL unimplemented features. - * \{ - */ - -/** - * Read from file. - * \return the number of bytes read. - */ -typedef size_t (*ReadFunc_t) (struct KFile *fd, void *buf, size_t size); - -/** - * Write to file. - * \return the number of bytes written. - */ -typedef size_t (*WriteFunc_t) (struct KFile *fd, const void *buf, size_t size); - -/** - * Seek into file (if seekable). - * \return the new file offset or EOF on errors. - */ -typedef kfile_off_t (*SeekFunc_t) (struct KFile *fd, kfile_off_t offset, KSeekMode whence); - -/** - * Close and reopen file \a fd. - * The reopening is done with the former file parameters and access modes. - */ -typedef struct KFile * (*ReOpenFunc_t) (struct KFile *fd); - -/** - * Close file. - * \return 0 on success, EOF on errors. - */ -typedef int (*CloseFunc_t) (struct KFile *fd); - -/** - * Flush file I/O. - * \return 0 on success, EOF on errors. - */ -typedef int (*FlushFunc_t) (struct KFile *fd); - -/** - * Get file error mask. - * \return 0 on success or file error code, device specific. - */ -typedef int (*ErrorFunc_t) (struct KFile *fd); - -/** - * Clear errors. - */ -typedef void (*ClearErrFunc_t) (struct KFile *fd); -/* \} */ - -/** - * Context data for callback functions which operate on - * pseudo files. - * \note If you change interface, remember to add corresponding access function. - */ -typedef struct KFile -{ - ReadFunc_t read; - WriteFunc_t write; - ReOpenFunc_t reopen; - CloseFunc_t close; - SeekFunc_t seek; - FlushFunc_t flush; - ErrorFunc_t error; - ClearErrFunc_t clearerr; - DB(id_t _type); ///< Used to keep trace, at runtime, of obj type. - - /* NOTE: these must _NOT_ be size_t on 16bit CPUs! */ - uint32_t seek_pos; - uint32_t size; -} KFile; - -/** - * Generic implementation of kfile_seek. - */ -kfile_off_t kfile_genericSeek(struct KFile *fd, kfile_off_t offset, KSeekMode whence); - -/** - * Generic implementation of kfile_reopen. - */ -struct KFile * kfile_genericReopen(struct KFile *fd); - -int kfile_putc(int c, struct KFile *fd); ///< Generic putc implementation using kfile_write. -int kfile_getc(struct KFile *fd); ///< Generic getc implementation using kfile_read. -int kfile_printf(struct KFile *fd, const char *format, ...); -int kfile_print(struct KFile *fd, const char *s); -int kfile_gets(struct KFile *fd, char *buf, int size); -int kfile_gets_echo(struct KFile *fd, char *buf, int size, bool echo); - -/** - * Interface functions for KFile access. - * \note Remember to change following functions if KFile interface changes. - * \{ - */ -INLINE size_t kfile_read(struct KFile *fd, void *buf, size_t size) -{ - ASSERT(fd->read); - return fd->read(fd, buf, size); -} - -INLINE size_t kfile_write(struct KFile *fd, const void *buf, size_t size) -{ - ASSERT(fd->write); - return fd->write(fd, buf, size); -} - -INLINE KFile * kfile_reopen(struct KFile *fd) -{ - ASSERT(fd->reopen); - return fd->reopen(fd); -} - -INLINE int kfile_close(struct KFile *fd) -{ - ASSERT(fd->close); - return fd->close(fd); -} - -INLINE kfile_off_t kfile_seek(struct KFile *fd, kfile_off_t offset, KSeekMode whence) -{ - ASSERT(fd->seek); - return fd->seek(fd, offset, whence); -} - -INLINE int kfile_flush(struct KFile *fd) -{ - ASSERT(fd->flush); - return fd->flush(fd); -} - -INLINE int kfile_error(struct KFile *fd) -{ - ASSERT(fd->error); - return fd->error(fd); -} - -INLINE void kfile_clearerr(struct KFile *fd) -{ - ASSERT(fd->clearerr); - fd->clearerr(fd); -} -/* \} */ - -/** - * Kfile test function. - */ -bool kfile_test(KFile *fd, uint8_t *test_buf, uint8_t *save_buf, size_t size); - -#endif /* KERN_KFILE_H */ diff --git a/kern/kfile_test.c b/kern/kfile_test.c deleted file mode 100644 index 76e78092..00000000 --- a/kern/kfile_test.c +++ /dev/null @@ -1,248 +0,0 @@ -/** - * \file - * - * - * \brief Test suite for virtual KFile I/O interface. - * This module implements a test for some generic I/O interfaces for kfile. - * - * \version $Id$ - * \author Francesco Sacchi - * \author Daniele Basile - * - */ - - -#include "kfile.h" -#include - -#include -#include -#include - -/** - * KFile read/write subtest. - * Try to write/read in the same \a f file location \a size bytes. - * \return true if all is ok, false otherwise - * \note Restore file position at exit (if no error) - * \note Test buffer \a buf must be filled with - * the following statement: - *
- * buf[i] = i & 0xff
- * 
- */ -static bool kfile_rwTest(KFile *f, uint8_t *buf, size_t size) -{ - /* - * Write test buffer - */ - if (kfile_write(f, buf, size) != size) - return false; - - kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR); - - /* - * Reset test buffer - */ - memset(buf, 0, size); - - /* - * Read file in test buffer - */ - if (kfile_read(f, buf, size) != size) - return false; - kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR); - - /* - * Check test result - */ - for (size_t i = 0; i < size; i++) - if (buf[i] != (i & 0xff)) - return false; - - return true; -} - -/** - * KFile read/write test. - * This function write and read \a test_buf long \a size - * on \a fd handler. - * \a save_buf can be NULL or a buffer where to save previous file content. - */ -bool kfile_test(KFile *fd, uint8_t *test_buf, uint8_t *save_buf, size_t size) -{ - /* - * Part of test buf size that you would write. - * This var is used in test 3 to check kfile_write - * when writing beyond filesize limit. - */ - kfile_off_t len = size / 2; - - - /* Fill test buffer */ - for (size_t i = 0; i < size; i++) - test_buf[i] = (i & 0xff); - - /* - * If necessary, user can save content, - * for later restore. - */ - if (save_buf) - { - kfile_read(fd, save_buf, size); - kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); - } - - /* TEST 1 BEGIN. */ - kprintf("Test 1: write from pos 0 to [%lu]\n", size); - - /* - * Seek to addr 0. - */ - if (kfile_seek(fd, 0, KSM_SEEK_SET) != 0) - goto kfile_test_end; - - /* - * Test read/write to address 0..size - */ - if (!kfile_rwTest(fd, test_buf, size)) - goto kfile_test_end; - - kprintf("Test 1: ok!\n"); - - /* - * Restore previous read content. - */ - if (save_buf) - { - kfile_seek(fd, 0, KSM_SEEK_SET); - - if (kfile_write(fd, save_buf, size) != size) - goto kfile_test_end; - - kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); - } - /* TEST 1 END. */ - - /* TEST 2 BEGIN. */ - kprintf("Test 2: write from pos [%lu] to [%lu]\n", fd->size/2 , fd->size/2 + size); - - /* - * Go to half test size. - */ - kfile_seek(fd, (fd->size / 2), KSM_SEEK_SET); - - /* - * If necessary, user can save content - * for later restore. - */ - if (save_buf) - { - kfile_read(fd, save_buf, size); - kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR); - kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); - } - - /* - * Test read/write to address filesize/2 ... filesize/2 + size - */ - if (!kfile_rwTest(fd, test_buf, size)) - goto kfile_test_end; - - kprintf("Test 2: ok!\n"); - - /* - * Restore previous content. - */ - if (save_buf) - { - kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR); - - if (kfile_write(fd, save_buf, size) != size) - goto kfile_test_end; - - kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + size); - } - - /* TEST 2 END. */ - - /* TEST 3 BEGIN. */ - kprintf("Test 3: write outside of fd->size limit [%lu]\n", fd->size); - kprintf("This test should FAIL!, you must see an assertion fail message.\n"); - - /* - * Go to the Flash end - */ - kfile_seek(fd, -len, KSM_SEEK_END); - - /* - * If necessary, user can save content, - * for later restore. - */ - if (save_buf) - { - kfile_read(fd, save_buf, len); - kfile_seek(fd, -len, KSM_SEEK_CUR); - kprintf("Saved content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + len); - } - - /* - * Test read/write to address (filesize - size) ... filesize - */ - if (kfile_rwTest(fd, test_buf, size)) - goto kfile_test_end; - - kprintf("Test 3: ok!\n"); - - /* - * Restore previous read content - */ - if (save_buf) - { - kfile_seek(fd, -len, KSM_SEEK_END); - - if (kfile_write(fd, save_buf, len) != len) - goto kfile_test_end; - - kprintf("Restore content..form [%lu] to [%lu]\n", fd->seek_pos, fd->seek_pos + len); - } - - /* TEST 3 END. */ - - kfile_close(fd); - return true; - -kfile_test_end: - kfile_close(fd); - return false; -} - - - diff --git a/kern/monitor.c b/kern/monitor.c deleted file mode 100644 index 96b563e1..00000000 --- a/kern/monitor.c +++ /dev/null @@ -1,174 +0,0 @@ -/** - * \file - * - * - * \brief Monitor to check for stack overflows - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - - -#include "monitor.h" - -#if CONFIG_KERN_MONITOR - -#include "proc_p.h" -#include -#include -#include -#include -#include - - -static List MonitorProcs; - - -void monitor_init(void) -{ - LIST_INIT(&MonitorProcs); -} - - -void monitor_add(Process* proc, const char* name, cpustack_t* stack_base, size_t stack_size) -{ - proc->monitor.name = name; - proc->monitor.stack_base = stack_base; - proc->monitor.stack_size = stack_size; - - ADDTAIL(&MonitorProcs, &proc->monitor.link); -} - - -void monitor_remove(Process* proc) -{ - REMOVE(&proc->monitor.link); -} - -void monitor_rename(Process *proc, const char* name) -{ - proc->monitor.name = name; -} - -/* TODO: use containerof() */ -#define MONITOR_NODE_TO_PROCESS(node) \ - (struct Process *)((intptr_t)(node) - offsetof(struct Process, monitor.link)) - -size_t monitor_checkStack(cpustack_t* stack_base, size_t stack_size) -{ - cpustack_t* beg; - cpustack_t* cur; - cpustack_t* end; - size_t sp_free; - - beg = stack_base; - end = stack_base + stack_size / sizeof(cpustack_t) - 1; - - if (CPU_STACK_GROWS_UPWARD) - { - cur = beg; - beg = end; - end = cur; - } - - cur = beg; - while (cur != end) - { - if (*cur != CONFIG_KERN_STACKFILLCODE) - break; - - if (CPU_STACK_GROWS_UPWARD) - cur--; - else - cur++; - } - - sp_free = ABS(cur - beg) * sizeof(cpustack_t); - return sp_free; -} - - -void monitor_report(void) -{ - struct Process* p; - int i; - - if (LIST_EMPTY(&MonitorProcs)) - { - kputs("No stacks registered in the monitor\n"); - return; - } - - kprintf("%-24s%-8s%-8s%-8s%-8s\n", "Process name", "TCB", "SPbase", "SPsize", "SPfree"); - for (i=0;i<56;i++) - kputchar('-'); - kputchar('\n'); - - for (p = MONITOR_NODE_TO_PROCESS(LIST_HEAD(&MonitorProcs)); - p->monitor.link.succ; - p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ)) - { - size_t free = monitor_checkStack(p->monitor.stack_base, p->monitor.stack_size); - kprintf("%-24s%-8p%-8p%-8lu%-8lu\n", - p->monitor.name, p, p->monitor.stack_base, p->monitor.stack_size, free); - } -} - - -static void NORETURN monitor(void) -{ - struct Process *p; - - while (1) - { - for (p = MONITOR_NODE_TO_PROCESS(LIST_HEAD(&MonitorProcs)); - p->monitor.link.succ; - p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ)) - { - size_t free = monitor_checkStack(p->monitor.stack_base, p->monitor.stack_size); - - if (free < 0x20) - kprintf("MONITOR: WARNING: Free stack for process '%s' is only %u chars\n", - p->monitor.name, (unsigned int)free); - - timer_delay(500); - } - } -} - - -void monitor_start(size_t stacksize, cpustack_t *stack) -{ - proc_new(monitor, NULL, stacksize, stack); -} - -#endif /* CONFIG_KERN_MONITOR */ diff --git a/kern/monitor.h b/kern/monitor.h deleted file mode 100644 index 95bbb6db..00000000 --- a/kern/monitor.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * \file - * - * - * \brief Monitor to check for stack overflows - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -#ifndef KERN_MONITOR_H -#define KERN_MONITOR_H - -#include -#include - -#if CONFIG_KERN_MONITOR - -/** - * Start the kernel monitor. It is a special process which checks every second the stacks of the - * running processes trying to detect stack overflows. - * - * \param stacksize Size of stack in chars - * \param stack Pointer to the stack that will be used by the monitor - * - * \note The stack is provided by the caller so that there is no wasted space if the monitor - * is not used. - */ -void monitor_start(size_t stacksize, cpustack_t *stack); - - -/** - * Manually check if a given stack has overflown. This is used to check for stacks - * of processes handled externally form the kernel, or for other stacks (for instance - * the interrupt supervisor stack). - * - * \note For this function to work, the stack must have been filled at startup with - * CONFIG_KERN_STACKFILLCODE. - */ -size_t monitor_checkStack(cpustack_t *stack_base, size_t stack_size); - - -/** Print a report of the stack status through kdebug */ -void monitor_report(void); - - -#endif /* CONFIG_KERN_MONITOR */ -#endif /* KERN_MONITOR_H */ diff --git a/kern/msg.h b/kern/msg.h deleted file mode 100644 index e4ee21f9..00000000 --- a/kern/msg.h +++ /dev/null @@ -1,286 +0,0 @@ -/** - * \file - * - * - * - * This module implements a common system for executing - * a user defined action calling a hook function. - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Simple inter-process messaging system - * - * Handle queues of messages associated an action. - * - * A message port is an abstraction used to exchange information - * asynchronously between processes or other entities such as - * interrupts and call-back functions. - * - * This form of IPC is higher-level than bare signals and - * semaphores, because it sets a policy for exchanging - * structured data with well-defined synchronization and - * ownership semantics. - * - * Before using it, a message port must be initialized by - * calling msg_initPort(), which associates the port with - * an Event object, which can be setup to signal a process - * or invoke a call-back hook. - * - * A process or interrupt routine can deliver messages to any - * message port by calling msg_put(). By sending a message, - * the sender temporarly or permanently transfers ownership - * of its associated data to the receiver. - * - * Queuing a message to a port automatically triggers the - * associated Event to notify the receiver. When the - * receiver wakes up, it usually invokes msg_get() to pick - * the next message from the port. - * - * Message ports can hold any number of pending messages, - * and receivers usually process them in FIFO order. - * Other scheduling policies are possible, but not implemented - * in this API. - * - * After the receiver has done processing a message, it replies - * it back to the sender with msg_reply(), which transfer - * ownership back to the original sender. Replies are delivered - * to a reply port, which is nothing more than another MsgPort - * structure designated by the sender. - * - * Returning messages to senders is not mandatory, but it provides - * a convenient way to provide some kind of result and simplify - * the resource allocation scheme at the same time. - * - * When using signals to receive messages in a process, you - * call sig_wait() in an event-loop to wake up when messages - * are delivered to any of your ports. When your process - * wakes up with the port signal active, multiple messages - * may already have queued up at the message port, and the - * process must process them all before returning to sleep. - * Signals don't keep a nesting count. - * - * A simple message loop works like this: - * - * \code - * // Our message port. - * static MsgPort test_port; - * - * // A test message with two parameters and a result. - * typedef struct - * { - * Msg msg; - * - * int x, y; - * int result; - * } TestMsg; - * - * - * // A process that sends two messages and waits for replies. - * static void sender_proc(void) - * { - * MsgPort test_reply_port; - * TestMsg msg1; - * TestMsg msg2; - * Msg *reply; - * - * msg_initPort(&reply_port, - * event_createSignal(proc_current(), SIGF_SINGLE); - * - * // Fill-in first message and send it out. - * msg1.x = 3; - * msg1.y = 2; - * msg1.msg.replyPort = &test_reply_port; - * msg_put(&test_port, &msg1); - * - * // Fill-in second message and send it out too. - * msg2.x = 5; - * msg2.y = 4; - * msg2.msg.replyPort = &test_reply_port; - * msg_put(&test_port, &msg1); - * - * // Wait for a reply... - * sig_wait(SIG_SINGLE); - * - * reply = (TestMsg *)msg_get(&test_reply_port); - * ASSERT(reply != NULL); - * ASSERT(reply->result == 5); - * - * // Get reply to second message. - * while (!(reply = (TestMsg *)msg_get(&test_reply_port)) - * { - * // Not yet, be patient and wait some more. - * sig_wait(SIG_SINGLE); - * } - * - * ASSERT(reply->result == 9); - * } - * - * - * // Receive messages and do something boring with them. - * static void receiver_proc(void) - * { - * msg_initPort(&test_port, - * event_createSignal(proc_current(), SIGF_EXAMPLE); - * - * proc_new(sender_proc, (iptr_t)&test_port, - * sender_stack, sizeof(sender_stack); - * - * for (;;) - * { - * sigmask_t sigs = sig_wait(SIGF_EXAMPLE | more_signals); - * - * if (sigs & SIGF_EXAMPLE) - * { - * TestMsg *emsg; - * while (emsg = (TestMsg *)msg_get(&test_port) - * { - * // Do something with the message - * emsg->result = emsg->x + emsg->y; - * msg_reply((Msg *)msg); - * } - * } - * } - * } - * \endcode - */ - - */ - -#ifndef KERN_MSG_H -#define KERN_MSG_H - -#include "event.h" -#include - - -typedef struct MsgPort -{ - List queue; /**< Messages queued at this port. */ - Event event; /**< Event to trigger when a message arrives. */ -} MsgPort; - - -typedef struct Msg -{ - Node link; /**< Link into message port queue. */ - MsgPort *replyPort; /**< Port to which the msg is to be replied. */ - /* User data may follow */ -} Msg; - - -/** - * Lock a message port. - * - * This is required before reading or manipulating - * any field of the MsgPort structure. - * - * \note Ports may be locked multiple times and each - * call to msg_lockPort() must be paired with - * a corresponding call to msg_unlockPort(). - * - * \todo Add a configurable policy for locking against - * interrupts and locking with semaphorse. - * - * \see msg_unlockPort() - */ -INLINE void msg_lockPort(MsgPort *port) -{ - proc_forbid(); -} - -/** - * Unlock a message port. - * - * \see msg_lockPort() - */ -INLINE void msg_unlockPort(MsgPort *port) -{ - proc_permit(); -} - - -/** Initialize a message port */ -INLINE void msg_initPort(MsgPort *port, Event event) -{ - LIST_INIT(&port->queue); - port->event = event; -} - -/** Queue \a msg into \a port, triggering the associated event */ -INLINE void msg_put(MsgPort *port, Msg *msg) -{ - msg_portLock(port); - ADDTAIL(&port->queue, &msg->link); - msg_portUnlock(port); - - event_do(&port->event); -} - -/** - * Get the first message from the queue of \a port. - * - * \return Pointer to the message or NULL if the port was empty. - */ -INLINE Msg *msg_get(MsgPort *port) -{ - Msg *msg; - - msg_portLock(port); - msg = (Msg *)REMHEAD(&port->queue); - msg_portUnlock(port); - - return msg; -} - -/** Peek the first message in the queue of \a port, or NULL if the port is empty. */ -INLINE Msg *msg_peek(MsgPort *port) -{ - Msg *msg; - - msg_portLock(port); - msg = (Msg *)port->queue.head; - if (ISLISTEMPTY(&port->queue)) - msg = NULL; - msg_portUnlock(port); - - return msg; -} - -/** Send back (reply) \a msg to its sender. */ -INLINE void msg_reply(Msg *msg) -{ - msg_put(msg->replyPort, msg); -} - -#endif /* KERN_MSG_H */ diff --git a/kern/proc.c b/kern/proc.c deleted file mode 100644 index a9e95624..00000000 --- a/kern/proc.c +++ /dev/null @@ -1,416 +0,0 @@ -/** - * \file - * - * - * \brief Simple realtime multitasking scheduler. - * Context switching is only done cooperatively. - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - - -#include "proc_p.h" -#include "proc.h" -//#include "hw.h" -#include -#include -#include -#include -#include -#include -#include /* ARCH_EMUL */ -#include /* ABS() */ - -#include /* memset() */ - -/** - * CPU dependent context switching routines. - * - * \note This function *MUST* preserve also the status of the interrupts. - */ -EXTERN_C void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp); -EXTERN_C int asm_switch_version(void); - -/* - * The scheduer tracks ready and waiting processes - * by enqueuing them in these lists. A pointer to the currently - * running process is stored in the CurrentProcess pointer. - * - * NOTE: these variables are protected by DI/EI locking - */ -REGISTER Process *CurrentProcess; -REGISTER List ProcReadyList; - - -#if CONFIG_KERN_PREEMPTIVE -/* - * The time sharing scheduler forces a task switch when - * the current process has consumed its quantum. - */ -uint16_t Quantum; -#endif - - -/* In Win32 we must emulate stack on the real process stack */ -#if (ARCH & ARCH_EMUL) -extern List StackFreeList; -#endif - -/** The main process (the one that executes main()). */ -struct Process MainProcess; - - -static void proc_init_struct(Process *proc) -{ - /* Avoid warning for unused argument. */ - (void)proc; - -#if CONFIG_KERN_SIGNALS - proc->sig_recv = 0; -#endif - -#if CONFIG_KERN_PREEMPTIVE - proc->forbid_cnt = 0; -#endif - -#if CONFIG_KERN_HEAP - proc->flags = 0; -#endif -} - -MOD_DEFINE(proc); - -void proc_init(void) -{ - LIST_INIT(&ProcReadyList); - -#if CONFIG_KERN_MONITOR - monitor_init(); -#endif - - /* We "promote" the current context into a real process. The only thing we have - * to do is create a PCB and make it current. We don't need to setup the stack - * pointer because it will be written the first time we switch to another process. - */ - proc_init_struct(&MainProcess); - CurrentProcess = &MainProcess; - - /* Make sure the assembly routine is up-to-date with us */ - ASSERT(asm_switch_version() == 1); - MOD_INIT(proc); -} - - -/** - * Create a new process, starting at the provided entry point. - * - * \return Process structure of new created process - * if successful, NULL otherwise. - */ -struct Process *proc_new_with_name(UNUSED(const char *, name), void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack_base) -{ - Process *proc; - size_t i; - size_t proc_size_words = ROUND2(sizeof(Process), sizeof(cpustack_t)) / sizeof(cpustack_t); -#if CONFIG_KERN_HEAP - bool free_stack = false; -#endif - -#if (ARCH & ARCH_EMUL) - /* Ignore stack provided by caller and use the large enough default instead. */ - stack_base = (cpustack_t *)LIST_HEAD(&StackFreeList); - REMOVE(LIST_HEAD(&StackFreeList)); - stacksize = CONFIG_PROC_DEFSTACKSIZE; -#elif CONFIG_KERN_HEAP - /* Did the caller provide a stack for us? */ - if (!stack_base) - { - /* Did the caller specify the desired stack size? */ - if (!stacksize) - stacksize = CONFIG_PROC_DEFSTACKSIZE + sizeof(Process); - - /* Allocate stack dinamically */ - if (!(stack_base = heap_alloc(stacksize))) - return NULL; - - free_stack = true; - } -#else - /* Stack must have been provided by the user */ - ASSERT(stack_base); - ASSERT(stacksize); -#endif - -#if CONFIG_KERN_MONITOR - /* Fill-in the stack with a special marker to help debugging */ - memset(stack_base, CONFIG_KERN_STACKFILLCODE, stacksize / sizeof(cpustack_t)); -#endif - - /* Initialize the process control block */ - if (CPU_STACK_GROWS_UPWARD) - { - proc = (Process*)stack_base; - proc->stack = stack_base + proc_size_words; - if (CPU_SP_ON_EMPTY_SLOT) - proc->stack++; - } - else - { - proc = (Process*)(stack_base + stacksize / sizeof(cpustack_t) - proc_size_words); - proc->stack = (cpustack_t*)proc; - if (CPU_SP_ON_EMPTY_SLOT) - proc->stack--; - } - - proc_init_struct(proc); - proc->user_data = data; - -#if CONFIG_KERN_HEAP - proc->stack_base = stack_base; - proc->stack_size = stack_size; - if (free_stack) - proc->flags |= PF_FREESTACK; -#endif - - /* Initialize process stack frame */ - CPU_PUSH_CALL_CONTEXT(proc->stack, proc_exit); - CPU_PUSH_CALL_CONTEXT(proc->stack, entry); - - /* Push a clean set of CPU registers for asm_switch_context() */ - for (i = 0; i < CPU_SAVED_REGS_CNT; i++) - CPU_PUSH_WORD(proc->stack, CPU_REG_INIT_VALUE(i)); - - /* Add to ready list */ - ATOMIC(SCHED_ENQUEUE(proc)); - -#if CONFIG_KERN_MONITOR - monitor_add(proc, name, stack_base, stacksize); -#endif - - return proc; -} - -/** Rename a process */ -void proc_rename(struct Process *proc, const char *name) -{ -#if CONFIG_KERN_MONITOR - monitor_rename(proc, name); -#else - (void)proc; (void)name; -#endif -} - - -/** - * System scheduler: pass CPU control to the next process in - * the ready queue. - * - * Saving and restoring the context on the stack is done - * by a CPU-dependent support routine which must usually be - * written in assembly. - */ -void proc_schedule(void) -{ - struct Process *old_process; - cpuflags_t flags; - - /* Remember old process to save its context later */ - old_process = CurrentProcess; - -#ifdef IRQ_RUNNING - /* Scheduling in interrupts is a nono. */ - ASSERT(!IRQ_RUNNING()); -#endif - - /* Poll on the ready queue for the first ready process */ - IRQ_SAVE_DISABLE(flags); - while (!(CurrentProcess = (struct Process *)list_remHead(&ProcReadyList))) - { - /* - * Make sure we physically reenable interrupts here, no matter what - * the current task status is. This is important because if we - * are idle-spinning, we must allow interrupts, otherwise no - * process will ever wake up. - * - * During idle-spinning, can occur an interrupt, it may be able to - * modify \p ProcReadyList. To ensure that compiler reload this - * variable every while cycle we call CPU_MEMORY_BARRIER. - * The memory barrier ensure that all variables used in this context - * are reloaded. - * \todo If there was a way to write sig_wait() so that it does not - * disable interrupts while waiting, there would not be any - * reason to do this. - */ - IRQ_ENABLE; - CPU_IDLE; - MEMORY_BARRIER; - IRQ_DISABLE; - } - IRQ_RESTORE(flags); - - /* - * Optimization: don't switch contexts when the active - * process has not changed. - */ - if (CurrentProcess != old_process) - { - cpustack_t *dummy; - -#if CONFIG_KERN_PREEMPTIVE - /* Reset quantum for this process */ - Quantum = CONFIG_KERN_QUANTUM; -#endif - - /* Save context of old process and switch to new process. If there is no - * old process, we save the old stack pointer into a dummy variable that - * we ignore. In fact, this happens only when the old process has just - * exited. - * TODO: Instead of physically clearing the process at exit time, a zombie - * list should be created. - */ - asm_switch_context(&CurrentProcess->stack, old_process ? &old_process->stack : &dummy); - } - - /* This RET resumes the execution on the new process */ -} - - -/** - * Terminate the current process - */ -void proc_exit(void) -{ -#if CONFIG_KERN_MONITOR - monitor_remove(CurrentProcess); -#endif - -#if CONFIG_KERN_HEAP - /* - * The following code is BROKEN. - * We are freeing our own stack before entering proc_schedule() - * BAJO: A correct fix would be to rearrange the scheduler with - * an additional parameter which frees the old stack/process - * after a context switch. - */ - if (CurrentProcess->flags & PF_FREESTACK) - heap_free(CurrentProcess->stack_base, CurrentProcess->stack_size); - heap_free(CurrentProcess); -#endif - -#if (ARCH & ARCH_EMUL) -#warning This is wrong - /* Reinsert process stack in free list */ - ADDHEAD(&StackFreeList, (Node *)(CurrentProcess->stack - - (CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)))); - - /* - * NOTE: At this point the first two words of what used - * to be our stack contain a list node. From now on, we - * rely on the compiler not reading/writing the stack. - */ -#endif /* ARCH_EMUL */ - - CurrentProcess = NULL; - proc_schedule(); - /* not reached */ -} - - -/** - * Co-operative context switch - */ -void proc_switch(void) -{ - cpuflags_t flags; - - IRQ_SAVE_DISABLE(flags); - SCHED_ENQUEUE(CurrentProcess); - IRQ_RESTORE(flags); - - proc_schedule(); -} - - -/** - * Get the pointer to the current process - */ -struct Process *proc_current(void) -{ - return CurrentProcess; -} - -/** - * Get the pointer to the user data of the current process - */ -iptr_t proc_current_user_data(void) -{ - return CurrentProcess->user_data; -} - - -#if CONFIG_KERN_PREEMPTIVE - -/** - * Disable preemptive task switching. - * - * The scheduler maintains a per-process nesting counter. Task switching is - * effectively re-enabled only when the number of calls to proc_permit() - * matches the number of calls to proc_forbid(). - * - * Calling functions that could sleep while task switching is disabled - * is dangerous, although supported. Preemptive task switching is - * resumed while the process is sleeping and disabled again as soon as - * it wakes up again. - * - * \sa proc_permit() - */ -void proc_forbid(void) -{ - /* No need to protect against interrupts here. */ - ++CurrentProcess->forbid_cnt; -} - -/** - * Re-enable preemptive task switching. - * - * \sa proc_forbid() - */ -void proc_permit(void) -{ - /* No need to protect against interrupts here. */ - --CurrentProcess->forbid_cnt; -} - -#endif /* CONFIG_KERN_PREEMPTIVE */ diff --git a/kern/proc.h b/kern/proc.h deleted file mode 100644 index cec57487..00000000 --- a/kern/proc.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * \file - * - * - * \brief Process scheduler (public interface). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ -#ifndef KERN_PROC_H -#define KERN_PROC_H - -#include -#include -#include - -/* Fwd decl */ -struct Process; - -/* Task scheduling services */ -void proc_init(void); -struct Process *proc_new_with_name(const char* name, void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack); - -#if !CONFIG_KERN_MONITOR - #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack)) -#else - #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack)) -#endif - -void proc_exit(void); -void proc_switch(void); -void proc_test(void); -struct Process *proc_current(void); -iptr_t proc_current_user_data(void); -void proc_rename(struct Process *proc, const char* name); - -#if CONFIG_KERN_PREEMPTIVE - void proc_forbid(void); - void proc_permit(void); -#else - INLINE void proc_forbid(void) { /* nop */ } - INLINE void proc_permit(void) { /* nop */ } -#endif - -/** - * Execute a block of \a CODE atomically with respect to task scheduling. - */ -#define PROC_ATOMIC(CODE) \ - do { \ - proc_forbid(); \ - CODE; \ - proc_permit(); \ - } while(0) - -#endif /* KERN_PROC_H */ diff --git a/kern/proc_p.h b/kern/proc_p.h deleted file mode 100644 index 8fbb0ed0..00000000 --- a/kern/proc_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * \file - * - * - * \brief Internal scheduler structures and definitions for processes. - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#ifndef KERN_PROC_P_H -#define KERN_PROC_P_H - -#include -#include /* for cpu_stack_t */ -#include -#include -#include - -typedef struct Process -{ - Node link; /**< Link Process into scheduler lists */ - cpustack_t *stack; /**< Per-process SP */ - iptr_t user_data; /**< Custom data passed to the process */ - -#if CONFIG_KERN_SIGNALS - sigmask_t sig_wait; /**< Signals the process is waiting for */ - sigmask_t sig_recv; /**< Received signals */ -#endif - -#if CONFIG_KERN_PREEMPTIVE - int forbid_cnt; /**< Nesting count for proc_forbid()/proc_permit(). */ -#endif - -#if CONFIG_KERN_HEAP - uint16_t flags; /**< Flags */ - cpustack_t *stack_base; /**< Base of process stack */ - size_t stack_size; /**< Size of process stack */ -#endif - -#if CONFIG_KERN_MONITOR - struct ProcMonitor - { - Node link; - const char *name; - cpustack_t *stack_base; - size_t stack_size; - } monitor; -#endif - -} Process; - - -/** - * \name Flags for Process.flags. - * \{ - */ -#define PF_FREESTACK BV(0) /**< Free the stack when process dies */ -/*\}*/ - - -/** Track running processes. */ -extern REGISTER Process *CurrentProcess; - -/** Track ready processes. */ -extern REGISTER List ProcReadyList; - - -/** Enqueue a task in the ready list. */ -#define SCHED_ENQUEUE(proc) ADDTAIL(&ProcReadyList, &(proc)->link) - -/** Schedule to another process *without* adding the current to the ready list. */ -void proc_schedule(void); - -#if CONFIG_KERN_MONITOR - /** Initialize the monitor */ - void monitor_init(void); - - /** Register a process into the monitor */ - void monitor_add(Process *proc, const char *name, cpustack_t *stack, size_t stacksize); - - /** Unregister a process from the monitor */ - void monitor_remove(Process *proc); - - /** Rename a process */ - void monitor_rename(Process *proc, const char* name); -#endif /* CONFIG_KERN_MONITOR */ - -#endif /* KERN_PROC_P_H */ - diff --git a/kern/proc_test.c b/kern/proc_test.c deleted file mode 100644 index 4c2f3126..00000000 --- a/kern/proc_test.c +++ /dev/null @@ -1,58 +0,0 @@ - -#include -#include - -/** - * Proc scheduling test subthread 1 - */ -static void NORETURN proc_test_thread1(void) -{ - for (;;) - { - kputs(">task 1\n"); - timer_delay(50); - proc_switch(); - } -} - -/** - * Proc scheduling test subthread 2 - */ -static void NORETURN proc_test_thread2(void) -{ - for (;;) - { - kputs(">task 2\n"); - timer_delay(75); - proc_switch(); - } -} - -static cpustack_t proc_test_stack1[CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)]; -static cpustack_t proc_test_stack2[CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t)]; - -/** - * Proc scheduling test - */ -void NORETURN proc_test(void) -{ - proc_new(proc_test_thread1, NULL, sizeof(proc_test_stack1), proc_test_stack1); - proc_new(proc_test_thread2, NULL, sizeof(proc_test_stack2), proc_test_stack2); - kputs("Created tasks\n"); - - kputs("stack1:\n"); -// #warning FIXME - kdump(proc_test_stack1+sizeof(proc_test_stack1)-64, 64); - kputs("stack2:\n"); -// #warning FIXME - kdump(proc_test_stack2+sizeof(proc_test_stack1)-64, 64); - - for (;;) - { - kputs(">main task\n"); - timer_delay(93); - proc_switch(); - } - - ASSERT(false); -} diff --git a/kern/sem.c b/kern/sem.c deleted file mode 100644 index 0f31fa06..00000000 --- a/kern/sem.c +++ /dev/null @@ -1,186 +0,0 @@ -/** - * \file - * - * - * \brief Semaphore based synchronization services. - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#include "sem.h" -#include -#include -#include -#include - -INLINE void sem_verify(struct Semaphore *s) -{ - (void)s; - ASSERT(s); - LIST_ASSERT_VALID(&s->wait_queue); - ASSERT(s->nest_count >= 0); - ASSERT(s->nest_count < 128); // heuristic max -} - - -/** - * \brief Initialize a Semaphore structure. - */ -void sem_init(struct Semaphore *s) -{ - LIST_INIT(&s->wait_queue); - s->owner = NULL; - s->nest_count = 0; -} - - -/** - * \brief Attempt to lock a semaphore without waiting. - * - * \return true in case of success, false if the semaphore - * was already locked by someone else. - * - * \note each call to sem_attempt() must be matched by a - * call to sem_release(). - * - * \see sem_obtain() sem_release() - */ -bool sem_attempt(struct Semaphore *s) -{ - bool result = false; - - proc_forbid(); - sem_verify(s); - if ((!s->owner) || (s->owner == CurrentProcess)) - { - s->owner = CurrentProcess; - s->nest_count++; - result = true; - } - proc_permit(); - - return result; -} - - -/** - * \brief Lock a semaphore. - * - * If the semaphore is already owned by another process, the caller - * process will be enqueued into the waiting list and sleep until - * the semaphore is available. - * - * \note Each call to sem_obtain() must be matched by a - * call to sem_release(). - * - * \note This routine is optimized for highest speed in - * the most common case: the semaphore is free or locked - * by the calling process itself. Rearranging this code - * is probably a bad idea. - * - * \sa sem_release() sem_attempt() - */ -void sem_obtain(struct Semaphore *s) -{ - proc_forbid(); - sem_verify(s); - - /* Is the semaphore already locked by another process? */ - if (UNLIKELY(s->owner && (s->owner != CurrentProcess))) - { - /* Append calling process to the wait queue */ - ADDTAIL(&s->wait_queue, (Node *)CurrentProcess); - - /* - * We will wake up only when the current owner calls - * sem_release(). Then, the semaphore will already - * be locked for us. - */ - proc_permit(); - proc_schedule(); - } - else - { - ASSERT(LIST_EMPTY(&s->wait_queue)); - - /* The semaphore was free: lock it */ - s->owner = CurrentProcess; - s->nest_count++; - proc_permit(); - } -} - - -/** - * \brief Release a lock on a previously locked semaphore. - * - * If the nesting count of the semaphore reaches zero, - * the next process waiting for it will be awaken. - * - * \note This routine is optimized for highest speed in - * the most common case: the semaphore has been locked just - * once and nobody else was waiting for it. Rearranging - * this code is probably a bad idea. - * - * \sa sem_obtain() sem_attempt() - */ -void sem_release(struct Semaphore *s) -{ - proc_forbid(); - sem_verify(s); - - ASSERT(s->owner == CurrentProcess); - - /* - * Decrement nesting count and check if the semaphore - * has been fully unlocked. - */ - if (--s->nest_count == 0) - { - Process *proc; - - /* Disown semaphore */ - s->owner = NULL; - - /* Give semaphore to the first applicant, if any */ - if (UNLIKELY((proc = (Process *)list_remHead(&s->wait_queue)))) - { - s->nest_count = 1; - s->owner = proc; - SCHED_ENQUEUE(proc); - } - } - - proc_permit(); -} diff --git a/kern/sem.h b/kern/sem.h deleted file mode 100644 index a80c914f..00000000 --- a/kern/sem.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * \file - * - * - * \brief Mutually exclusive semaphores. - * Shared locking not supported in this implementation. - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - - -#ifndef KERN_SEM_H -#define KERN_SEM_H - -#include -#include - -/* Fwd decl */ -struct Process; - - -typedef struct Semaphore -{ - struct Process *owner; - List wait_queue; - int nest_count; -} Semaphore; - -/** - * \name Process synchronization services - * \{ - */ -void sem_init(struct Semaphore *s); -bool sem_attempt(struct Semaphore *s); -void sem_obtain(struct Semaphore *s); -void sem_release(struct Semaphore *s); -/* \} */ - -#endif /* KERN_SEM_H */ diff --git a/kern/signal.c b/kern/signal.c deleted file mode 100644 index 5abd7062..00000000 --- a/kern/signal.c +++ /dev/null @@ -1,218 +0,0 @@ -/** - * \file - * - * - * \brief IPC signals implementation. - * - * Signals are a low-level IPC primitive. A process receives a signal - * when some external event has happened. Like interrupt requests, - * signals do not carry any additional information. If processing a - * specific event requires additional data, the process must obtain it - * through some other mechanism. - * - * Despite the name, one shouldn't confuse these signals with POSIX - * signals. POSIX signals are usually executed synchronously, like - * software interrupts. - * - * Signals are very low overhead. Using them exclusively to wait - * for multiple asynchronous events results in very simple dispatch - * logic with low processor and resource usage. - * - * The "event" module is a higher-level interface that can optionally - * deliver signals to processes. Messages provide even higher-level - * IPC services built on signals. Semaphore arbitration is also - * implemented using signals. - * - * In this implementation, each process has a limited set of signal - * bits (usually 32) and can wait for multiple signals at the same - * time using sig_wait(). Signals can also be polled using sig_check(), - * but a process spinning on its signals usually defeats their purpose - * of providing a multitasking-friendly infrastructure for event-driven - * applications. - * - * Signals are like flags: they are either active or inactive. After an - * external event has delivered a particular signal, it remains raised until - * the process acknowledges it using either sig_wait() or sig_check(). - * Counting signals is not a reliable way to count how many times a - * particular event has occurred, because the same signal may be - * delivered twice before the process can notice. - * - * Any execution context, including an interrupt handler, can deliver - * a signal to a process using sig_signal(). Multiple independent signals - * may be delivered at once with a single invocation of sig_signal(), - * although this is rarely useful. - * - * \section signal_allocation Signal Allocation - * - * There's no hardcoded mapping of specific events to signal bits. - * The meaning of a particular signal bit is defined by an agreement - * between the delivering entity and the receiving process. - * For instance, a terminal driver may be designed to deliver - * a signal bit called SIG_INT when it reads the CTRL-C sequence - * from the keyboard, and a process may react to it by quitting. - * - * \section sig_single SIG_SINGLE - * - * The SIG_SINGLE bit is reserved as a convenient shortcut in those - * simple scenarios where a process needs to wait on just one event - * synchronously. By using SIG_SINGLE, there's no need to allocate - * a specific signal from the free pool. The constraints for safely - * accessing SIG_SINGLE are: - * - The process MUST sig_wait() exclusively on SIG_SINGLE - * - SIG_SIGNAL MUST NOT be left pending after use (sig_wait() will reset - * it automatically) - * - Do not sleep between starting the asynchronous task that will fire - * SIG_SINGLE, and the call to sig_wait(). - * - Do not call system functions that may implicitly sleep, such as - * timer_delayTickes(). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#include "signal.h" - -#include -#include -#include -#include - - -#if CONFIG_KERN_SIGNALS - -/** - * Check if any of the signals in \a sigs has occurred and clear them. - * \return the signals that have occurred. - */ -sigmask_t sig_check(sigmask_t sigs) -{ - sigmask_t result; - cpuflags_t flags; - - IRQ_SAVE_DISABLE(flags); - result = CurrentProcess->sig_recv & sigs; - CurrentProcess->sig_recv &= ~sigs; - IRQ_RESTORE(flags); - - return result; -} - - -/** - * Sleep until any of the signals in \a sigs occurs. - * \return the signal(s) that have awoken the process. - */ -sigmask_t sig_wait(sigmask_t sigs) -{ - sigmask_t result; - cpuflags_t flags; - - IRQ_SAVE_DISABLE(flags); - - /* Loop until we get at least one of the signals */ - while (!(result = CurrentProcess->sig_recv & sigs)) - { - /* go to sleep and proc_schedule() another process */ - CurrentProcess->sig_wait = sigs; - proc_schedule(); - - /* When we come back here, a signal must be arrived */ - ASSERT(!CurrentProcess->sig_wait); - ASSERT(CurrentProcess->sig_recv); - } - - /* Signals found: clear them and return */ - CurrentProcess->sig_recv &= ~sigs; - - IRQ_RESTORE(flags); - return result; -} - -/** - * Sleep until any of the signals in \a sigs or \a timeout ticks elapse. - * If the timeout elapse a SIG_TIMEOUT is added to the received signal(s). - * \return the signal(s) that have awoken the process. - * \note Caller must check return value to check which signal awoke the process. - */ -sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout) -{ - Timer t; - sigmask_t res; - cpuflags_t flags; - - ASSERT(!sig_check(SIG_TIMEOUT)); - ASSERT(!(sigs & SIG_TIMEOUT)); - /* IRQ are needed to run timer */ - ASSERT(IRQ_ENABLED()); - - timer_set_event_signal(&t, proc_current(), SIG_TIMEOUT); - timer_setDelay(&t, timeout); - timer_add(&t); - res = sig_wait(SIG_TIMEOUT | sigs); - - IRQ_SAVE_DISABLE(flags); - /* Remove timer if sigs occur before timer signal */ - if (!(res & SIG_TIMEOUT) && !sig_check(SIG_TIMEOUT)) - timer_abort(&t); - IRQ_RESTORE(flags); - return res; -} - - -/** - * Send the signals \a sigs to the process \a proc. - * The process will be awoken if it was waiting for any of them. - * - * \note This call is interrupt safe. - */ -void sig_signal(Process *proc, sigmask_t sigs) -{ - cpuflags_t flags; - IRQ_SAVE_DISABLE(flags); - - /* Set the signals */ - proc->sig_recv |= sigs; - - /* Check if process needs to be awoken */ - if (proc->sig_recv & proc->sig_wait) - { - /* Wake up process and enqueue in ready list */ - proc->sig_wait = 0; - SCHED_ENQUEUE(proc); - } - - IRQ_RESTORE(flags); -} - -#endif /* CONFIG_KERN_SIGNALS */ - diff --git a/kern/signal.h b/kern/signal.h deleted file mode 100644 index af3aed6b..00000000 --- a/kern/signal.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * \file - * - * - * \brief Signal module (public interface). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - - -#ifndef KERN_SIGNAL_H -#define KERN_SIGNAL_H - -#include - - -/* Fwd decl */ -struct Process; - -/* Inter-process Communication services */ -sigmask_t sig_check(sigmask_t sigs); -void sig_signal(struct Process *proc, sigmask_t sig); -sigmask_t sig_wait(sigmask_t sigs); -sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout); - - -/** - * \name Signal definitions - * \{ - */ -#define SIG_USER0 BV(0) /**< Free for user usage */ -#define SIG_USER1 BV(1) /**< Free for user usage */ -#define SIG_USER2 BV(2) /**< Free for user usage */ -#define SIG_USER3 BV(3) /**< Free for user usage */ -#define SIG_TIMEOUT BV(4) /**< Reserved for timeout use */ -#define SIG_SYSTEM5 BV(5) /**< Reserved for system use */ -#define SIG_SYSTEM6 BV(6) /**< Reserved for system use */ -#define SIG_SINGLE BV(7) /**< Used to wait for a single event */ -/*\}*/ - -#endif /* KERN_SIGNAL_H */ diff --git a/kern/switch.S b/kern/switch.S deleted file mode 100644 index 93d9b7c7..00000000 --- a/kern/switch.S +++ /dev/null @@ -1,8 +0,0 @@ -#if defined(__i386__) - #include "switch_i386.s" -#elif defined(__x86_64__) - #include "switch_x86_64.s" -#else - #error Unknown CPU -#endif - diff --git a/kern/switch_arm.S b/kern/switch_arm.S deleted file mode 100644 index 531b18a5..00000000 --- a/kern/switch_arm.S +++ /dev/null @@ -1,67 +0,0 @@ -/** - * \file - * - * - * \brief ARM context switch - * - * \version $Id: proc.c 18271 2007-10-11 14:51:31Z batt $ - * - * \author Stefano Fedrigo - * \author Francesco Sacchi - */ - - -/* - * NOTE: At each change of this function affecting proc.c - * (i.e. arguments, data stored in the stack) bump up version - * number in asm_switch_version(). - */ - -/* void asm_switch_context(void **new_sp, void **save_sp) */ -.globl asm_switch_context -asm_switch_context: - mrs r2, cpsr /* Save status. */ - stmfd sp!, {r2, r4-r11, lr} /* Save registers. */ - - str sp, [r1] /* Save old stack pointer. */ - ldr sp, [r0] /* Load new stack pointer */ - - ldmfd sp!, {r2, r4-r11, lr} /* Load new registers. */ - msr cpsr, r2 /* restore flags reg. */ - - mov pc, lr - - -/* int asm_switch_version(void) */ -.globl asm_switch_version -asm_switch_version: - mov r0, #1 - mov pc, lr diff --git a/kern/switch_avr.S b/kern/switch_avr.S deleted file mode 100644 index 93892919..00000000 --- a/kern/switch_avr.S +++ /dev/null @@ -1,135 +0,0 @@ -/*! - * \file - * - * - * \brief AVR context switch - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#include - -/* - * NOTE: At each change of this function affecting proc.c - * (i.e. arguments, data stored in the stack) bump up version - * number in asm_switch_version(). - */ - -/* void asm_switch_context(void **new_sp, void **save_sp) */ -.globl asm_switch_context -asm_switch_context: - -; r0 is the TEMP REG and can be used freely. -; r1 is the ZERO REG and must always contain 0. -; -; Stack frame is 19 byte, remember to update -; CPU_SAVED_REGS_CNT if you change pushed regs. - - in r0,SREG-__SFR_OFFSET - push r0 -; push r1 ;zero-reg - push r2 - push r3 - push r4 - push r5 - push r6 - push r7 - push r8 - push r9 - push r10 - push r11 - push r12 - push r13 - push r14 - push r15 - push r16 - push r17 -; push r18 ;caller-save -; push r19 ;caller-save -; push r20 ;caller-save -; push r21 ;caller-save -; push r22 ;caller-save -; push r23 ;caller-save -; push r24 ;caller-save -; push r25 ;caller-save -; push r26 ;caller-save -; push r27 ;caller-save - push r28 - push r29 -; push r30 ;caller-save -; push r31 ;caller-save - -; First parameter (new_sp) is in r24:r25, second (save_sp) in r22:r23 - - in r18,SPL-__SFR_OFFSET ; r18:r19 = SP - in r19,SPH-__SFR_OFFSET - movw r26,r22 ; X = save_sp - st X+,r18 ; *save_sp = SP - st X,r19 - movw r26,r24 ; X = new_sp - ld r18,X+ - ld r19,X - -; Set new stack pointer. -; AVR is an 8 bit processor so -; care must be taken when updating -; SP that is a 16 bit reg. -; Two instructions are required to update SP -; so an IRQ can sneak in between them. -; So IRQ *MUST* be disabled and then restored. - cli ; Disable interrupt - out SPL-__SFR_OFFSET,r18 ; SP = *new_sp - out SPH-__SFR_OFFSET,r19 - out SREG-__SFR_OFFSET,r0 ; Restore previous IRQ state - -; pop r31 ;caller-save -; pop r30 ;caller-save - pop r29 - pop r28 -; pop r27 ;caller-save -; pop r26 ;caller-save -; pop r25 ;caller-save -; pop r24 ;caller-save -; pop r23 ;caller-save -; pop r22 ;caller-save -; pop r21 ;caller-save -; pop r20 ;caller-save -; pop r19 ;caller-save -; pop r18 ;caller-save - pop r17 - pop r16 - pop r15 - pop r14 - pop r13 - pop r12 - pop r11 - pop r10 - pop r9 - pop r8 - pop r7 - pop r6 - pop r5 - pop r4 - pop r3 - pop r2 -; pop r1 ;zero-reg - pop r0 - out SREG-__SFR_OFFSET,r0 - - ret - - -/* int asm_switch_version(void) */ -.globl asm_switch_version -asm_switch_version: - ldi r24,lo8(1) - ldi r25,hi8(1) - ret - diff --git a/kern/switch_dsp56k.c b/kern/switch_dsp56k.c deleted file mode 100644 index 41a12056..00000000 --- a/kern/switch_dsp56k.c +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Giovanni Bajo - * - * \brief DSP5680x task switching support - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/02/24 01:17:05 bernie - *#* Update for new emulator. - *#* - *#* Revision 1.5 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.4 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.3 2004/07/30 14:24:16 rasky - *#* Task switching con salvataggio perfetto stato di interrupt (SR) - *#* Kernel monitor per dump informazioni su stack dei processi - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 17:27:00 bernie - *#* Import kern/ subdirectory. - *#* - *#*/ - -void asm_switch_context(void ** new_sp/*R2*/, void ** save_sp/*R3*/); -asm void asm_switch_context(void ** new_sp, void ** save_sp) -{ - lea (SP)+ - - ; From the manual: - ; The compiler uses page 0 address locations X: 0x0030 - 0x003F as register - ; variables. Frequently accessed local variables are assigned to the page 0 - ; registers instead of to stack locations so that load and store instructions - ; are shortened. Addresses X: 0x0030 - 0x0037 (page 0 registers MR0-MR7) are - ; volatile registers and can be overwritten. The remaining registers (page 0 - ; registers MR8-MR15) are treated as non-volatile and, if used by a routine, - ; must be saved on entry and restored on exit. - ; - ; So, register 0x30-0x37 are caller-save, while 0x38-0x3F are callee-save. - move x:<$38,y1 - move y1,x:(SP)+ - move x:<$39,y1 - move y1,x:(SP)+ - move x:<$3A,y1 - move y1,x:(SP)+ - move x:<$3B,y1 - move y1,x:(SP)+ - move x:<$3C,y1 - move y1,x:(SP)+ - move x:<$3D,y1 - move y1,x:(SP)+ - move x:<$3E,y1 - move y1,x:(SP)+ - move x:<$3F,y1 - move y1,x:(SP) - - ; - ; Switch stacks - nop - move SP, x:(R3) - nop - move x:(R2), SP - nop - - ; - ; restore all saved registers - ; - pop y1 - move y1,x:<$3F - pop y1 - move y1,x:<$3E - pop y1 - move y1,x:<$3D - pop y1 - move y1,x:<$3C - pop y1 - move y1,x:<$3B - pop y1 - move y1,x:<$3A - pop y1 - move y1,x:<$39 - pop y1 - move y1,x:<$38 - - ; SR is already pushed on the stack (normal call context). Use RTI to restore - ; it, so that interrupt status is preserved across the tasks. - rti -} - -int asm_switch_version(void); -int asm_switch_version(void) -{ - return 1; -} diff --git a/kern/switch_i196.s32 b/kern/switch_i196.s32 deleted file mode 100644 index a2f3c70d..00000000 --- a/kern/switch_i196.s32 +++ /dev/null @@ -1,92 +0,0 @@ -;* Copyright 2004 Develer S.r.l. (http://www.develer.com/) -;* Copyright 1999,2000,2001 Bernardo Innocenti -;* This file is part of DevLib - See devlib/README for information. -;* -;* \version $Id$ -;* -;* \author Bernardo Innocenti -;* - -;* $Log$ -;* Revision 1.2 2004/06/06 16:14:12 bernie -;* Add DevLib license information. -;* -;* Revision 1.1 2004/05/23 17:27:00 bernie -;* Import kern/ subdirectory. -;* -;* - -!!!!!! THIS FILE HAS NOT BEEN REVISED FOR THE NEW SCHEDULER API !!!!!! - - - - NAME AsmSwitch - RSEG CODE - - EXTERN ?LR - EXTERN ?GR - PUBLIC AsmSwitchContext - PUBLIC AsmReplaceContext - - -;* Perform low-level process context switching -;* -;* void AsmSwitchContext(cpustack_t *new_sp, cpustack_t **save_sp) -;* GR+0 SP+2 -;* -;* Replace current context with new process -;* -;* void AsmReplaceContext(cpustack_t *new_sp, cpustack_t **dummy) -;* GR+0 SP+2 -;* - -AsmSwitchContext: - -; pop 2nd parameter from the stack - ld ?GR+2,2[SP] - -; save all registers - push ?LR+0 - push ?LR+2 - push ?LR+4 - push ?LR+6 - push ?LR+8 - push ?LR+10 - push ?LR+12 - push ?LR+14 - push ?LR+16 - push ?LR+18 - push ?LR+20 - push ?LR+22 - push ?LR+24 - push ?LR+26 - push ?LR+28 - push ?LR+30 - st SP,[?GR+2] ; save old stack pointer - ; fall-thru - -AsmReplaceContext: - ld SP,?GR+0 ; load new stack pointer - -; restore all registers - pop ?LR+30 - pop ?LR+28 - pop ?LR+26 - pop ?LR+24 - pop ?LR+22 - pop ?LR+20 - pop ?LR+18 - pop ?LR+16 - pop ?LR+14 - pop ?LR+12 - pop ?LR+10 - pop ?LR+8 - pop ?LR+6 - pop ?LR+4 - pop ?LR+2 - pop ?LR+0 - -; restore execution in new context - ret - - END diff --git a/kern/switch_i386.s b/kern/switch_i386.s deleted file mode 100644 index 6931d45c..00000000 --- a/kern/switch_i386.s +++ /dev/null @@ -1,44 +0,0 @@ -/*! - * \file - * - * - * \brief i386 context switch - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -/* void asm_switch_context(void ** new_sp, void ** save_sp) */ -.globl asm_switch_context -asm_switch_context: - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushl %esi - pushl %edi - pushl %ebp - movl 0x24(%esp),%ebp /* ebp = save_sp */ - movl %esp,(%ebp) /* *save_sp = esp */ - movl 0x20(%esp),%ebp /* ebp = new_sp */ - movl (%ebp),%esp /* esp = *new_sp */ - popl %ebp - popl %edi - popl %esi - popl %edx - popl %ecx - popl %ebx - popl %eax - ret - -/* int asm_switch_version(void) */ -.globl asm_switch_version -asm_switch_version: - mov $1,%eax - ret - diff --git a/kern/switch_win32.s b/kern/switch_win32.s deleted file mode 100644 index 5891ae90..00000000 --- a/kern/switch_win32.s +++ /dev/null @@ -1,58 +0,0 @@ -/*! - * \file - * - * - * \brief i386 context switch for WIN32 - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -!!!!!! THIS FILE HAS NOT BEEN REVISED FOR THE NEW SCHEDULER API !!!!!! - -__declspec(naked) void AsmSwitchContext(void * new_sp, void ** save_sp) -{ - __asm - { - push eax - push ebx - push ecx - push edx - push esi - push edi - push ebp - mov ebp,dword ptr [esp+24h] ; ebp <- save_sp - mov dword ptr [ebp],esp ; *save_sp = esp - mov esp,dword ptr [esp+20h] ; new_sp - pop ebp - pop edi - pop esi - pop edx - pop ecx - pop ebx - pop eax - ret - } -} - -__declspec(naked) void AsmReplaceContext(void * new_sp, void ** dummy) -{ - __asm - { - mov esp,dword ptr [esp + 4] ; new_sp - pop ebp - pop edi - pop esi - pop edx - pop ecx - pop ebx - pop eax - ret - } -} - diff --git a/kern/switch_x86_64.s b/kern/switch_x86_64.s deleted file mode 100644 index 5fb4da65..00000000 --- a/kern/switch_x86_64.s +++ /dev/null @@ -1,71 +0,0 @@ -/*! - * \file - * - * - * \brief i386 context switch - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -/* - * $Log$ - * Revision 1.4 2006/09/20 14:02:49 marco - * C-style comment. - * - * Revision 1.3 2006/02/24 01:35:40 bernie - * Update for new emulator. - * - * Revision 1.2 2006/02/24 01:17:05 bernie - * Update for new emulator. - * - * Revision 1.1 2005/11/27 03:06:15 bernie - * Add x86_64 task switching (to be updated to new-style scheduler). - * - * Revision 1.1 2005/11/14 21:06:38 bernie - * Add x86_64 support. - * - * Revision 1.2 2004/06/06 16:14:12 bernie - * Add DevLib license information. - * - * Revision 1.1 2004/05/23 17:27:00 bernie - * Import kern/ subdirectory. - * - */ - -/* I know it's ugly... */ -/* .intel_syntax */ - -/* void AsmSwitchContext(void **new_sp, void **save_sp) */ -/* %rdi %rsi */ -.globl asm_switch_context -asm_switch_context: - pushq %rax - pushq %rbx - pushq %rcx - pushq %rdx - pushq %rsi - pushq %rdi - pushq %rbp - movq %rsp,(%rsi) /* *save_sp = rsp */ - movq (%rdi),%rsp /* rsp = *new_sp */ - popq %rbp - popq %rdi - popq %rsi - popq %rdx - popq %rcx - popq %rbx - popq %rax - ret - -/* int asm_switch_version(void) */ -.globl asm_switch_version -asm_switch_version: - mov $1,%rax - ret - diff --git a/mware/blanker.c b/mware/blanker.c deleted file mode 100644 index 5cf5247e..00000000 --- a/mware/blanker.c +++ /dev/null @@ -1,222 +0,0 @@ -/** - * \file - * - * - * \brief Display Blanker (implementation). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#include "blanker.h" -#include -#include - -/* Time without input events before starting blanker */ -#define BLK_BLANKTIMEOUT (15 * 1000) /* ms */ - -// TODO: move to blanker_hw.h -#include -#define BLK_LCDON power_LcdOn() -#define BLK_LCDOFF power_LcdOff() - - -/** Keyboard event handler to listen for key presses in blanker. */ -static KbdHandler blk_KbdHandler; - -/** Time since last key event. */ -static ticks_t blk_lastevent; - -/** Display blanking function is enabled. */ -static bool blk_enabled; - -/** Display blanker is engaged right now. */ -static bool blk_active; - - -static bool blk_on(void) -{ - if (!blk_active) - { - blk_active = true; - BLK_LCDOFF; - } - return true; -} - - -static void blk_off(void) -{ - if (blk_active) - { - blk_active = false; - BLK_LCDON; - } -} - - -void blk_retrigger(void) -{ - blk_lastevent = timer_clock(); - blk_off(); -} - -#if 0 -/** - * Matrix-like screen saver effect - */ -static void blk_hack(void) -{ - static signed char blk_colstart[LCD_COLS]; - UBYTE row, col; - - - if (rand()%3 == 0) - { - /* Modify one column */ - col = rand() % LCD_COLS; - blk_colstart[col] += rand() % 12 - 5; - } - - for (col = 0; col < LCD_COLS; ++col) - { - if (blk_colstart[col] > 0) - { - --blk_colstart[col]; - - /* Scroll down */ - for(row = LCD_ROWS-1; row; --row) - { - lcd_SetAddr(blk_layer, LCD_POS(col,row)); - lcd_PutChar(blk_layer->Buf[LCD_POS(col,row-1)], blk_layer); - } - - /* Add new kanji */ - lcd_SetAddr(blk_layer, LCD_POS(col,0)); - lcd_PutChar((char)(rand() % 127 + 128), blk_layer); - } - else if (blk_colstart[col] < 0) - { - ++blk_colstart[col]; - - /* Clear tail */ - for(row = 0; row < LCD_ROWS; ++row) - { - if (blk_layer->Buf[LCD_POS(col,row)] != ' ') - { - lcd_SetAddr(blk_layer, LCD_POS(col,row)); - lcd_PutChar(' ', blk_layer); - break; - } - } - } - } -} -#endif - - -static keymask_t blk_handlerFunc(keymask_t key) -{ - /* key used to turn off blanker */ - static keymask_t offkey; - - ticks_t now = timer_clock(); - - /* If key pressed */ - if (key != 0) - { - blk_lastevent = now; - if (blk_active) - { - blk_off(); - - /* remember and eat key event */ - offkey = key; - key = 0; - } - else if (key == offkey) - { - /* keep eating the key until released */ - key = 0; - } - - /* pass key through */ - return key; - } - - /* reset off key */ - offkey = 0; - - /* Blank timeout reached? */ - if (now - blk_lastevent > ms_to_ticks(BLK_BLANKTIMEOUT)) - { - /* Enable blanker unless already done */ - if (!blk_active && !blk_on()) - return 0; - -#if 0 - /* Do some nice visual effect */ - blk_hack(); -#endif /* _DEBUG */ - } - - return 0; -} - - -void blk_enable(void) -{ - if (!blk_enabled) - { - blk_active = false; - blk_lastevent = timer_clock(); - - /* Add display blanker handler */ - blk_KbdHandler.hook = blk_handlerFunc; - blk_KbdHandler.pri = 100; /* high priority */ - blk_KbdHandler.flags = KHF_RAWKEYS; - kbd_addHandler(&blk_KbdHandler); - - blk_enabled = true; - } -} - - -void blk_disable(void) -{ - if (blk_enabled) - { - kbd_remHandler(&blk_KbdHandler); - blk_off(); - blk_enabled = false; - } -} diff --git a/mware/blanker.h b/mware/blanker.h deleted file mode 100644 index bdcdc679..00000000 --- a/mware/blanker.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * \file - * - * - * \brief Display Blanker (implementation). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ -#ifndef MWARE_BLANKER_H -#define MWARE_BLANKER_H - -extern void blk_enable(void); -extern void blk_disable(void); -extern void blk_retrigger(void); - -#endif /* MWARE_BLANKER_H */ diff --git a/mware/byteorder.h b/mware/byteorder.h deleted file mode 100644 index 0ed874bb..00000000 --- a/mware/byteorder.h +++ /dev/null @@ -1,269 +0,0 @@ -/** - * \file - * - * - * \brief Functions to convert integers to/from host byte-order. - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -#ifndef MWARE_BYTEORDER_H -#define MWARE_BYTEORDER_H - -#include -#include - -/** - * Swap upper and lower bytes in a 16-bit value. - */ -INLINE uint16_t swab16(uint16_t x) -{ - return ((x & (uint16_t)0x00FFU) << 8) - | ((x & (uint16_t)0xFF00U) >> 8); -} - -/** - * Reverse bytes in a 32-bit value (e.g.: 0x12345678 -> 0x78563412). - */ -INLINE uint32_t swab32(uint32_t x) -{ - return ((x & (uint32_t)0x000000FFUL) << 24) - | ((x & (uint32_t)0x0000FF00UL) << 8) - | ((x & (uint32_t)0x00FF0000UL) >> 8) - | ((x & (uint32_t)0xFF000000UL) >> 24); -} - -/** - * Reverse bytes in a 64-bit value. - */ -INLINE uint64_t swab64(uint64_t x) -{ - return (uint64_t)swab32(x >> 32) - | ((uint64_t)swab32(x & 0xFFFFFFFFUL) << 32); -} - -/** - * Reverse bytes in a float value. - */ -INLINE float swab_float(float x) -{ - /* Avoid breaking strict aliasing rules. */ - char *cx = (char *)(&x); - STATIC_ASSERT(sizeof(float) == 4); - #define BYTEORDER_SWAP(a, b) ((a) ^= (b) ^= (a) ^= (b)) - BYTEORDER_SWAP(cx[0], cx[3]); - BYTEORDER_SWAP(cx[1], cx[2]); - #undef BYTEORDER_SWAP - return x; -} - -INLINE uint16_t cpu_to_be16(uint16_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab16(x) : x; -} - -INLINE uint16_t cpu_to_le16(uint16_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab16(x) : x; -} - -INLINE uint32_t cpu_to_be32(uint32_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab32(x) : x; -} - -INLINE uint32_t cpu_to_le32(uint32_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab32(x) : x; -} - -INLINE uint64_t cpu_to_be64(uint64_t x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab64(x) : x; -} - -INLINE uint64_t cpu_to_le64(uint64_t x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab64(x) : x; -} - -INLINE float cpu_to_be_float(float x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab_float(x) : x; -} - -INLINE float cpu_to_le_float(float x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab_float(x) : x; -} - -INLINE uint16_t be16_to_cpu(uint16_t x) -{ - return cpu_to_be16(x); -} - -INLINE uint16_t le16_to_cpu(uint16_t x) -{ - return cpu_to_le16(x); -} - -INLINE uint32_t be32_to_cpu(uint32_t x) -{ - return cpu_to_be32(x); -} - -INLINE uint32_t le32_to_cpu(uint32_t x) -{ - return cpu_to_le32(x); -} - -INLINE uint64_t be64_to_cpu(uint64_t x) -{ - return cpu_to_be64(x); -} - -INLINE uint64_t le64_to_cpu(uint64_t x) -{ - return cpu_to_le64(x); -} - -INLINE float be_float_to_cpu(float x) -{ - return cpu_to_be_float(x); -} - -INLINE float le_float_to_cpu(float x) -{ - return cpu_to_le_float(x); -} - -INLINE uint16_t host_to_net16(uint16_t x) -{ - return cpu_to_be16(x); -} - -INLINE uint16_t net_to_host16(uint16_t x) -{ - return be16_to_cpu(x); -} - -INLINE uint32_t host_to_net32(uint32_t x) -{ - return cpu_to_be32(x); -} - -INLINE uint32_t net_to_host32(uint32_t x) -{ - return be32_to_cpu(x); -} - -INLINE uint64_t host_to_net64(uint64_t x) -{ - return cpu_to_be64(x); -} - -INLINE uint64_t net_to_host64(uint64_t x) -{ - return be64_to_cpu(x); -} - -INLINE float host_to_net_float(float x) -{ - return cpu_to_be_float(x); -} - -INLINE float net_to_host_float(float x) -{ - return be_float_to_cpu(x); -} - -#ifdef __cplusplus - -/// Type generic byte swapping. -template -INLINE T swab(T x); - -template<> INLINE uint16_t swab(uint16_t x) { return swab16(x); } -template<> INLINE uint32_t swab(uint32_t x) { return swab32(x); } -template<> INLINE uint64_t swab(uint64_t x) { return swab64(x); } -template<> INLINE int16_t swab(int16_t x) { return static_cast(swab16(static_cast(x))); } -template<> INLINE int32_t swab(int32_t x) { return static_cast(swab32(static_cast(x))); } -template<> INLINE int64_t swab(int64_t x) { return static_cast(swab64(static_cast(x))); } -template<> INLINE float swab(float x) { return swab_float(x); } - -/// Type generic conversion from CPU byte order to big-endian byte order. -template -INLINE T cpu_to_be(T x) -{ - return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab(x) : x; -} - -/// Type generic conversion from CPU byte-order to little-endian. -template -INLINE T cpu_to_le(T x) -{ - return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab(x) : x; -} - -/// Type generic conversion from big endian byte-order to CPU byte order. -template -INLINE T be_to_cpu(T x) -{ - return cpu_to_be(x); -} - -/// Type generic conversion from little-endian byte order to CPU byte order. -template -INLINE T le_to_cpu(T x) -{ - return cpu_to_le(x); -} - -/// Type generic conversion from network byte order to host byte order. -template -INLINE T net_to_host(T x) -{ - return be_to_cpu(x); -} - -/// Type generic conversion from host byte order to network byte order. -template -INLINE T host_to_net(T x) -{ - return net_to_host(x); -} - -#endif /* __cplusplus */ - -#endif /* MWARE_BYTEORDER_H */ diff --git a/mware/cmd_hunk.h b/mware/cmd_hunk.h deleted file mode 100644 index a3dfff79..00000000 --- a/mware/cmd_hunk.h +++ /dev/null @@ -1,180 +0,0 @@ -/** - * \file - * - * This module permits to create hunks for the functions that must be executed through - * RPC commands. For instance, given this code: - * - * \code - * ResultCode cmd_add(long a, long b, long* result); - * DECLARE_COMMAND_HUNK(add, (long)(long)(NIL), (long)(NIL)); - * // ^ parameters ^ return values - * \endcode - * - * The macro is expanded to: - * - * \code - * ResultCode cmd_add_hunk(params argv[], params results[]) - * { - * return cmd_add(argv[0].l, argv[1].l, &results[0].l); - * } - * - * const struct CmdTemplate cmd_add_template = - * { - * "add", "dd", "d", cmd_add_hunk - * }; - * \endcode - * - * which is all the boilerplate needed to make the function ready for the RPC. - * The implementation uses the Boost Preprocessor Library (part of the Boost - * library, available at http://www.boost.org). The version we developed the - * code with is 1.31. - * - * \version $Id$ - * - * \author Giovanni Bajo - * - * \brief Preprocessor magic to create hunks for the commands executed from the parser - * - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2006/06/01 12:27:39 marco - *#* Added utilities for protocols - *#* - *#* Revision 1.8 2005/01/12 20:06:31 rasky - *#* enum ResultCode è ora un typedef - *#* - *#* Revision 1.7 2004/12/14 15:10:53 user1 - *#* Bernardo e Francesco: Assegnazione di un codice di ritorno ai processi - *#* - *#* Revision 1.6 2004/12/02 17:43:15 rasky - *#* Aggiunta la possibilità di settare le flag dei comandi con la nuova macro DECLARE_CMD_HUNK_FLAGS (altrimenti, il default è zero) - *#* - *#* Revision 1.5 2004/10/16 13:20:15 rasky - *#* Aggiunto supporto per alias di uno stesso comando - *#* - *#* Revision 1.4 2004/08/25 14:17:10 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.3 2004/07/31 22:00:07 rasky - *#* Fixata una dipendenza - *#* - *#* Revision 1.2 2004/07/31 14:32:58 rasky - *#* args e results possono overlapparsi sempre grazie ai thunk generati: eliminati i due array separati per risparmiare memoria - *#* - *#* Revision 1.1 2004/05/22 16:29:16 rasky - *#* Generazione degli hunk dei comandi RPC tramite preprocessore - *#* - *#*/ - -#ifndef CMD_HUNK_H -#define CMD_HUNK_H - -#include "parser.h" - -// Bring in the Boost Preprocess Library -#include - -#define HUNK_INDEX_FOR_NIL 0 -#define HUNK_INDEX_FOR_string 1 -#define HUNK_INDEX_FOR_long 2 -#define HUNK_ARRAY_LETTERS (3, (NIL, s, l)) -#define HUNK_ARRAY_STRINGS (3, ("", "s", "d")) - -// Transform int->l, float->f, etc. -#define HUNK_TYPE_LETTER(s, _, type) \ - BOOST_PP_CAT(HUNK_INDEX_FOR_, type) \ - /**/ - -#define HUNK_TRANSFORMER(_, array, elem) \ - BOOST_PP_ARRAY_ELEM(elem, array) \ - /**/ - -#define HUNK_SEQ_TRANS_ARRAY(seq, array) \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TRANSFORMER, array, seq) \ - /**/ - -#define HUNK_PARAM(_, n, seq) \ - args_results[n+1]. BOOST_PP_SEQ_ELEM(n, seq) \ - /**/ - -#define HUNK_RESULT(_, n, seq) \ - &args_results[n]. BOOST_PP_SEQ_ELEM(n, seq) \ - /**/ - -#define HUNK_IDENTITY(_, dummy, x) x -#define CMD_HUNK_TEMPLATE(func) cmd_##func###_template - -#define DECLARE_CMD_HUNK_2(func, name, param_types, result_types, flags) \ - static ResultCode cmd_##name##_hunk(parms args_results[]) \ - { \ - return cmd_##func( \ - BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)), HUNK_PARAM, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_LETTERS)) \ - BOOST_PP_COMMA_IF(BOOST_PP_AND(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(param_types)), BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)))) \ - BOOST_PP_ENUM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(result_types)), HUNK_RESULT, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_LETTERS)) \ - ); \ - } \ - const struct CmdTemplate CMD_HUNK_TEMPLATE(name) = { \ - #name, \ - BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(param_types, HUNK_ARRAY_STRINGS)), \ - BOOST_PP_SEQ_FOR_EACH(HUNK_IDENTITY, _, HUNK_SEQ_TRANS_ARRAY(result_types, HUNK_ARRAY_STRINGS)), \ - cmd_##name##_hunk, \ - flags \ - } \ - /**/ - -#define DECLARE_CMD_HUNK(func, param_types, result_types) \ - DECLARE_CMD_HUNK_2(func, func, \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ - 0) \ - /**/ - -#define DECLARE_CMD_HUNK_NAME(func, name, param_types, result_types) \ - DECLARE_CMD_HUNK_2(func, name, \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ - 0) \ - /**/ - -#define DECLARE_CMD_HUNK_FLAGS(func, param_types, result_types, flags) \ - DECLARE_CMD_HUNK_2(func, func, \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, param_types), \ - BOOST_PP_SEQ_TRANSFORM(HUNK_TYPE_LETTER, _, result_types), \ - flags) \ - /**/ - -#endif diff --git a/mware/event.c b/mware/event.c deleted file mode 100644 index a0419fbf..00000000 --- a/mware/event.c +++ /dev/null @@ -1,57 +0,0 @@ -/** - * \file - * - * - * \brief Events handling implementation - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - - -#include "event.h" - -void event_hook_ignore(UNUSED_ARG(Event *, e)) -{ -} - -#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS -void event_hook_signal(Event *e) -{ - sig_signal((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit); -} -#endif - -void event_hook_softint(Event *e) -{ - e->Ev.Int.func(e->Ev.Int.user_data); -} diff --git a/mware/event.h b/mware/event.h deleted file mode 100644 index 4270e946..00000000 --- a/mware/event.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * \file - * - * - * \brief Events handling - * - * This module implements a common system for executing - * a user defined action calling a hook function. - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#ifndef KERN_EVENT_H -#define KERN_EVENT_H - -#include -#include - -#if CONFIG_KERNEL - #include - #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS - #include - #endif - - /* Forward decl */ - struct Process; -#endif - - -/// User defined callback type -typedef void (*Hook)(void *); - -typedef struct Event -{ - void (*action)(struct Event *); - union - { -#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS - struct - { - struct Process *sig_proc; /* Process to be signalled */ - sigbit_t sig_bit; /* Signal to send */ - } Sig; -#endif - struct - { - Hook func; /* Pointer to softint hook */ - void *user_data; /* Data to be passed back to user hook */ - } Int; - } Ev; -} Event; - -void event_hook_ignore(Event *event); -void event_hook_signal(Event *event); -void event_hook_softint(Event *event); - -/** Initialize the event \a e as a no-op */ -#define event_initNone(e) \ - ((e)->action = event_hook_ignore) - -/** Same as event_initNone(), but returns the initialized event */ -INLINE Event event_createNone(void); -INLINE Event event_createNone(void) -{ - Event e; - e.action = event_hook_ignore; - return e; -} - -/** Initialize the event \a e with a software interrupt (call function \a f, with parameter \a u) */ -#define event_initSoftInt(e,f,u) \ - ((e)->action = event_hook_softint,(e)->Ev.Int.func = (f), (e)->Ev.Int.user_data = (u)) - -/** Same as event_initSoftInt(), but returns the initialized event */ -INLINE Event event_createSoftInt(Hook func, void *user_data) -{ - Event e; - e.action = event_hook_softint; - e.Ev.Int.func = func; - e.Ev.Int.user_data = user_data; - return e; -} - - -#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS - -/** Initialize the event \a e with a signal (send signal \a s to process \a p) */ -#define event_initSignal(e,p,s) \ - ((e)->action = event_hook_signal,(e)->Ev.Sig.sig_proc = (p), (e)->Ev.Sig.sig_bit = (s)) - -/** Same as event_initSignal(), but returns the initialized event */ -INLINE Event event_createSignal(struct Process *proc, sigbit_t bit) -{ - Event e; - e.action = event_hook_signal; - e.Ev.Sig.sig_proc = proc; - e.Ev.Sig.sig_bit = bit; - return e; -} - -#endif - -/** Trigger an event */ -INLINE void event_do(struct Event *e) -{ - e->action(e); -} - -#endif /* KERN_EVENT_H */ diff --git a/mware/except.h b/mware/except.h deleted file mode 100644 index b78435de..00000000 --- a/mware/except.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * \file - * - * - * \brief C++-like structured exception handling for C programs - * - * \version $Id$ - * \author Bernardo Innocenti - */ -#ifndef MWARE_EXCEPT_H -#define MWARE_EXCEPT_H - -#include - -#include - -#define EXCEPT_CONTEXTS 8 - -/** - * A stack of jump buffers used to record try sites - * so they can be reached from throw sites. - * - * The stack contains return points for each nested - * context. jmp_buf's are pushed into the stack at - * try points and popped out when the try block ends - * normally or when an exception is thrown. - */ -extern jmp_buf except_stack[EXCEPT_CONTEXTS]; -extern int except_top; - -#define PUSH_EXCEPT (ASSERT(except_top < EXCEPT_CONTEXTS), setjmp(except_stack[except_top++])) -#define POP_EXCEPT (ASSERT(except_top > 0), --except_top) -#define DO_EXCEPT (ASSERT(except_top > 0), longjmp(except_stack[--except_top], true)) - -/** - * Jump buffer to use when throwing an exception or aborting an operation - * - * User code can throw exceptions like this: - * - * \code - * void a_function_throwing_exceptions(void) - * { - * if (some_error_condition) - * THROW; - * } - * \endcode - * - * Catching exceptions (brackets are optional): - * - * \code - * EXCEPT_DEFINE; - * - * void a_function_catching_an_exception(void) - * { - * TRY - * { - * printf("Entered try block\n"); - * a_function_throwing_exceptions(); - * printf("Survived execution of critical code\n"); - * } - * CATCH - * { - * printf("Exception caught!\n"); - * } - * CATCH_END - * } - * \endcode - * - * Simple syntax when you don't need to do anything when catching an excaption: - * - * \code - * TRY - * printf("Entered try block\n"); - * a_function_throwing_exceptions(); - * printf("Survived execution of critical code\n"); - * TRY_END - * \endcode - * - * You also need to declare the exception stack once in - * your global declarations: - * \code - * EXCEPT_DEFINE; - * \endcode - */ -#define TRY if (PUSH_EXCEPT) { { -#define TRY_END } POP_EXCEPT; } -#define CATCH } POP_EXCEPT; } else { -#define CATCH_END } -#define THROW DO_EXCEPT - - -#define EXCEPT_DEFINE \ - jmp_buf except_stack[EXCEPT_CONTEXTS]; \ - int except_top; - -#endif /* MWARE_EXCEPT_H */ diff --git a/mware/fifobuf.h b/mware/fifobuf.h deleted file mode 100644 index cb634ee3..00000000 --- a/mware/fifobuf.h +++ /dev/null @@ -1,353 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief General pourpose FIFO buffer implemented with a ring buffer - * - * \li \c begin points to the first buffer element; - * \li \c end points to the last buffer element (unlike the STL convention); - * \li \c head points to the element to be extracted next; - * \li \c tail points to the location following the last insertion; - * \li when any of the pointers advances beyond \c end, it is reset - * back to \c begin. - * - * \code - * - * +-----------------------------------+ - * | empty | valid data | empty | - * +-----------------------------------+ - * ^ ^ ^ ^ - * begin head tail end - * - * \endcode - * - * The buffer is EMPTY when \c head and \c tail point to the same location: - * \code head == tail \endcode - * - * The buffer is FULL when \c tail points to the location immediately - * after \c head: - * \code tail == head - 1 \endcode - * - * The buffer is also FULL when \c tail points to the last buffer - * location and head points to the first one: - * \code head == begin && tail == end \endcode - */ - -#ifndef MWARE_FIFO_H -#define MWARE_FIFO_H - -#include -#include -#include - -typedef struct FIFOBuffer -{ - unsigned char * volatile head; - unsigned char * volatile tail; - unsigned char *begin; - unsigned char *end; -} FIFOBuffer; - - -#define ASSERT_VALID_FIFO(fifo) \ - ATOMIC( \ - ASSERT((fifo)->head >= (fifo)->begin); \ - ASSERT((fifo)->head <= (fifo)->end); \ - ASSERT((fifo)->tail >= (fifo)->begin); \ - ASSERT((fifo)->tail <= (fifo)->end); \ - ) - - -/** - * 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 - * (which the AVR and other 8-bit processors can't do). - * - * \sa fifo_isempty_locked - */ -INLINE bool fifo_isempty(const FIFOBuffer *fb) -{ - //ASSERT_VALID_FIFO(fb); - return 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. - */ -INLINE bool fifo_isfull(const FIFOBuffer *fb) -{ - //ASSERT_VALID_FIFO(fb); - return - ((fb->head == fb->begin) && (fb->tail == fb->end)) - || (fb->tail == fb->head - 1); -} - - -/** - * Push a character on 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, unless the CPU can't update - * a pointer atomically (which the AVR and other 8-bit - * processors can't do). - * - * \sa fifo_push_locked - */ -INLINE void fifo_push(FIFOBuffer *fb, unsigned char c) -{ -#ifdef __MWERKS__ -#pragma interrupt called -#endif - //ASSERT_VALID_FIFO(fb); - - /* Write at tail position */ - *(fb->tail) = c; - - if (UNLIKELY(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. - */ -INLINE unsigned char fifo_pop(FIFOBuffer *fb) -{ -#ifdef __MWERKS__ -#pragma interrupt called -#endif - //ASSERT_VALID_FIFO(fb); - - if (UNLIKELY(fb->head == fb->end)) - { - /* wrap head around */ - fb->head = fb->begin; - return *(fb->end); - } - else - /* move head forward */ - return *(fb->head++); -} - - -/** - * Make the fifo empty, discarding all its current contents. - */ -INLINE void fifo_flush(FIFOBuffer *fb) -{ - //ASSERT_VALID_FIFO(fb); - fb->head = fb->tail; -} - - -#if CPU_REG_BITS >= CPU_BITS_PER_PTR - - /* - * 16/32bit CPUs that can update a pointer with a single write - * operation, no need to disable interrupts. - */ - #define fifo_isempty_locked(fb) fifo_isempty((fb)) - #define fifo_push_locked(fb, c) fifo_push((fb), (c)) - #define fifo_pop_locked(fb) fifo_pop((fb)) - #define fifo_flush_locked(fb) fifo_flush((fb)) - -#else /* CPU_REG_BITS < CPU_BITS_PER_PTR */ - - /** - * Similar to fifo_isempty(), but with stronger guarantees for - * concurrent access between user and interrupt code. - * - * \note This is actually only needed for 8-bit processors. - * - * \sa fifo_isempty() - */ - INLINE bool fifo_isempty_locked(const FIFOBuffer *fb) - { - bool result; - ATOMIC(result = fifo_isempty(fb)); - return result; - } - - - /** - * Similar to fifo_push(), but with stronger guarantees for - * concurrent access between user and interrupt code. - * - * \note This is actually only needed for 8-bit processors. - * - * \sa fifo_push() - */ - INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c) - { - ATOMIC(fifo_push(fb, c)); - } - - /* Probably not really needed, but hard to prove. */ - INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb) - { - unsigned char c; - ATOMIC(c = fifo_pop(fb)); - return c; - } - - /** - * Similar to fifo_flush(), but with stronger guarantees for - * concurrent access between user and interrupt code. - * - * \note This is actually only needed for 8-bit processors. - * - * \sa fifo_flush() - */ - INLINE void fifo_flush_locked(FIFOBuffer *fb) - { - ATOMIC(fifo_flush(fb)); - } - -#endif /* CPU_REG_BITS < BITS_PER_PTR */ - - -/** - * Thread safe version of fifo_isfull() - */ -INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb) -{ - bool result; - ATOMIC(result = fifo_isfull(_fb)); - return result; -} - - -/** - * FIFO Initialization. - */ -INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size) -{ - /* FIFO buffers have a known bug with 1-byte buffers. */ - ASSERT(size > 1); - - fb->head = fb->tail = fb->begin = buf; - fb->end = buf + size - 1; -} - - -#if 0 - -/* - * UNTESTED: if uncommented, to be moved in fifobuf.c - */ -void fifo_pushblock(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 - -#endif /* MWARE_FIFO_H */ - diff --git a/mware/formatwr.c b/mware/formatwr.c deleted file mode 100644 index 6353e1f1..00000000 --- a/mware/formatwr.c +++ /dev/null @@ -1,945 +0,0 @@ -/** - * \file - * - * - * \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 - * channels 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: - * - * \code - * -D CONFIG_PRINTF=PRINTF_FULL Full ANSI printf formatter - * -D CONFIG_PRINTF=PRINTF_NOFLOAT Exclude support for floats - * -D CONFIG_PRINTF=PRINTF_REDUCED Simplified formatter (see below) - * -D CONFIG_PRINTF=PRINTF_NOMODIFIERS Exclude 'l' and 'h' modifiers in reduced version - * -D CONFIG_PRINTF=PRINTF_DISABLED No formatter at all - * \endcode - * - * Code size on AVR4 with GCC 3.4.1 (-O2): - * PRINTF_FULL 2912byte (0xB60) - * PRINTF_NOFLOAT 1684byte (0x694) - * PRINTF_REDUCED 924byte (0x39C) - * PRINTF_NOMODIFIERS 416byte (0x1A0) - * - * Code/data size in words on DSP56K with CodeWarrior 6.0: - * PRINTF_FULL 1493/45 - * PRINTF_NOFLOAT 795/45 - * PRINTF_REDUCED 482/0 - * PRINTF_NOMODIFIERS 301/0 - * - * 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. - */ - - -#include "formatwr.h" -#include -#include -#include /* ASSERT */ -#include /* CONFIG_ macros */ - -#ifndef CONFIG_PRINTF_N_FORMATTER - /** Disable the arcane %n formatter. */ - #define CONFIG_PRINTF_N_FORMATTER 0 -#endif - -#ifndef CONFIG_PRINTF_OCTAL_FORMATTER - /** Disable the %o formatter. */ - #define CONFIG_PRINTF_OCTAL_FORMATTER 0 -#endif - -/* True if we must keep a count of the number of characters we print. */ -#define CONFIG_PRINTF_COUNT_CHARS (CONFIG_PRINTF_RETURN_COUNT || CONFIG_PRINTF_N_FORMATTER) - -#if CONFIG_PRINTF - -#if CONFIG_PRINTF > PRINTF_NOFLOAT - #include - - /* Maximum precision for floating point values */ - typedef long double max_float_t; - - /*bernie: save some memory, who cares about floats with lots of decimals? */ - #define FRMWRI_BUFSIZE 134 - #warning 134 is too much, the code must be fixed to have a lower precision limit -#else - /* - * Conservative estimate. Should be (probably) 12 (which is the size necessary - * to represent (2^32-1) in octal plus the sign bit. - */ - #define FRMWRI_BUFSIZE 16 -#endif - -/* Probably useful for fancy microcontrollers such as the PIC, nobody knows. */ -#ifndef MEM_ATTRIBUTE -#define MEM_ATTRIBUTE -#endif - -#if CONFIG_PRINTF > PRINTF_NOMODIFIERS - #define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier)) -#else - #define IS_SHORT (sizeof(int) == 2) -#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ - - -#if CONFIG_PRINTF > PRINTF_NOFLOAT - -static char *float_conversion(MEM_ATTRIBUTE max_float_t value, - MEM_ATTRIBUTE short nr_of_digits, - MEM_ATTRIBUTE char *buf, - MEM_ATTRIBUTE char format_flag, - MEM_ATTRIBUTE char g_flag, - MEM_ATTRIBUTE bool 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 = true; - } - - /* %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 -= (max_float_t)(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 /* CONFIG_PRINTF > PRINTF_NOFLOAT */ - -/** - * 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) -{ -#if CONFIG_PRINTF > PRINTF_REDUCED - MEM_ATTRIBUTE static char bad_conversion[] = "???"; - MEM_ATTRIBUTE static char null_pointer[] = ""; - - MEM_ATTRIBUTE int precision; - MEM_ATTRIBUTE int n; -#if CONFIG_PRINTF_COUNT_CHARS - MEM_ATTRIBUTE int nr_of_chars; -#endif - MEM_ATTRIBUTE int field_width; - MEM_ATTRIBUTE char format_flag; - enum PLUS_SPACE_FLAGS { - PSF_NONE, PSF_PLUS, PSF_MINUS - }; - enum DIV_FACTOR { - DIV_DEC, DIV_HEX, -#if CONFIG_PRINTF_OCTAL_FORMATTER - DIV_OCT, -#endif - }; - MEM_ATTRIBUTE struct { - enum PLUS_SPACE_FLAGS plus_space_flag : 2; -#if CONFIG_PRINTF_OCTAL_FORMATTER - enum DIV_FACTOR div_factor : 2; -#else - enum DIV_FACTOR div_factor : 1; -#endif - bool left_adjust : 1; - bool l_L_modifier : 1; - bool h_modifier : 1; - bool alternate_flag : 1; - bool nonzero_value : 1; - bool zeropad : 1; -#if CPU_HARVARD - bool progmem : 1; -#endif - } flags; - MEM_ATTRIBUTE unsigned long ulong; - -#if CONFIG_PRINTF > PRINTF_NOFLOAT - MEM_ATTRIBUTE max_float_t fvalue; -#endif - - MEM_ATTRIBUTE char *buf_pointer; - MEM_ATTRIBUTE char *ptr; - MEM_ATTRIBUTE const char *hex; - MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE]; - -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars = 0; -#endif - for (;;) /* Until full format string read */ - { - while ((format_flag = PGM_READ_CHAR(format++)) != '%') /* Until '%' or '\0' */ - { - if (!format_flag) -#if CONFIG_PRINTF_RETURN_COUNT - return (nr_of_chars); -#else - return 0; -#endif - put_one_char(format_flag, secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - if (PGM_READ_CHAR(format) == '%') /* %% prints as % */ - { - format++; - put_one_char('%', secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - continue; - } - - flags.left_adjust = false; - flags.alternate_flag = false; - flags.plus_space_flag = PSF_NONE; - flags.zeropad = false; -#if CPU_HARVARD - flags.progmem = false; -#endif - ptr = buf_pointer = &buf[0]; - hex = HEX_tab; - - /* check for leading '-', '+', ' ','#' or '0' flags */ - for (;;) - { - switch (PGM_READ_CHAR(format)) - { - case ' ': - if (flags.plus_space_flag) - goto NEXT_FLAG; - case '+': - flags.plus_space_flag = PSF_PLUS; - goto NEXT_FLAG; - case '-': - flags.left_adjust = true; - goto NEXT_FLAG; - case '#': - flags.alternate_flag = true; - goto NEXT_FLAG; - case '0': - flags.zeropad = true; - 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; - flags.left_adjust = true; - } - 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 (flags.left_adjust) - flags.zeropad = false; - - /* 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. - */ - - flags.l_L_modifier = false; - flags.h_modifier = false; - - /* Optional 'l','L','z' or 'h' modifier? */ - switch (PGM_READ_CHAR(format)) - { - case 'l': - case 'L': - case 'z': - flags.l_L_modifier = true; - format++; - break; - case 'h': - flags.h_modifier = true; - 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 CONFIG_PRINTF_N_FORMATTER - case 'n': - if (sizeof(short) != sizeof(int)) - { - if (sizeof(int) != sizeof(long)) - { - if (h_modifier) - *va_arg(ap, short *) = nr_of_chars; - else if (flags.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 (flags.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; - - /* Custom formatter for strings in program memory. */ - case 'S': -#if CPU_HARVARD - flags.progmem = true; -#endif - /* Fall trough */ - - case 's': - if ( !(buf_pointer = va_arg(ap, char *)) ) - buf_pointer = null_pointer; - if (precision < 0) - precision = 10000; - - /* - * Move `ptr' to the last character of the - * string that will be actually printed. - */ - ptr = buf_pointer; -#if CPU_HARVARD - if (flags.progmem) - { - for (n=0; pgm_read_char(ptr) && n < precision; n++) - ++ptr; - } - else -#endif - for (n=0; *ptr && n < precision; n++) - ++ptr; - break; - -#if CONFIG_PRINTF_OCTAL_FORMATTER - case 'o': - if (flags.alternate_flag && !precision) - precision++; -#endif - case 'x': - hex = hex_tab; - 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 (flags.l_L_modifier) - ulong = va_arg(ap, unsigned long); - else if (flags.h_modifier) - ulong = (unsigned long)(unsigned short)va_arg(ap, unsigned int); - else - ulong = va_arg(ap, unsigned int); - - flags.div_factor = -#if CONFIG_PRINTF_OCTAL_FORMATTER - (format_flag == 'o') ? DIV_OCT : -#endif - (format_flag == 'u') ? DIV_DEC : DIV_HEX; - flags.plus_space_flag = PSF_NONE; - goto INTEGRAL_CONVERSION; - - case 'd': - case 'i': - if (flags.l_L_modifier) - ulong = (unsigned long)(long)va_arg(ap, long); - else - ulong = (unsigned long)(long)va_arg(ap, int); - - /* Extract sign */ - if ((signed long)ulong < 0) - { - flags.plus_space_flag = PSF_MINUS; - ulong = (unsigned long)(-((signed long)ulong)); - } - - flags.div_factor = DIV_DEC; - - /* Now convert to digits */ -INTEGRAL_CONVERSION: - ptr = buf_pointer = &buf[FRMWRI_BUFSIZE - 1]; - flags.nonzero_value = (ulong != 0); - - /* No char if zero and zero precision */ - if (precision != 0 || flags.nonzero_value) - { - switch (flags.div_factor) - { - case DIV_DEC: - do - *--buf_pointer = hex[ulong % 10]; - while (ulong /= 10); - break; - - case DIV_HEX: - do - *--buf_pointer = hex[ulong % 16]; - while (ulong /= 16); - break; -#if CONFIG_PRINTF_OCTAL_FORMATTER - case DIV_OCT: - do - *--buf_pointer = hex[ulong % 8]; - while (ulong /= 8); - break; -#endif - } - } - - /* "precision" takes precedence */ - if (precision < 0) - if (flags.zeropad) - precision = field_width - (flags.plus_space_flag != PSF_NONE); - while (precision > (int)(ptr - buf_pointer)) - *--buf_pointer = '0'; - - if (flags.alternate_flag && flags.nonzero_value) - { - if (format_flag == 'x' || format_flag == 'X') - { - *--buf_pointer = format_flag; - *--buf_pointer = '0'; - } -#if CONFIG_PRINTF_OCTAL_FORMATTER - else if ((format_flag == 'o') && (*buf_pointer != '0')) - { - *--buf_pointer = '0'; - } -#endif - } - ASSERT(buf_pointer >= buf); - break; - -#if CONFIG_PRINTF > PRINTF_NOFLOAT - 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(max_float_t)) - { - fvalue = flags.l_L_modifier ? - va_arg(ap,max_float_t) : va_arg(ap,double); - } - else - fvalue = va_arg(ap,max_float_t); - - if (fvalue < 0) - { - flags.plus_space_flag = PSF_MINUS; - fvalue = -fvalue; - } - ptr = float_conversion (fvalue, - (short)precision, - buf_pointer += field_width, - format_flag, - (char)n, - flags.alternate_flag); - if (flags.zeropad) - { - precision = field_width - (flags.plus_space_flag != PSF_NONE); - while (precision > ptr - buf_pointer) - *--buf_pointer = '0'; - } - break; - -#endif /* CONFIG_PRINTF <= PRINTF_NOFLOAT */ - - case '\0': /* Really bad place to find NUL in */ - format--; - - default: - /* Undefined conversion! */ - ptr = buf_pointer = bad_conversion; - ptr += sizeof(bad_conversion) - 1; - 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 - (flags.plus_space_flag != PSF_NONE); - } - - /* emit any leading pad characters */ - if (!flags.left_adjust) - while (--n >= 0) - { - put_one_char(' ', secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - - /* emit flag characters (if any) */ - if (flags.plus_space_flag) - { - put_one_char(flags.plus_space_flag == PSF_PLUS ? '+' : '-', secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - -#if CPU_HARVARD - if (flags.progmem) - { - while (--precision >= 0) - { - put_one_char(pgm_read_char(buf_pointer++), secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - } - else -#endif /* CPU_HARVARD */ - { - /* emit the string itself */ - while (--precision >= 0) - { - put_one_char(*buf_pointer++, secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - } - - /* emit trailing space characters */ - if (flags.left_adjust) - while (--n >= 0) - { - put_one_char(' ', secret_pointer); -#if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; -#endif - } - } - -#else /* PRINTF_REDUCED starts here */ - -#if CONFIG_PRINTF > PRINTF_NOMODIFIERS - bool l_modifier, h_modifier; - unsigned long u_val, div_val; -#else - unsigned int u_val, div_val; -#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ - - 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++; - } - -#if CONFIG_PRINTF > PRINTF_NOMODIFIERS - /*=================================*/ - /* Optional 'l' or 'h' modifiers ? */ - /*=================================*/ - l_modifier = h_modifier = false; - switch (PGM_READ_CHAR(format)) - { - case 'l': - l_modifier = true; - format++; - break; - - case 'h': - h_modifier = true; - format++; - break; - } -#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ - - 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: -#if CONFIG_PRINTF > PRINTF_NOMODIFIERS - 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 /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ - u_val = va_arg(ap,int); -#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */ - 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 /* CONFIG_PRINTF > PRINTF_REDUCED */ -} - -#endif /* CONFIG_PRINTF */ diff --git a/mware/formatwr.h b/mware/formatwr.h deleted file mode 100644 index 5854bd4a..00000000 --- a/mware/formatwr.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \brief Basic "printf", "sprintf" and "fprintf" formatter. - */ - -#ifndef MWARE_FORMATWR_H -#define MWARE_FORMATWR_H - -#include /* va_list */ -#include -#include /* CPU_HARVARD */ - -/** - * \name _formatted_write() configuration - * \{ - */ -#define PRINTF_DISABLED 0 -#define PRINTF_NOMODIFIERS 1 -#define PRINTF_REDUCED 2 -#define PRINTF_NOFLOAT 3 -#define PRINTF_FULL 4 -/* \} */ - -#ifndef CONFIG_PRINTF_RETURN_COUNT - /** Enable/disable _formatted_write return value */ - #define CONFIG_PRINTF_RETURN_COUNT 1 -#endif - -int -_formatted_write( - const char *format, - void put_char_func(char c, void *user_data), - void *user_data, - va_list ap); - -#if CPU_HARVARD - #include - int _formatted_write_P( - const char * PROGMEM format, - void put_char_func(char c, void *user_data), - void *user_data, - va_list ap); -#endif /* CPU_HARVARD */ - -#endif /* MWARE_FORMATWR_H */ - diff --git a/mware/hashtable.c b/mware/hashtable.c deleted file mode 100644 index d3797339..00000000 --- a/mware/hashtable.c +++ /dev/null @@ -1,391 +0,0 @@ -/** - * \file - * - * - * \brief Portable hash table implementation - * - * Some rationales of our choices in implementation: - * - * \li For embedded systems, it is vital to allocate the table in static memory. To do - * so, it is necessary to expose the \c HashNode and \c HashTable structures in the header file. - * Nevertheless, they should be used as opaque types (that is, the users should not - * access the structure fields directly). - * - * \li To statically allocate the structures, a macro is provided. With this macro, we - * are hiding completely \c HashNode to the user (who only manipulates \c HashTable). Without - * the macro, the user would have had to define both the \c HashNode and the \c HashTable - * manually, and pass both of them to \c ht_init() (which would have created the link between - * the two). Instead, the link is created with a literal initialization. - * - * \li The hash table is created as power of two to remove the divisions from the code. - * Of course, hash functions work at their best when the table size is a prime number. - * When calculating the modulus to convert the hash value to an index, the actual operation - * becomes a bitwise AND: this is fast, but truncates the value losing bits. Thus, the higher - * bits are first "merged" with the lower bits through some XOR operations (see the last line of - * \c calc_hash()). - * - * \li To minimize the memory occupation, there is no flag to set for the empty node. An - * empty node is recognized by its data pointer set to NULL. It is then invalid to store - * NULL as data pointer in the table. - * - * \li The visiting interface through iterators is implemented with pass-by-value semantic. - * While this is overkill for medium-to-stupid compilers, it is the best designed from an - * user point of view. Moreover, being totally inlined (defined completely in the header), - * even a stupid compiler should be able to perform basic optimizations on it. - * We thought about using a pass-by-pointer semantic but it was much more awful to use, and - * the compiler is then forced to spill everything to the stack (unless it is *very* smart). - * - * \li The current implementation allows to either store the key internally (that is, copy - * the key within the hash table) or keep it external (that is, a hook is used to extract - * the key from the data in the node). The former is more memory-hungry of course, as it - * allocated static space to store the key copies. The overhead to keep both methods at - * the same time is minimal: - *
    - *
  • There is a run-time check in node_get_key which is execute per each node visited.
  • - *
  • Theoretically, there is no memory overhead. In practice, there were no - * flags in \c struct HashTable till now, so we had to add a first bit flag, but the - * overhead will disappear if a second flag is added for a different reason later.
  • - *
  • There is a little interface overhead, since we have two different versions of - * \c ht_insert(), one with the key passed as parameter and one without, but in - * the common case (external keys) both can be used.
  • - *
- * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -/*#* - *#* $Log$ - *#* Revision 1.8 2007/02/06 16:05:01 asterix - *#* Replaced ROTATE_* with ROT* defined in macros.h - *#* - *#* Revision 1.7 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/06/01 12:27:39 marco - *#* Added utilities for protocols - *#* - *#*/ - -#include "hashtable.h" -#include -#include -#include //ROTL(), ROTR(); - -#include - - - -typedef const void** HashNodePtr; -#define NODE_EMPTY(node) (!*(node)) -#define HT_HAS_INTERNAL_KEY(ht) (CONFIG_HT_OPTIONAL_INTERNAL_KEY && ht->flags.key_internal) - -/** For hash tables with internal keys, compute the pointer to the internal key for a given \a node. */ -INLINE uint8_t *key_internal_get_ptr(struct HashTable *ht, HashNodePtr node) -{ - uint8_t* key_buf = ht->key_data.mem; - size_t index; - - // Compute the index of the node and use it to move within the whole key buffer - index = node - &ht->mem[0]; - ASSERT(index < (size_t)(1 << ht->max_elts_log2)); - key_buf += index * (INTERNAL_KEY_MAX_LENGTH + 1); - - return key_buf; -} - - -INLINE void node_get_key(struct HashTable* ht, HashNodePtr node, const void** key, uint8_t* key_length) -{ - if (HT_HAS_INTERNAL_KEY(ht)) - { - uint8_t* k = key_internal_get_ptr(ht, node); - - // Key has its length stored in the first byte - *key_length = *k++; - *key = k; - } - else - *key = ht->key_data.hook(*node, key_length); -} - - -INLINE bool node_key_match(struct HashTable* ht, HashNodePtr node, const void* key, uint8_t key_length) -{ - const void* key2; - uint8_t key2_length; - - node_get_key(ht, node, &key2, &key2_length); - - return (key_length == key2_length && memcmp(key, key2, key_length) == 0); -} - - -static uint16_t calc_hash(const void* _key, uint8_t key_length) -{ - const char* key = (const char*)_key; - uint16_t hash = key_length; - int i; - int len = (int)key_length; - - for (i = 0; i < len; ++i) - hash = ROTL(hash, 4) ^ key[i]; - - return hash ^ (hash >> 6) ^ (hash >> 13); -} - - -static HashNodePtr perform_lookup(struct HashTable* ht, - const void* key, uint8_t key_length) -{ - uint16_t hash = calc_hash(key, key_length); - uint16_t mask = ((1 << ht->max_elts_log2) - 1); - uint16_t index = hash & mask; - uint16_t first_index = index; - uint16_t step; - HashNodePtr node; - - // Fast-path optimization: we check immediately if the current node - // is the one we were looking for, so we save the computation of the - // increment step in the common case. - node = &ht->mem[index]; - if (NODE_EMPTY(node) - || node_key_match(ht, node, key, key_length)) - return node; - - // Increment while going through the hash table in case of collision. - // This implements the double-hash technique: we use the higher part - // of the hash as a step increment instead of just going to the next - // element, to minimize the collisions. - // Notice that the number must be odd to be sure that the whole table - // is traversed. Actually MCD(table_size, step) must be 1, but - // table_size is always a power of 2, so we just ensure that step is - // never a multiple of 2. - step = (ROTR(hash, ht->max_elts_log2) & mask) | 1; - - do - { - index += step; - index &= mask; - - node = &ht->mem[index]; - if (NODE_EMPTY(node) - || node_key_match(ht, node, key, key_length)) - return node; - - // The check is done after the key compare. This actually causes - // one more compare in the case the table is full (since the first - // element was compared at the very start, and then at the end), - // but it makes faster the common path where we enter this loop - // for the first time, and index will not match first_index for - // sure. - } while (index != first_index); - - return NULL; -} - - -void ht_init(struct HashTable* ht) -{ - memset(ht->mem, 0, sizeof(ht->mem[0]) * (1 << ht->max_elts_log2)); -} - - -static bool insert(struct HashTable* ht, const void* key, uint8_t key_length, const void* data) -{ - HashNodePtr node; - - if (!data) - return false; - - if (HT_HAS_INTERNAL_KEY(ht)) - key_length = MIN(key_length, (uint8_t)INTERNAL_KEY_MAX_LENGTH); - - node = perform_lookup(ht, key, key_length); - if (!node) - return false; - - if (HT_HAS_INTERNAL_KEY(ht)) - { - uint8_t* k = key_internal_get_ptr(ht, node); - *k++ = key_length; - memcpy(k, key, key_length); - } - - *node = data; - return true; -} - - -bool ht_insert_with_key(struct HashTable* ht, const void* key, uint8_t key_length, const void* data) -{ -#ifdef _DEBUG - if (!HT_HAS_INTERNAL_KEY(ht)) - { - // Construct a fake node and use it to match the key - HashNodePtr node = &data; - if (!node_key_match(ht, node, key, key_length)) - { - ASSERT2(0, "parameter key is different from the external key"); - return false; - } - } -#endif - - return insert(ht, key, key_length, data); -} - - -bool ht_insert(struct HashTable* ht, const void* data) -{ - const void* key; - uint8_t key_length; - -#ifdef _DEBUG - if (HT_HAS_INTERNAL_KEY(ht)) - { - ASSERT("parameter cannot be a hash table with internal keys - use ht_insert_with_key()" - && 0); - return false; - } -#endif - - key = ht->key_data.hook(data, &key_length); - - return insert(ht, key, key_length, data); -} - - -const void* ht_find(struct HashTable* ht, const void* key, uint8_t key_length) -{ - HashNodePtr node; - - if (HT_HAS_INTERNAL_KEY(ht)) - key_length = MIN(key_length, (uint8_t)INTERNAL_KEY_MAX_LENGTH); - - node = perform_lookup(ht, key, key_length); - - if (!node || NODE_EMPTY(node)) - return NULL; - - return *node; -} - - -#if 0 - -#include - -bool ht_test(void); - -static const void* test_get_key(const void* ptr, uint8_t* length) -{ - const char* s = ptr; - *length = strlen(s); - return s; -} - -#define NUM_ELEMENTS 256 -DECLARE_HASHTABLE_STATIC(test1, 256, test_get_key); -DECLARE_HASHTABLE_INTERNALKEY_STATIC(test2, 256); - -static char data[NUM_ELEMENTS][10]; -static char keydomain[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -static bool single_test(void) -{ - int i; - - ht_init(&test1); - ht_init(&test2); - - for (i=0;i - * - * \brief Portable hash table - * - * This file implements a portable hash table, with the following features: - * - * \li Open double-hashing. The maximum number of elements is fixed. The double hashing - * function improves recovery in case of collisions. - * \li Configurable size (which is clamped to a power of two) - * \li Visiting interface through iterator (returns the element in random order). - * \li The key is stored within the data and a hook is used to extract it. Optionally, it - * is possible to store a copy of the key within the hash table. - * - * Since the hashing is open, there is no way to remove elements from the table. Instead, a - * function is provided to clear the table completely. - * - * The data stored within the table must be a pointer. The NULL pointer is used as - * a marker for a free node, so it is invalid to store a NULL pointer in the table - * with \c ht_insert(). - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - -/*#* - *#* $Log$ - *#* Revision 1.8 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.7 2006/06/01 12:27:39 marco - *#* Added utilities for protocols - *#* - *#*/ - -#ifndef MWARE_HASHTABLE_H -#define MWARE_HASHTABLE_H - -#include -#include -#include - -/** - * Enable/disable support to declare special hash tables which maintain a copy of - * the key internally instead of relying on the hook to extract it from the data. - */ -#define CONFIG_HT_OPTIONAL_INTERNAL_KEY 1 - -/// Maximum length of the internal key (use (2^n)-1 for slight speedup) -#define INTERNAL_KEY_MAX_LENGTH 15 - -/** - * Hook to get the key from \a data, which is an element of the hash table. The - * key must be returned together with \a key_length (in words). - */ -typedef const void *(*hook_get_key)(const void *data, uint8_t *key_length); - - -/** - * Hash table description - * - * \note This structures MUST NOT be accessed directly. Its definition is - * provided in the header file only for optimization purposes (see the rationale - * in hashtable.c). - * - * \note If new elements must be added to this list, please double check - * \c DECLARE_HASHTABLE, which requires the existing elements to be at the top. - */ -struct HashTable -{ - const void **mem; ///< Buckets of data - uint16_t max_elts_log2; ///< Log2 of the size of the table - struct { - bool key_internal : 1; ///< true if the key is copied internally - } flags; - union { - hook_get_key hook; ///< Hook to get the key - uint8_t *mem; ///< Pointer to the key memory - } key_data; -}; - - -/// Iterator to walk the hash table -typedef struct -{ - const void** pos; - const void** end; -} HashIterator; - - -/** - * Declare a hash table in the current scope - * - * \param name Variable name - * \param size Number of elements - * \param hook_gk Hook to be used to extract the key from the node - * - * \note The number of elements will be rounded down to the nearest - * power of two. - * - */ -#define DECLARE_HASHTABLE(name, size, hook_gk) \ - static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ - struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, hook_gk } - -/** Exactly like \c DECLARE_HASHTABLE, but the variable will be declared as static. */ -#define DECLARE_HASHTABLE_STATIC(name, size, hook_gk) \ - static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ - static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { false }, { hook_gk } } - -#if CONFIG_HT_OPTIONAL_INTERNAL_KEY - /** Declare a hash table with internal copies of the keys. This version does not - * require a hook, nor it requires the user to allocate static memory for the keys. - * It is mostly suggested for tables whose keys are computed on the fly and need - * to be stored somewhere. - */ - #define DECLARE_HASHTABLE_INTERNALKEY(name, size) \ - static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \ - static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ - struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys } - - /** Exactly like \c DECLARE_HASHTABLE_INTERNALKEY, but the variable will be declared as static. */ - #define DECLARE_HASHTABLE_INTERNALKEY_STATIC(name, size) \ - static uint8_t name##_keys[(1 << UINT32_LOG2(size)) * (INTERNAL_KEY_MAX_LENGTH + 1)]; \ - static const void* name##_nodes[1 << UINT32_LOG2(size)]; \ - static struct HashTable name = { name##_nodes, UINT32_LOG2(size), { true }, name##_keys } -#endif - -/** - * Initialize (and clear) a hash table in a memory buffer. - * - * \param ht Hash table declared with \c DECLARE_HASHTABLE - * - * \note This function must be called before using the hash table. Optionally, - * it can be called later in the program to clear the hash table, - * removing all its elements. - */ -void ht_init(struct HashTable* ht); - -/** - * Insert an element into the hash table - * - * \param ht Handle of the hash table - * \param data Data to be inserted into the table - * \return true if insertion was successful, false otherwise (table is full) - * - * \note The key for the element to insert is extract from the data with - * the hook. This means that this function cannot be called for hashtables - * with internal keys. - * - * \note If an element with the same key already exists in the table, - * it will be overwritten. - * - * \note It is not allowed to store NULL in the table. If you pass NULL as data, - * the function call will fail. - */ -bool ht_insert(struct HashTable* ht, const void* data); - -/** - * Insert an element into the hash table - * - * \param ht Handle of the hash table - * \param key Key of the element - * \param key_length Length of the key in characters - * \param data Data to be inserted into the table - * \return true if insertion was successful, false otherwise (table is full) - * - * \note If this function is called for hash table with external keys, - * the key provided must be match the key that would be extracted with the - * hook, otherwise the function will fail. - * - * \note If an element with the same key already exists in the table, - * it will be overwritten. - * - * \note It is not allowed to store NULL in the table. If you pass NULL as data, - * the function call will fail. - */ -bool ht_insert_with_key(struct HashTable* ht, const void* key, uint8_t key_length, const void* data); - -/** - * Find an element in the hash table - * - * \param ht Handle of the hash table - * \param key Key of the element - * \param key_length Length of the key in characters - * \return Data of the element, or NULL if no element was found for the given key. - */ -const void* ht_find(struct HashTable* ht, const void* key, uint8_t key_length); - -/** Similar to \c ht_insert_with_key() but \a key is an ASCIIZ string */ -#define ht_insert_str(ht, key, data) ht_insert_with_key(ht, key, strlen(key), data) - -/** Similar to \c ht_find() but \a key is an ASCIIZ string */ -#define ht_find_str(ht, key) ht_find(ht, key, strlen(key)) - -/// Get an iterator to the begin of the hash table \a ht -INLINE HashIterator ht_iter_begin(struct HashTable* ht) -{ - HashIterator h; - - h.pos = &ht->mem[0]; - h.end = &ht->mem[1 << ht->max_elts_log2]; - - while (h.pos != h.end && !*h.pos) - ++h.pos; - - return h; -} - -/** - * Get an iterator to the (exclusive) end of the hash table \a ht - * - * \note Like in STL, the end iterator is not a valid iterator (you - * cannot call \c ht_iter_get() on it), and it must be used only to - * detect if we reached the end of the iteration (through \c ht_iter_cmp()). - */ -INLINE HashIterator ht_iter_end(struct HashTable* ht) -{ - HashIterator h; - - h.pos = h.end = &ht->mem[1 << ht->max_elts_log2]; - - return h; -} - -/// Compare \a it1 and \a it2 for equality -INLINE bool ht_iter_cmp(HashIterator it1, HashIterator it2) -{ - ASSERT(it1.end == it2.end); - return it1.pos == it2.pos; -} - -/// Get the element within the hash table \a ht pointed by the iterator \a iter -INLINE const void* ht_iter_get(HashIterator iter) -{ return *iter.pos; } - -/** Return an iterator pointing to the element following \a h - * - * \note The order of the elements visited during the iteration is casual, - * and depends on the implementation. - * - */ -INLINE HashIterator ht_iter_next(HashIterator h) -{ - ++h.pos; - while (h.pos != h.end && !(*h.pos)) - ++h.pos; - - return h; -} - -#endif /* MWARE_HASHTABLE_H */ diff --git a/mware/heap.c b/mware/heap.c deleted file mode 100644 index bced107e..00000000 --- a/mware/heap.c +++ /dev/null @@ -1,265 +0,0 @@ -/** - * \file - * - * - * \brief Heap subsystem (public interface). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.9 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.8 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.7 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.6 2004/10/26 09:02:13 bernie - *#* heap_free(): Handle NULL pointers like free(), write documentation. - *#* - *#* Revision 1.5 2004/10/03 20:43:22 bernie - *#* Import changes from sc/firmware. - *#* - *#* Revision 1.1 2004/07/31 16:33:58 rasky - *#* Spostato lo heap da kern/ a mware/ - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 17:27:00 bernie - *#* Import kern/ subdirectory. - *#* - *#*/ - -#include "heap.h" -#include // memset() -#include // IS_POW2() -#include // ASSERT() - -/* NOTE: struct size must be a 2's power! */ -typedef struct _MemChunk -{ - struct _MemChunk *next; - size_t size; -} MemChunk; - -STATIC_ASSERT(IS_POW2(sizeof(MemChunk))); - -#define FREE_FILL_CODE 0xDEAD -#define ALLOC_FILL_CODE 0xBEEF - -void heap_init(struct Heap* h, void* memory, size_t size) -{ -#ifdef _DEBUG - memset(memory, FREE_FILL_CODE, size); -#endif - - /* Initialize heap with a single big chunk */ - h->FreeList = (MemChunk *)memory; - h->FreeList->next = NULL; - h->FreeList->size = size; -} - - -void *heap_allocmem(struct Heap* h, size_t size) -{ - MemChunk *chunk, *prev; - - /* Round size up to the allocation granularity */ - size = ROUND2(size, sizeof(MemChunk)); - - /* Handle allocations of 0 bytes */ - if (!size) - size = sizeof(MemChunk); - - /* Walk on the free list looking for any chunk big enough to - * fit the requested block size. - */ - for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList; - chunk; - prev = chunk, chunk = chunk->next) - { - if (chunk->size >= size) - { - if (chunk->size == size) - { - /* Just remove this chunk from the free list */ - prev->next = chunk->next; - #ifdef _DEBUG - memset(chunk, ALLOC_FILL_CODE, size); - #endif - return (void *)chunk; - } - else - { - /* Allocate from the END of an existing chunk */ - chunk->size -= size; - #ifdef _DEBUG - memset((uint8_t *)chunk + chunk->size, ALLOC_FILL_CODE, size); - #endif - return (void *)((uint8_t *)chunk + chunk->size); - } - } - } - - return NULL; /* fail */ -} - - -void heap_freemem(struct Heap* h, void *mem, size_t size) -{ - MemChunk *prev; - - ASSERT(mem); - -#ifdef _DEBUG - memset(mem, FREE_FILL_CODE, size); -#endif - - /* Round size up to the allocation granularity */ - size = ROUND2(size, sizeof(MemChunk)); - - /* Handle allocations of 0 bytes */ - if (!size) - size = sizeof(MemChunk); - - /* Special case: first chunk in the free list */ - ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList); - if (((uint8_t *)mem) < ((uint8_t *)h->FreeList)) - { - /* Insert memory block before the current free list head */ - prev = (MemChunk *)mem; - prev->next = h->FreeList; - prev->size = size; - h->FreeList = prev; - } - else /* Normal case: not the first chunk in the free list */ - { - /* - * Walk on the free list. Stop at the insertion point (when mem - * is between prev and prev->next) - */ - prev = h->FreeList; - while (prev->next < (MemChunk *)mem && prev->next) - prev = prev->next; - - /* Make sure mem is not *within* prev */ - ASSERT((uint8_t*)mem >= (uint8_t*)prev + prev->size); - - /* Should it be merged with previous block? */ - if (((uint8_t *)prev) + prev->size == ((uint8_t *)mem)) - { - /* Yes */ - prev->size += size; - } - else /* not merged with previous chunk */ - { - MemChunk *curr = (MemChunk*)mem; - - /* insert it after the previous node - * and move the 'prev' pointer forward - * for the following operations - */ - curr->next = prev->next; - curr->size = size; - prev->next = curr; - - /* Adjust for the following test */ - prev = curr; - } - } - - /* Also merge with next chunk? */ - if (((uint8_t *)prev) + prev->size == ((uint8_t *)prev->next)) - { - prev->size += prev->next->size; - prev->next = prev->next->next; - - /* There should be only one merge opportunity, becuase we always merge on free */ - ASSERT((uint8_t*)prev + prev->size != (uint8_t*)prev->next); - } -} - -#if CONFIG_HEAP_MALLOC - -void *heap_malloc(struct Heap* h, size_t size) -{ - size_t *mem; - - size += sizeof(size_t); - if ((mem = (size_t*)heap_allocmem(h, size))) - *mem++ = size; - - return mem; -} - -void *heap_calloc(struct Heap* h, size_t size) -{ - void *mem; - - if ((mem = heap_malloc(h, size))) - memset(mem, 0, size); - - return mem; -} - -/** - * Free a block of memory, determining its size automatically. - * - * \param h Heap from which the block was allocated. - * \param mem Pointer to a block of memory previously allocated with - * either heap_malloc() or heap_calloc(). - * - * \note If \a mem is a NULL pointer, no operation is performed. - * - * \note Freeing the same memory block twice has undefined behavior. - * - * \note This function works like the ANSI C free(). - */ -void heap_free(struct Heap *h, void *mem) -{ - size_t *_mem = (size_t *)mem; - - if (_mem) - { - --_mem; - heap_freemem(h, _mem, *_mem); - } -} - -#endif /* CONFIG_HEAP_MALLOC */ diff --git a/mware/heap.h b/mware/heap.h deleted file mode 100644 index 97cef8a3..00000000 --- a/mware/heap.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * \file - * - * - * \brief Heap subsystem (public interface). - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \todo Heap memory could be defined as an array of MemChunk, and used - * in this form also within the implementation. This would probably remove - * memory alignment problems, and also some aliasing issues. - * - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/07/19 12:56:27 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2005/11/27 23:36:19 bernie - *#* Use appconfig.h instead of cfg/config.h. - *#* - *#* Revision 1.5 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.4 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.3 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.2 2004/08/04 15:54:18 rasky - *#* Merge da SC: prima versione veramente funzionante - *#* - *#* Revision 1.1 2004/07/31 16:33:58 rasky - *#* Spostato lo heap da kern/ a mware/ - *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. - *#* - *#* Revision 1.1 2004/05/23 17:27:00 bernie - *#* Import kern/ subdirectory. - *#* - *#*/ - -#ifndef MWARE_HEAP_H -#define MWARE_HEAP_H - -#include -#include - -struct _MemChunk; - -/// A heap -struct Heap -{ - struct _MemChunk *FreeList; ///< Head of the free list -}; - - -/// Initialize \a heap within the buffer pointed by \a memory which is of \a size bytes -void heap_init(struct Heap* heap, void* memory, size_t size); - -/// Allocate a chunk of memory of \a size bytes from the heap -void *heap_allocmem(struct Heap* heap, size_t size); - -/// Free a chunk of memory of \a size bytes from the heap -void heap_freemem(struct Heap* heap, void *mem, size_t size); - - -#define HNEW(heap, type) \ - (type*)heap_allocmem(heap, sizeof(type)) - -#define HNEWVEC(heap, type, nelem) \ - (type*)heap_allocmem(heap, sizeof(type) * (nelem)) - -#define HDELETE(heap, type, mem) \ - heap_freemem(heap, mem, sizeof(type)) - -#define HDELETEVEC(heap, type, nelem, mem) \ - heap_freemem(heap, mem, sizeof(type) * (nelem)) - - -#if CONFIG_HEAP_MALLOC - -void *heap_malloc(struct Heap* heap, size_t size); -void *heap_calloc(struct Heap* heap, size_t size); -void heap_free(struct Heap* heap, void * mem); - -#endif - -#endif /* MWARE_HEAP_H */ diff --git a/mware/hex.c b/mware/hex.c deleted file mode 100644 index 01c41642..00000000 --- a/mware/hex.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * \file - * - * - * \brief Poor man's hex arrays (implementation). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - - -#include "hex.h" - -const char hex_tab[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; -const char HEX_tab[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; diff --git a/mware/hex.h b/mware/hex.h deleted file mode 100644 index 2c703066..00000000 --- a/mware/hex.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * \file - * - * - * \brief Poor man's hex arrays (implementation). - * - * \version $Id$ - * - * \author Bernardo Innocenti - */ - -#ifndef MWARE_HEX_H -#define MWARE_HEX_H - -extern const char hex_tab[16]; -extern const char HEX_tab[16]; - -#endif /* MWARE_HEX_H */ diff --git a/mware/list.h b/mware/list.h deleted file mode 100644 index ddbad8c4..00000000 --- a/mware/list.h +++ /dev/null @@ -1,323 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief General pourpose double-linked lists - */ - -#ifndef MWARE_LIST_H -#define MWARE_LIST_H - -#include /* INLINE */ -#include /* ASSERT() */ - -/** - * This structure represents a node for bidirectional lists. - * - * Data is usually appended to nodes by making them the first - * field of another struture, as a poor-man's form of inheritance. - */ -typedef struct _Node -{ - struct _Node *succ; - struct _Node *pred; -} Node; - -/** - * Head of a doubly-linked list of \c Node structs. - * - * Lists must be initialized with LIST_INIT() prior to use. - * - * Nodes can be added and removed from either end of the list - * with O(1) performance. Iterating over these lists can be - * tricky: use the FOREACH_NODE() macro instead. - */ -typedef struct _List -{ - Node head; - Node tail; -} List; - -/** - * Extended node for priority queues. - */ -typedef struct _PriNode -{ - Node link; - int pri; -} PriNode; - - -/** - * Template for a naked node in a list of \a T structures. - * - * To be used as data member in other structures: - * - * \code - * struct Foo - * { - * DECLARE_NODE_ANON(struct Foo) - * int a; - * float b; - * } - * - * DECLARE_LIST_TYPE(Foo); - * - * void foo(void) - * { - * static LIST_TYPE(Foo) foo_list; - * static Foo foo1, foo2; - * Foo *fp; - * - * LIST_INIT(&foo_list); - * ADDHEAD(&foo_list, &foo1); - * INSERT_BEFORE(&foo_list, &foo2); - * FOREACH_NODE(fp, &foo_list) - * fp->a = 10; - * } - * - * \endcode - */ -#define DECLARE_NODE_ANON(T) \ - T *succ; T *pred; - -/** Declare a typesafe node for structures of type \a T. */ -#define DECLARE_NODE_TYPE(T) \ - typedef struct T##Node { T *succ; T *pred; } T##Node - -/** Template for a list of \a T structures. */ -#define DECLARE_LIST_TYPE(T) \ - DECLARE_NODE_TYPE(T); \ - typedef struct T##List { \ - T##Node head; \ - T##Node tail; \ - } T##List - -#define NODE_TYPE(T) T##Node -#define LIST_TYPE(T) T##List - -/** - * Get a pointer to the first node in a list. - * - * If \a l is empty, result points to l->tail. - */ -#define LIST_HEAD(l) ((l)->head.succ) - -/** - * Get a pointer to the last node in a list. - * - * If \a l is empty, result points to l->head. - */ -#define LIST_TAIL(l) ((l)->tail.pred) - -// TODO: move in compiler.h -#if COMPILER_TYPEOF - #define TYPEOF_OR_VOIDPTR(type) typeof(type) -#else - #define TYPEOF_OR_VOIDPTR(type) void * -#endif - -/** - * Iterate over all nodes in a list. - * - * This macro generates a "for" statement using the following parameters: - * \param n Node pointer to be used in each iteration. - * \param l Pointer to list. - */ -#define FOREACH_NODE(n, l) \ - for( \ - (n) = (TYPEOF_OR_VOIDPTR(n))LIST_HEAD(l); \ - ((Node *)(n))->succ; \ - (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->succ) \ - ) - -/** - * Iterate backwards over all nodes in a list. - * - * This macro generates a "for" statement using the following parameters: - * \param n Node pointer to be used in each iteration. - * \param l Pointer to list. - */ -#define REVERSE_FOREACH_NODE(n, l) \ - for( \ - (n) = (TYPEOF_OR_VOIDPTR(n))LIST_TAIL(l); \ - ((Node *)(n))->pred; \ - (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->pred) \ - ) - -/** Initialize a list. */ -#define LIST_INIT(l) \ - do { \ - (l)->head.succ = (TYPEOF_OR_VOIDPTR((l)->head.succ)) &(l)->tail; \ - (l)->head.pred = NULL; \ - (l)->tail.succ = NULL; \ - (l)->tail.pred = (TYPEOF_OR_VOIDPTR((l)->tail.pred)) &(l)->head; \ - } while (0) - -#ifdef _DEBUG - /** Make sure that a list is valid (it was initialized and is not corrupted). */ - #define LIST_ASSERT_VALID(l) \ - do { \ - Node *n, *pred; \ - ASSERT((l)->head.succ != NULL); \ - ASSERT((l)->head.pred == NULL); \ - ASSERT((l)->tail.succ == NULL); \ - ASSERT((l)->tail.pred != NULL); \ - pred = &(l)->head; \ - FOREACH_NODE(n, l) \ - { \ - ASSERT(n->pred == pred); \ - pred = n; \ - } \ - ASSERT(n == &(l)->tail); \ - } while (0) - - #define INVALIDATE_NODE(n) ((n)->succ = (n)->pred = NULL) -#else - #define LIST_ASSERT_VALID(l) do {} while (0) - #define INVALIDATE_NODE(n) do {} while (0) -#endif - -/** Add node to list head. */ -#define ADDHEAD(l,n) \ - do { \ - ASSERT(l); \ - ASSERT(n); \ - (n)->succ = (l)->head.succ; \ - (n)->pred = (l)->head.succ->pred; \ - (n)->succ->pred = (n); \ - (n)->pred->succ = (n); \ - } while (0) - -/** Add node to list tail. */ -#define ADDTAIL(l,n) \ - do { \ - ASSERT(l); \ - ASSERT(n); \ - (n)->succ = &(l)->tail; \ - (n)->pred = (l)->tail.pred; \ - (n)->pred->succ = (n); \ - (l)->tail.pred = (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 INSERT_BEFORE(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. - * - * \note Removing a node that has not previously been - * inserted into a list invokes undefined behavior. - */ -#define REMOVE(n) \ - do { \ - (n)->pred->succ = (n)->succ; \ - (n)->succ->pred = (n)->pred; \ - INVALIDATE_NODE(n); \ - } while (0) - -/** Tell whether a list is empty. */ -#define LIST_EMPTY(l) ( (void *)((l)->head.succ) == (void *)(&(l)->tail) ) - -/** - * Insert a priority node in a priority queue. - * - * The new node is inserted immediately before the - * first node with lower priority or appended to - * the tail if no such node exists. - */ -#define LIST_ENQUEUE(list, node) \ - do { \ - PriNode *ln; \ - FOREACH_NODE(ln, (list)) \ - if (ln->pri < (node)->pri) \ - break; \ - INSERT_BEFORE(&(node)->link, &ln->link); \ - } while (0) - - -/** - * Unlink a node from the head of the list \a l. - * - * \return Pointer to node, or NULL if the list was empty. - */ -INLINE Node *list_remHead(List *l) -{ - Node *n; - - if (LIST_EMPTY(l)) - return (Node *)0; - - n = l->head.succ; /* Get first node. */ - l->head.succ = n->succ; /* Link list head to second node. */ - n->succ->pred = &l->head; /* Link second node to list head. */ - - INVALIDATE_NODE(n); - return n; -} - -/** - * Unlink a node from the tail of the list \a l. - * - * \return Pointer to node, or NULL if the list was empty. - */ -INLINE Node *list_remTail(List *l) -{ - Node *n; - - if (LIST_EMPTY(l)) - return (Node *)0; - - n = l->tail.pred; /* Get last node. */ - l->tail.pred = n->pred; /* Link list tail to second last node. */ - n->pred->succ = &l->tail; /* Link second last node to list tail. */ - - INVALIDATE_NODE(n); - return n; -} - -#endif /* MWARE_LIST_H */ diff --git a/mware/mean.h b/mware/mean.h deleted file mode 100644 index 893241e2..00000000 --- a/mware/mean.h +++ /dev/null @@ -1,41 +0,0 @@ -#warning revise me! - - -/** - * DECLARE_SMEAN(temperature, uint8_t, uint16_t); - * for (i = 0; i < TEMP_MEANS; ++i) - * SMEAN_ADD(temperature, adc_get(), TEMP_MEANS); - * printf("mean temperature = %d\n", SMEAN_GET(temperature)); - */ - -/** - * Instantiate a mean instance - */ -#define DECLARE_SMEAN(name, Type, SumType) \ - struct { \ - SumType sum; \ - Type result; \ - int count; \ - } name = { 0, 0, 0 } - -/** - * Insert a new sample into the mean. - * - * \note \a mean and \a max_samples are evaluated multiple times - */ -#define SMEAN_ADD(mean, sample, max_samples) \ - do { \ - (mean).sum += (sample); \ - if ((mean).count++ >= (max_samples)) \ - { \ - (mean).result = (mean).sum / (max_samples); \ - (mean).sum = 0; \ - (mean).count = 0; \ - } \ - } while (0) - -/** - * Return current mean value. - */ -#define SMEAN_GET(mean) ((mean).result) - diff --git a/mware/msg.c b/mware/msg.c deleted file mode 100644 index f565c8ab..00000000 --- a/mware/msg.c +++ /dev/null @@ -1,78 +0,0 @@ -/** - * \file - * - * - * \brief Messages for LCD. - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/07/19 12:56:28 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.1 2005/03/01 23:31:02 bernie - *#* String table and localization stuff. - *#* - *#*/ - -#include "msg.h" - -/** - * Array of pointers to localized strings. Should be filled - * by localization stuff, but not for now. - */ -const char *msg_strings[MSG_COUNT] = { - 0, - // TODO: add your strings here -}; - -/* Buffer for catalog file */ -/* char msg_buf[MSG_BUFSIZE]; */ - - -/* The following does not work (move string tables into the DMSG/CMSG segments) - * #pragma memory=dataseg(DMSG) - * #pragma memory=constseg(CMSG) - */ - - -/** - * Untranslated constant strings used more than once are - * grouped here to save ROM space. - */ -const char - str_empty[] = ""; - diff --git a/mware/msg.h b/mware/msg.h deleted file mode 100644 index 14d4c128..00000000 --- a/mware/msg.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * \file - * - * - * \brief Definitions of constant string messages. - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - */ - -/*#* - *#* $Log$ - *#* Revision 1.2 2006/02/10 11:30:37 bernie - *#* C++ fixes. - *#* - *#* Revision 1.1 2005/03/01 23:31:02 bernie - *#* String table and localization stuff. - *#* - *#*/ -#ifndef MWARE_MSG_H -#define MWARE_MSG_H - -enum -{ - MSG_NULL, - - // TODO: add your labels here. - - MSG_COUNT -}; - - -#define MSG_BUFSIZE 6144 /* FIXME: how much? */ - -/* String tables */ -extern const char *msg_strings const [MSG_COUNT]; -/* extern char msg_buf[MSG_BUFSIZE]; */ - - -/* Macros to access translated messages */ -#define MSG(x) msg_strings[x] -#define PTRMSG(x) ((x) < (const_iptr_t)256 ? msg_strings[(unsigned int)(x)] : (const char *)(x)) - - -#endif /* MWARE_MSG_H */ diff --git a/mware/observer.c b/mware/observer.c deleted file mode 100644 index a3acf98c..00000000 --- a/mware/observer.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file - * - * - * \brief Simple notifier for the observer/subject pattern (implementation) - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "observer.h" -#include // IRQ_DISABLE/IRQ_ENABLE - - -void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)) -{ - observer->event = event; -} - -void observer_InitSubject(Subject *subject) -{ - LIST_INIT(&subject->observers); -} - -void observer_Subscribe(Subject *subject, Observer *observer) -{ - ATOMIC(ADDHEAD(&subject->observers, &observer->link)); -} - -void observer_Unsubscribe(UNUSED_ARG(Subject *,subject), Observer *observer) -{ - ATOMIC(REMOVE(&observer->link)); -} - -void observer_notify(Subject *subject, int event_id, void *param) -{ - Observer *observer; - cpuflags_t irqstate; - IRQ_SAVE_DISABLE(irqstate); - - /* - * Run over list with protection against other - * threads, but re-enable irqs in callbacks. - */ - FOREACH_NODE(observer, &subject->observers) - { - IRQ_RESTORE(irqstate); - observer->event(event_id, param); - IRQ_SAVE_DISABLE(irqstate); - } - - IRQ_RESTORE(irqstate); -} diff --git a/mware/observer.h b/mware/observer.h deleted file mode 100644 index 39d33d68..00000000 --- a/mware/observer.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file - * - * - * \brief Simple notifier for the subject/observer pattern (interface) - * - * \version $Id$ - * \author Bernardo Innocenti - */ -#ifndef MWARE_OBSERVER_H -#define MWARE_OBSERVER_H - -#include - -/** - * - * Here's a simple example: - * - * \code - * Subject kbd_driver; - * - * Observer kbd_observer; - * - * void key_pressed(int event, void *_param) - * { - * char *param = (char *)_param; - * - * if (event == EVENT_KBD_PRESSED) - * printf("You pressed %c\n", *param); - * } - * - * void register_kbd_listener(void) - * { - * observer_SetEvent(&kbd_observer, key_pressed); - * observer_Subscribe(&kbd_driver, &kbd_observer); - * } - * \endcode - */ -typedef struct Observer -{ - Node link; - void (*event)(int event_id, void *param); -} Observer; - -typedef struct Subject -{ - /// Subscribed observers. - List observers; - -} Subject; - -void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)); - -#define OBSERVER_INITIALIZER(callback) { { NULL, NULL }, callback } - -void observer_InitSubject(Subject *subject); - -/// Aggiunge un Observer all'insieme -void observer_Subscribe(Subject *subject, Observer *observer); - -/// Rimuove un Observer dall'insieme -void observer_Unsubscribe(Subject *subject, Observer *observer); - -/// per tutti gli elementi nel set notifica l'evento, chiamando la relativa -/// funzione event -void observer_notify(Subject *subject, int event_id, void *param); - -#endif /* MWARE_OBSERVER_H */ diff --git a/mware/parser.c b/mware/parser.c deleted file mode 100644 index cc20b4e6..00000000 --- a/mware/parser.c +++ /dev/null @@ -1,392 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \author Giovanni Bajo - * - * \brief Serial protocol parser and commands. - * - * This file contains the serial protocol parser and - * the definition of the protocol commands. Commands are defined - * in a "CmdTemplate" type array, containing: - * - the name of the command, - * - the arguments it expects to receive, - * - the output values, - * - the name of the function implementing the command. - * - * The arguments and results are passed to command function - * using an union: the element of the union to use for each - * argument is determined by format strings present in the - * CmdTemplate table. - */ - - -#include "parser.h" -#include - -#include // atol(), NULL -#include // strchr(), strcmp() - -#include - -#include "appconfig.h" - -#define ARG_SEP_S " " -#define ARG_SEP_C ' ' - -#define MAX_COMMANDS_NUMBER 128 // 64 - -/// Hashtable hook to extract the key from a command -static const void* get_key_from_command(const void* cmd, uint8_t* length); - -/// Hashtable that handles the commands that can be executed -DECLARE_HASHTABLE_STATIC(commands, MAX_COMMANDS_NUMBER, get_key_from_command); - - -/** - * \brief Tokenize one word at a time from a text. - * - * This function is similar to strtok, but does not use any implicit - * context, nor it does modify the input buffer in any form. - * The word is returned as a STL-like [begin,end) range. - * - * To extract the first word, make both begin and end point at the - * start of the text, and call the function. Then, subsequent - * calls will return the following words (assuming the begin/end - * variable are not modified between calls). - * - * \param begin Will contain the index of the first character of the word - * \param end Will contain the index of the character after the last - * character of the word - * - * \return True if a word was extracted, false if we got to the end - * of the string without extracting any word. - */ -static bool get_word(const char **begin, const char **end) -{ - const char *cur = *end; - - while ((*cur == ' ' || *cur == '\t') && *cur) - ++cur; - - *begin = cur; - - while ((*cur != ' ' && *cur != '\t') && *cur) - ++cur; - - *end = cur; - - return (*end != *begin); -} - - -/** - * \brief Command arguments parser. - * - * Using the format pointed by the argument fmt - * parses the input string filling the array argv - * with input parameters of the correct type. - * - * \param fmt Parameters format string. - * \param input Input string. - * \param argv Array filled with parameters. - * - * \return False in case of errors, otherwise true. - */ -static bool parseArgs(const char *fmt, const char *input, parms argv[]) -{ - const char *begin = input, *end = input; - - while (*fmt) - { - // Extract the argument - if (!get_word(&begin, &end)) - return false; - - switch (*fmt) - { - case 'd': - (*argv++).l = atol(begin); - break; - - case 's': - (*argv++).s = begin; - break; - - default: - ASSERT2(0, "Unknown format for argument"); - return false; - } - - ++fmt; - } - - /* check if there are remaining args */ - if (get_word(&begin, &end)) - return false; - - return true; -} - - -#ifdef UNUSED_CODE -/** - * \brief Command result formatting and printing. - * - * Prints out on device fd the values contained - * in the array result, using the format specified - * in fmt. - * - * \param ser Serial handle. - * \param fmt Values format string. - * \param result Array containing result to be printed. - * - * \return -1 in case of errors, otherwise 0. - */ -static int printResult(struct Serial *ser, const char *fmt, parms result[]) -{ - long n; - char repeat_cnt = 0; - - while (*fmt) - { - if (*fmt >= '0' && *fmt <= '9') - { - /* Collect repeat count digit (left to right order) */ - repeat_cnt = (repeat_cnt * 10) + (*fmt - '0'); - } - else - { - /* Set default repeat cnt of 1 when not specified */ - if (repeat_cnt == 0) - repeat_cnt = 1; - - /* Loop repeat_cnt times */ - do - { - switch (*fmt) - { - case 'd': - ser_printf(ser, ARG_SEP_S "%ld", (*result).l); - result++; - break; - case 'c': - ser_print(ser, ARG_SEP_S); - ser_print(ser, (*result).s); - result++; - break; - case 's': - ser_printf(ser, ARG_SEP_S "%s", (*result).s); - result++; - break; - case 'n': - n = (*result++).l; - ser_printf(ser, ARG_SEP_S "%ld", n); - while (n--) { - ser_printf(ser, ARG_SEP_S "%ld", (*result).l); - result++; - } - break; - default: - break; - } - } - while (--repeat_cnt); - } - - /* Skip to next format char */ - ++fmt; - - } /* while (*fmt) */ - - - ser_print(ser, "\r\n"); - return 0; -} -#endif /* UNUSED_CODE */ - -/// Hook provided by the parser for matching of command names (TAB completion) for readline -const char* parser_rl_match(UNUSED_ARG(void *,dummy), const char *word, int word_len) -{ - HashIterator cur; - HashIterator end = ht_iter_end(&commands); - const char *found = NULL; - - for (cur = ht_iter_begin(&commands); - !ht_iter_cmp(cur, end); - cur = ht_iter_next(cur)) - { - const struct CmdTemplate* cmdp = (const struct CmdTemplate*)ht_iter_get(cur); - if (strncmp(cmdp->name, word, word_len) == 0) - { - // If there was another matching word, it means that we have a multiple - // match: then return NULL. - if (found) - return NULL; - - found = cmdp->name; - } - } - - return found; -} - -bool parser_get_cmd_id(const char* line, unsigned long* ID) -{ - const char *begin = line, *end = line; - char *end2; - - // The first word is the ID - if (!get_word(&begin, &end)) - return false; - - *ID = strtoul(begin, &end2, 10); - if (end2 != end) - return false; - - return true; -} - -const struct CmdTemplate* parser_get_cmd_template(const char *input) -{ -// const struct CmdTemplate *cmdp; -// int cmdlen; - const char *begin = input, *end = input; - - // Skip the ID, and get the command - if (!get_word(&begin, &end)) - return NULL; - if (!get_word(&begin, &end)) - return NULL; - - return (const struct CmdTemplate*)ht_find(&commands, begin, end-begin); -} - -static const char *skip_to_params(const char *input, const struct CmdTemplate *cmdp) -{ - const char *begin = input, *end = input; - - // Skip the ID, and get the command - if (!get_word(&begin, &end)) - return NULL; - if (!get_word(&begin, &end)) - return NULL; - - ASSERT2(strlen(cmdp->name) == (size_t)(end-begin), "Invalid command template specified"); - ASSERT2(!strncmp(begin, cmdp->name, end-begin), "Invalid command template specified"); - - return end; -} - -bool parser_get_cmd_arguments(const char* input, const struct CmdTemplate* cmdp, parms args[PARSER_MAX_ARGS]) -{ - input = skip_to_params(input, cmdp); - if (!input) - return false; - - args[0].s = cmdp->name; - if (!parseArgs(cmdp->arg_fmt, input, args + 1)) - return false; - - return true; -} - -static const void* get_key_from_command(const void* cmd, uint8_t* length) -{ - const struct CmdTemplate* c = cmd; - *length = strlen(c->name); - return c->name; -} - -bool parser_process_line(const char* input) -{ - const struct CmdTemplate *cmdp; - parms args[PARSER_MAX_ARGS]; - - cmdp = parser_get_cmd_template(input); - if (!cmdp) - return false; - - if (!parser_get_cmd_arguments(input, cmdp, args)) - return false; - - if (!parser_execute_cmd(cmdp, args)) - return false; - - return true; -} - -void parser_register_cmd(const struct CmdTemplate* cmd) -{ - ht_insert(&commands, cmd); -} - -#if CONFIG_INTERNAL_COMMANDS -static ResultCode cmd_help(void) -{ -#ifdef _DEBUG - - // FIXME: There is no way at the moment to access the serial port. Dump - // this through JTAG for now - for (HashIterator iter = ht_iter_begin(&commands); - !ht_iter_cmp(iter, ht_iter_end(&commands)); - iter = ht_iter_next(iter)) - { - struct CmdTemplate* cmd = (struct CmdTemplate*)ht_iter_get(iter); - kprintf("%-20s", cmd->name); - for (unsigned j = 0; cmd->arg_fmt[j]; ++j) - kprintf("%c ", 'a' + j); - kprintf("\r\n"); - } -#endif - - return RC_OK; -} - -#include "cmd_hunk.h" -DECLARE_CMD_HUNK(help, (NIL), (NIL)); - -#endif // CONFIG_INTERNAL_COMMANDS - - -void parser_init(void) -{ - // Initialize the hashtable used to store the command description - ht_init(&commands); - -#if CONFIG_INTERNAL_COMMANDS - parser_register_cmd(&CMD_HUNK_TEMPLATE(help)); -#endif -} diff --git a/mware/parser.h b/mware/parser.h deleted file mode 100644 index b4e2f61d..00000000 --- a/mware/parser.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * \author Giovanni Bajo - * - * \brief serial protocol parser and commands. - */ - - -#ifndef PARSER_H -#define PARSER_H - -#include - -/** Max number of arguments and results for each command */ -#define PARSER_MAX_ARGS 8 - -/** - * Error generated by the commands through the return code. - */ -typedef enum -{ - RC_ERROR = -1, ///< Reply with error. - RC_OK = 0, ///< No reply (ignore reply arguments). - RC_REPLY = 1, ///< Reply command arguments. - RC_SKIP = 2 ///< Skip following commands -} ResultCode; - -/** union that contains parameters passed to and from commands */ -typedef union { long l; const char *s; } parms; -/** pointer to commands */ -typedef ResultCode (*CmdFuncPtr)(parms args_results[]); - -/** - * Define a command that can be tokenized by the parser. - * - * The format strings are sequences of characters, one for each - * parameter/result. Valid characters are: - * - * d - a long integer, in decimal format - * s - a var string (in RAM) - * - * \note To create and fill an instance for this function, it is strongly - * advised to use \c DECLARE_CMD_HUNK (cmd_hunk.h). - */ -struct CmdTemplate -{ - const char *name; ///< Name of command - const char *arg_fmt; ///< Format string for the input - const char *result_fmt; ///< Format string for the output - CmdFuncPtr func; ///< Pointer to the handler function - uint16_t flags; ///< Currently unused. -}; - -/** - * Initialize the parser module - * - * \note This function must be called before any other function in this module - */ -void parser_init(void); - - -/** - * Register a new command into the parser - * - * \param cmd Command template describing the command - * - */ -void parser_register_cmd(const struct CmdTemplate* cmd); - - -/** - * Hook for readline to provide completion support for the commands - * registered in the parser. - * - * \note This is meant to be used with mware/readline.c. See the - * documentation there for a description of this hook. - */ -const char* parser_rl_match(void* dummy, const char* word, int word_len); - - -/** - * \brief Command input handler. - * - * Process the input, calling the requested command - * (if found) and calling printResult() to give out - * the result (on device specified with parameter fd). - * - * \param line Text line to be processed (ASCIIZ) - * - * \return true if everything is OK, false in case of errors - */ -bool parser_process_line(const char* line); - - -/** - * Execute a command with its arguments, and fetch its results. - * - * \param templ Template of the command to be executed - * \param args Arguments for the command, and will contain the results - * - * \return False if the command returned an error, true otherwise - */ -INLINE bool parser_execute_cmd(const struct CmdTemplate* templ, parms args[PARSER_MAX_ARGS]) -{ - return (templ->func(args) == 0); -} - - -/** - * Find the template for the command contained in the text line. - * The template can be used to tokenize the command and interpret - * it. - * - * This function can be used to find out which command is contained - * in a given text line without parsing all the parameters and - * executing it. - * - * \param line Text line to be processed (ASCIIZ) - * - * \return The command template associated with the command contained - * in the line, or NULL if the command is invalid. - */ -const struct CmdTemplate* parser_get_cmd_template(const char* line); - - -/** - * Extract the arguments for the command contained in the text line. - * - * \param line Text line to be processed (ASCIIZ) - * \param templ Command template for this line - * \param args Will contain the extracted parameters - * - * \return True if everything OK, false in case of parsing error. - */ -bool parser_get_cmd_arguments(const char* line, const struct CmdTemplate* templ, parms args[PARSER_MAX_ARGS]); - - -/** - * Extract the ID from the command text line. - * - * \param line Text line to be processed (ASCIIZ) - * \param ID Will contain the ID extracted. - * - * \return True if everything ok, false if there is no ID - * - */ -bool parser_get_cmd_id(const char* line, unsigned long* ID); - - -#endif /* PARSER_H */ - diff --git a/mware/pgm.h b/mware/pgm.h deleted file mode 100644 index eebe87fe..00000000 --- a/mware/pgm.h +++ /dev/null @@ -1,211 +0,0 @@ -/** - * \file - * - * - * \brief Support for reading program memory on Harvard architectures. - * - * Support is currently provided for AVR microcontrollers only. - * - * These macros allow building code twice, with and without - * pgm support (e.g.: strcpy() and strcpy_P()). - * - * Set the _PROGMEM predefine to compile in conditional - * program-memory support. - * - * - * \note This module contains code ripped out from avr-libc, - * which is distributed under a 3-clause BSD license. - */ -#ifndef MWARE_PGM_H -#define MWARE_PGM_H - -#include /* For intXX_t */ -#include -#include /* For CPU_HARVARD */ -#include /* For SIZEOF_INT */ - -#if CPU_AVR - - #ifdef __AVR_ENHANCED__ - #define pgm_read_char(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint8_t __result; \ - __asm__ \ - ( \ - "lpm %0, Z" "\n\t" \ - : "=r" (__result) \ - : "z" (__addr16) \ - ); \ - __result; \ - }) - #define pgm_read_uint16_t(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint16_t __result; \ - __asm__ \ - ( \ - "lpm %A0, Z+" "\n\t" \ - "lpm %B0, Z" "\n\t" \ - : "=r" (__result), "=z" (__addr16) \ - : "1" (__addr16) \ - ); \ - __result; \ - }) - - - #else /* !__AVR_ENHANCED__ */ - - #define pgm_read_char(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint8_t __result; \ - __asm__ \ - ( \ - "lpm" "\n\t" \ - "mov %0, r0" "\n\t" \ - : "=r" (__result) \ - : "z" (__addr16) \ - : "r0" \ - ); \ - __result; \ - }) - #define pgm_read_uint16_t(addr) \ - ({ \ - uint16_t __addr16 = (uint16_t)(addr); \ - uint16_t __result; \ - __asm__ \ - ( \ - "lpm" "\n\t" \ - "mov %A0, r0" "\n\t" \ - "adiw r30, 1" "\n\t" \ - "lpm" "\n\t" \ - "mov %B0, r0" "\n\t" \ - : "=r" (__result), "=z" (__addr16) \ - : "1" (__addr16) \ - : "r0" \ - ); \ - __result; \ - }) - - #endif /* !__AVR_ENHANCED__ */ - - #if SIZEOF_INT == 2 - #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr)) - #else - #error Missing support for CPU word size != 16bit - #endif - - #ifndef PROGMEM - #define PROGMEM __attribute__((__progmem__)) - #endif - #ifndef PSTR - #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; }) - #endif - #ifndef PFUNC - #define PFUNC(x) x ## _P - #endif - -#elif CPU_HARVARD - #error Missing CPU support -#endif - -#ifndef PSTR -#define PSTR /* nothing */ -#endif - -#ifndef PFUNC -#define PFUNC(x) x -#endif - -#ifndef PROGMEM -#define PROGMEM /* nothing */ -#endif - -/** - * \name Types for variables stored in program memory (harvard processors). - * \{ - */ -typedef PROGMEM char pgm_char; -typedef PROGMEM int8_t pgm_int8_t; -typedef PROGMEM uint8_t pgm_uint8_t; -typedef PROGMEM int16_t pgm_int16_t; -typedef PROGMEM uint16_t pgm_uint16_t; -typedef PROGMEM int32_t pgm_int32_t; -typedef PROGMEM uint32_t pgm_uint32_t; -/*\}*/ - -/** - * \name PGM support macros. - * - * These macros enable dual compilation of code for both program - * and data memory. - * - * Such a function may be defined like this: - * - * \code - * void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str) - * { - * char c; - * while ((c = PGM_READ_CHAR(str++)) - * lcd_putchar(c); - * } - * \endcode - * - * The above code can be compiled twice: once with the _PROGMEM preprocessor - * symbol defined, and once without. The two object modules can then be - * linked in the same application for use by client code: - * - * \code - * lcd_puts("Hello, world!"); - * lcd_puts_P(PSTR("Hello, world!")); - * - * // To be used when invoking inside other PGM_FUNC functions: - * PGM_FUNC(lcd_puts)(some_string); - * \endcode - * - * \{ - */ -#ifdef _PROGMEM - #define PGM_READ_CHAR(s) pgm_read_char(s) - #define PGM_FUNC(x) PFUNC(x) - #define PGM_STR(x) PSTR(x) - #define PGM_ATTR PROGMEM -#else - #define PGM_READ_CHAR(s) (*(s)) - #define PGM_FUNC(x) x - #define PGM_STR(x) x - #define PGM_ATTR /* nothing */ -#endif -/* \} */ - - -#endif /* MWARE_PGM_H */ diff --git a/mware/pool.h b/mware/pool.h deleted file mode 100644 index a6834e6c..00000000 --- a/mware/pool.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * \file - * - * - * \brief Pool macros. - * - * \version $Id$ - * \author Giovanni Bajo - */ - -/*#* - *#* $Log$ - *#* Revision 1.6 2006/07/19 12:56:28 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.5 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.4 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.3 2004/12/08 08:09:01 bernie - *#* Add missing header. - *#* - *#*/ -#ifndef MWARE_POOL_H -#define MWARE_POOL_H - -#include -#include - -#define EXTERN_POOL(name) \ - extern List name - -#define DECLARE_POOL_WITH_STORAGE(name, type, num, storage) \ - static type name##_items[num]; \ - storage name; \ - INLINE void name##_init(void (*init_func)(type*)) \ - { \ - int i; \ - LIST_INIT(&name); \ - for (i=0;i - * - * --> - * - * \brief Very simple rand() algorithm. - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/* This would really belong to libc */ -static int rand(void) -{ - static unsigned long seed; - - /* Randomize seed */ - seed = (seed ^ 0x4BAD5A39UL) + 6513973UL; - - return (int)(seed>>16); -} diff --git a/mware/readline.c b/mware/readline.c deleted file mode 100644 index 4c3b3a81..00000000 --- a/mware/readline.c +++ /dev/null @@ -1,507 +0,0 @@ -/** - * \file - * - * - * \brief Line editing support with history - * - * Rationale for basic implementation choices: - * - * \li The history is implemented storing consecutive ASCIIZ strings within an array of memory. When - * the history is full, the first (oldest) line is cancelled and the whole buffer is memmoved to - * overwrite it and make room. while this is is obviously not the fastest algorithm (which would - * require the use of a circular buffer) it is surely good enough for this module, which does not - * aim at fast performances (line editing does not require to be blazingly fast). - * - * \li The first character in the history is always \c \\0, and it is used as a guard. By 'wasting' it - * in this way, the code actually gets much simpler in that we remove many checks when moving - * backward (\c i>0 and similar). - * - * \li While editing, the current index points to the position of the buffer which contains the - * last character typed in (exactly like a stack pointer). This also allows to simplify calculations - * and to make easier using the last byte of history. - * - * \li While editing, the current line is always kept null-terminated. This is important because - * if the user press ENTER, we must have room to add a \c \\0 to terminate the line. If the line - * is as long as the whole history buffer, there would not be space for it. By always keeping the - * \c \\0 at the end, we properly ensure this without making index checks harder. - * - * \li When removing a line from the history (see \c pop_history()), instead of updating all the - * indices we have around, we move backward the pointer to the history we use. This way, we don't - * have to update anything. This means that we keep two pointers to the history: \c real_history - * always points to the physical start, while \c history is the adjusted pointer (that is - * dereference to read/write to it). - * - * \todo Use up/down to move through history The history line will be copied to the current line, - * making sure there is room for it. - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - - -#include "readline.h" - -#include -#include - -#include -#include - - -/// Enable compilation of the unit test code -#define DEBUG_UNIT_TEST 0 - -/// Enable dump of the history after each line -#define DEBUG_DUMP_HISTORY 0 - - -/** Special keys (escape sequences converted to a single code) */ -enum RL_KEYS { - SPECIAL_KEYS = 0x1000, - - /* - * Three byte keys: - * ################# - * UpArrow: 0x1B 0x5B 0X41 - * DownArrow: 0x1B 0x5B 0X42 - * RightArrow: 0x1B 0x5B 0x43 - * LeftArrow: 0x1b 0x5B 0x44 - * Beak(Pause): 0x1b 0x5B 0x50 - */ - KEY_UP_ARROW, - KEY_DOWN_ARROW, - KEY_LEFT_ARROW, - KEY_RIGHT_ARROW, - KEY_PAUSE, - - /* - * Four byte keys: - * ################ - * F1: 0x1b 0x5B 0x5B 0x41 - * F2: 0x1b 0x5B 0x5B 0x42 - * F3: 0x1b 0x5B 0x5B 0x43 - * F4: 0x1b 0x5B 0x5B 0x44 - * F5: 0x1b 0x5B 0x5B 0x45 - * Ins: 0x1b 0x5B 0x32 0x7E - * Home: 0x1b 0x5B 0x31 0x7E - * PgUp: 0x1b 0x5B 0x35 0x7E - * Del: 0x1b 0x5B 0x33 0x7E - * End: 0x1b 0x5B 0x34 0x7E - * PgDn: 0x1b 0x5B 0x36 0x7E - */ - KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, - KEY_INS, KEY_HOME, KEY_PGUP, KEY_DEL, KEY_END, KEY_PGDN, - - /* - * Five byte keys: - * ################ - * F6: 0x1b 0x5B 0x31 0x37 0x7E - * F7: 0x1b 0x5B 0x31 0x38 0x7E - * F8: 0x1b 0x5B 0x31 0x39 0x7E - * F9: 0x1b 0x5B 0x32 0x30 0x7E - * F10: 0x1b 0x5B 0x32 0x31 0x7E - * F11: 0x1b 0x5B 0x32 0x33 0x7E - * F12: 0x1b 0x5B 0x32 0x34 0x7E - */ - KEY_F6, KEY_F7, KEY_F8, KEY_F9, - KEY_F10, KEY_F11, KEY_F12, -}; - -/** Check if \a c is a separator between words. - * \note Parameter \a c is evaluated multiple times - */ -#define IS_WORD_SEPARATOR(c) ((c) == ' ' || (c) == '\0') - -/// Write the string \a txt to the IO output (without any kind of termination) -INLINE void rl_puts(const struct RLContext* ctx, const char* txt) -{ - if (!ctx->put) - return; - - while (*txt) - ctx->put(*txt++, ctx->put_param); -} - -/// Write character \a ch to the IO output. -INLINE void rl_putc(const struct RLContext* ctx, char ch) -{ - if (ctx->put) - ctx->put(ch, ctx->put_param); -} - -/** Read a character from the IO into \a ch. This function also takes - * care of converting the ANSI escape sequences into one of the codes - * defined in \c RL_KEYS. - */ -static bool rl_getc(const struct RLContext* ctx, int* ch) -{ - int c = ctx->get(ctx->get_param); - - if (c == EOF) - { - if (ctx->clear) - ctx->clear(ctx->clear_param); - - return false; - } - - if (c == 0x1B) - { - // Unknown ESC sequence. Ignore it and read - // return next character. - if (ctx->get(ctx->get_param) != 0x5B) - return rl_getc(ctx, ch); - - /* To be added: - * Home: 0x1b 0x5B 0x31 0x7E - * F6: 0x1b 0x5B 0x31 0x37 0x7E - * F7: 0x1b 0x5B 0x31 0x38 0x7E - * F8: 0x1b 0x5B 0x31 0x39 0x7E - * Ins: 0x1b 0x5B 0x32 0x7E - * F9: 0x1b 0x5B 0x32 0x30 0x7E - * F10: 0x1b 0x5B 0x32 0x31 0x7E - * F11: 0x1b 0x5B 0x32 0x33 0x7E - * F12: 0x1b 0x5B 0x32 0x34 0x7E - * Del: 0x1b 0x5B 0x33 0x7E - * End: 0x1b 0x5B 0x34 0x7E - * PgUp: 0x1b 0x5B 0x35 0x7E - * PgDn: 0x1b 0x5B 0x36 0x7E - */ - - c = ctx->get(ctx->get_param); - switch (c) - { - case 0x41: c = KEY_UP_ARROW; break; - case 0x42: c = KEY_DOWN_ARROW; break; - case 0x43: c = KEY_RIGHT_ARROW; break; - case 0x44: c = KEY_LEFT_ARROW; break; - case 0x50: c = KEY_PAUSE; break; - case 0x5B: - c = ctx->get(ctx->get_param); - switch (c) - { - case 0x41: c = KEY_F1; break; - case 0x42: c = KEY_F2; break; - case 0x43: c = KEY_F3; break; - case 0x44: c = KEY_F4; break; - case 0x45: c = KEY_F5; break; - default: return rl_getc(ctx, ch); - } - break; - default: return rl_getc(ctx, ch); - } - } - - *ch = c; - return true; -} - -INLINE void beep(struct RLContext* ctx) -{ - rl_putc(ctx, '\a'); -} - -static bool pop_history(struct RLContext* ctx, int total_len) -{ - // Compute the length of the first command (including terminator). - int len = strlen(ctx->real_history+1)+1; - - // (the first byte of the history should always be 0) - ASSERT(ctx->real_history[0] == '\0'); - - // If it is the only one in the history, do nothing - if (len == total_len) - return false; - - // Overwrite the first command with the second one - memmove(ctx->real_history, ctx->real_history+len, HISTORY_SIZE-len); - - // Move back the ctx->buffer pointer so that all the indices are still valid - ctx->history -= len; - - return true; -} - -/// Check if index \a i points to the begin of the history. -INLINE bool is_history_begin(struct RLContext* ctx, int i) -{ return ctx->history + i == ctx->real_history; } - -/// Check if index \a i points to the (exclusive) end of history -INLINE bool is_history_end(struct RLContext* ctx, int i) -{ return ctx->history + i == ctx->real_history + HISTORY_SIZE; } - -/// Check if index \a i points to the (exclusive) end of history, or somewhere past the end. -INLINE bool is_history_past_end(struct RLContext* ctx, int i) -{ return ctx->history + i >= ctx->real_history + HISTORY_SIZE; } - -/** Insert \a num_chars characters from \a ch into the history buffer at the - * position indicated by \a curpos. If needed, remove old history to make room. - * Returns true if everything was successful, false if there was no room to - * add the characters. - * \note \a num_chars can be 0, in which case we just make sure the line is - * correctly zero-terminated (ASCIIZ format). - */ -static bool insert_chars(struct RLContext* ctx, size_t *curpos, const char* ch, int num_chars) -{ - ASSERT(!is_history_past_end(ctx, *curpos)); - - while (is_history_past_end(ctx, *curpos+num_chars+1)) - { - if (!pop_history(ctx, *curpos)) - return false; - } - - while (num_chars--) - ctx->history[++(*curpos)] = *ch++; - - ASSERT(!is_history_past_end(ctx, *curpos + 1)); - ctx->history[*curpos+1] = '\0'; - return true; -} - -/// Insert a single character \a ch into the buffer (with the same semantic of \c insert_chars()) -static bool insert_char(struct RLContext* ctx, size_t *curpos, char ch) -{ - return insert_chars(ctx, curpos, &ch, 1); -} - -#if DEBUG_DUMP_HISTORY -/// Dump the internal history of a context (used only for debug purposes) -static void dump_history(struct RLContext* ctx) -{ - int k; - char buf[8]; - ASSERT(ctx->real_history[0] == '\0'); - rl_puts(ctx, "History dump:"); - rl_puts(ctx, "\r\n"); - for (k = 1; - ctx->real_history + k != ctx->history + ctx->history_pos + 1; - k += strlen(&ctx->real_history[k]) + 1) - { - rl_puts(ctx, &ctx->real_history[k]); - rl_puts(ctx, "\r\n"); - } - - sprintf(buf, "%d\r\n", ctx->history_pos + (ctx->history - ctx->real_history)); - rl_puts(ctx, buf); -} -#endif /* DEBUG_DUMP_HISTORY */ - -/// Complete the current word. Return false if no unambiguous completion was found -static bool complete_word(struct RLContext *ctx, size_t *curpos) -{ - const char* completed_word; - size_t wstart; - - // If the current character is a separator, - // there is nothing to complete - wstart = *curpos; - if (IS_WORD_SEPARATOR(ctx->history[wstart])) - { - beep(ctx); - return false; - } - - // Find the separator before the current word - do - --wstart; - while (!IS_WORD_SEPARATOR(ctx->history[wstart])); - - // Complete the word through the hook - completed_word = ctx->match(ctx->match_param, ctx->history + wstart + 1, *curpos - wstart); - if (!completed_word) - return false; - - // Move back the terminal cursor to the separator - while (*curpos != wstart) - { - rl_putc(ctx, '\b'); - --*curpos; - } - - // Insert the completed command - insert_chars(ctx, curpos, completed_word, strlen(completed_word)); - rl_puts(ctx, completed_word); - insert_char(ctx, curpos, ' '); - rl_putc(ctx, ' '); - - return true; -} - -void rl_refresh(struct RLContext* ctx) -{ - rl_puts(ctx, "\r\n"); - if (ctx->prompt) - rl_puts(ctx, ctx->prompt); - rl_puts(ctx, ctx->history + ctx->history_pos + 1); -} - -const char* rl_readline(struct RLContext* ctx) -{ - size_t i = ctx->history_pos; - - if (ctx->prompt) - rl_puts(ctx, ctx->prompt); - - insert_chars(ctx, &i, NULL, 0); - - while (1) - { - char ch; - int c; - - ASSERT(ctx->history - ctx->real_history + ctx->line_pos < HISTORY_SIZE); - - if (!rl_getc(ctx, &c)) - return NULL; - - // Just ignore special keys for now - if (c > SPECIAL_KEYS) - continue; - - if (c == '\t') - { - // Ask the match hook if available - if (!ctx->match) - return false; - - complete_word(ctx, &ctx->line_pos); - continue; - } - - if (c == '\r' || c == '\n') - { - if (ctx->prompt) - rl_puts(ctx, ctx->prompt); - - // Terminate line - insert_chars(ctx, &ctx->line_pos, NULL, 0); - rl_puts(ctx, "\r\n"); - break; - } - - // Backspace cancels a character, or it is ignored if at - // the start of the line - if (c == '\b') - { - if (ctx->history[ctx->line_pos] != '\0') - { - --ctx->line_pos; - rl_puts(ctx, "\b \b"); - } - continue; - } - - // Add a character to the buffer, if possible - ch = (char)c; - ASSERT2(ch == c, "a special key was not properly handled"); - if (insert_chars(ctx, &ctx->line_pos, &ch, 1)) - { - rl_putc(ctx, ch); - } - else - { - beep(ctx); - } - } - - ctx->history_pos = ctx->line_pos + 1; - while (ctx->history[ctx->line_pos] != '\0') - --ctx->line_pos; - - // Do not store empty lines in the history - if (ctx->line_pos == ctx->history_pos - 1) - ctx->history_pos -= 1; - -#if DEBUG_DUMP_HISTORY - dump_history(ctx); -#endif - - // Since the current pointer now points to the separator, we need - // to return the first character - return &ctx->history[ctx->line_pos + 1]; -} - - -#if DEBUG_UNIT_TEST - -/** Perform the unit test for the readline library */ -void rl_test(void); - -#if HISTORY_SIZE != 32 - #error This test needs HISTORY_SIZE to be set at 32 -#endif - -static struct RLContext test_ctx; - -static char* test_getc_ptr; -static int test_getc(void* data) -{ - return *test_getc_ptr++; -} - -/** Perform a readline test. The function pipes the characters from \a input_buffer - * through the I/O to \c rl_readline(). After the whole string is sent, \c do_test() - * checks if the current history within the context match \a expected_history. - */ -static bool do_test(char* input_buffer, char* expected_history) -{ - rl_init_ctx(&test_ctx); - rl_sethook_get(&test_ctx, test_getc, NULL); - - test_getc_ptr = input_buffer; - while (*test_getc_ptr) - rl_readline(&test_ctx); - - if (memcmp(test_ctx.real_history, expected_history, HISTORY_SIZE) != 0) - { - ASSERT2(0, "history compare failed"); - return false; - } - - return true; -} - -void rl_test(void) -{ - char* test1_in = "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n"; - char test1_hist[HISTORY_SIZE] = "\0l\0m\0n\0o\0p\0q\0r\0s\0t\0u\0v\0w\0x\0y\0z"; - - if (!do_test(test1_in, test1_hist)) - return; - - kprintf("rl_test successful\n"); -} - -#endif /* DEBUG_UNIT_TEST */ - diff --git a/mware/readline.h b/mware/readline.h deleted file mode 100644 index 9219bfd7..00000000 --- a/mware/readline.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * \file - * - * - * \brief Line editing support with history - * - * This file implements a kernel for line editing through a terminal, with history of the typed lines. - * Basic feature of this module: - * - * \li Abstracted from I/O. The user must provide hooks for getc and putc functions. - * \li Basic support for ANSI escape sequences for input of special codes. - * \li Support for command name completion (through a hook). - * - * \version $Id$ - * - * \author Giovanni Bajo - */ - - -#ifndef MWARE_READLINE_H -#define MWARE_READLINE_H - -#include - -#include - -#define HISTORY_SIZE 1024 - -typedef int (*getc_hook)(void* user_data); -typedef void (*putc_hook)(char ch, void* user_data); -typedef const char* (*match_hook)(void* user_data, const char* word, int word_len); -typedef void (*clear_hook)(void* user_data); - -struct RLContext -{ - getc_hook get; - void* get_param; - - putc_hook put; - void* put_param; - - match_hook match; - void* match_param; - - clear_hook clear; - void* clear_param; - - const char* prompt; - - char real_history[HISTORY_SIZE]; - char* history; - size_t history_pos; - size_t line_pos; -}; - -INLINE void rl_init_ctx(struct RLContext *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - ctx->history = ctx->real_history; -} - -INLINE void rl_clear_history(struct RLContext *ctx) -{ - memset(ctx->real_history, 0, sizeof(ctx->real_history)); - ctx->history_pos = 0; - ctx->history = ctx->real_history; -} - -INLINE void rl_sethook_get(struct RLContext* ctx, getc_hook get, void* get_param) -{ ctx->get = get; ctx->get_param = get_param; } - -INLINE void rl_sethook_put(struct RLContext* ctx, putc_hook put, void* put_param) -{ ctx->put = put; ctx->put_param = put_param; } - -INLINE void rl_sethook_match(struct RLContext* ctx, match_hook match, void* match_param) -{ ctx->match = match; ctx->match_param = match_param; } - -INLINE void rl_sethook_clear(struct RLContext* ctx, clear_hook clear, void* clear_param) -{ ctx->clear = clear; ctx->clear_param = clear_param; } - -INLINE void rl_setprompt(struct RLContext* ctx, const char* prompt) -{ ctx->prompt = prompt; } - -const char* rl_readline(struct RLContext* ctx); - -void rl_refresh(struct RLContext* ctx); - -#endif /* MWARE_READLINE_H */ diff --git a/mware/resource.c b/mware/resource.c deleted file mode 100644 index c723bd64..00000000 --- a/mware/resource.c +++ /dev/null @@ -1,113 +0,0 @@ - -#include "resource.h" -#include - -/** - * Internal structure for building a priority queue - * of processes waiting for the resource to become free. - */ -typedef struct ResourceWaiter -{ - PriNode link; - struct Observer *owner; - -} ResourceWaiter; - - -bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest) -{ - bool success = false; - - ASSERT(releaseRequest); - - sem_obtain(&res->lock); - - if (res->owner == releaseRequest) - { - // Already ours - res->pri = pri; - success = true; - } - else if (!res->owner) - { - // Trivial acquire: nobody was owning the resource - res->pri = pri; - res->owner = releaseRequest; - success = true; - } - else - { - ResourceWaiter waiter; - - // Setup waiter structure and enqueue it to resource - waiter.owner = releaseRequest; - waiter.link.pri = pri; - LIST_ENQUEUE(&res->queue, &waiter.link); - - // Resource busy: are we eligible for preemption? - if ((res->pri < pri) && res->owner->event) - res->owner->event(EVENT_RELEASE, res); - - // Wait in the queue until the timeout occurs. - do - { - sem_release(&res->lock); - // TODO: use a semaphore here instead - ResMan_sleep(); - sem_obtain(&res->lock); - - // Check for ownership - if (res->owner == releaseRequest) - { - success = true; - break; - } - } - while (timeout--); - - // Remove pending waiter - if (!success) - REMOVE(&waiter.link.link); - } - - sem_release(&res->lock); - return success; -} - -void ResMan_Free(Resource *res) -{ - ResourceWaiter *waiter; - - sem_obtain(&res->lock); - - - ASSERT(res->owner); - //TODO: check for real owner calling free - - // Check for new owner candidates. - if ((waiter = (ResourceWaiter *)list_remHead(&res->queue))) - { - // Transfer ownership of the resource - res->owner = waiter->owner; - res->pri = waiter->link.pri; - //ResMan_wakeup(waiter); - } - else - { - // Nobody waiting, free the resource - res->owner = NULL; - res->pri = -1; - } - - sem_release(&res->lock); -} - -void ResMan_Init(Resource *res) -{ - res->owner = NULL; - res->pri = -1; - - sem_init(&res->lock); - LIST_INIT(&res->queue); -} - diff --git a/mware/resource.h b/mware/resource.h deleted file mode 100644 index f30b232f..00000000 --- a/mware/resource.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef MWARE_RESOURCE_H -#define MWARE_RESOURCE_H - -#include // time_t -#include - -/* - * Abstract locking primitives used by host OS. - */ -#if CONFIG_KERNEL - - typedef Semaphore ResourceLock; - #define ResMan_sleep() timer_delay(1) - #define ResMan_time_t mtime_t - -#else /* FreeRTOS */ - - #include - #include - #include // vTaskDelay() - - #define ResMan_sleep() vTaskDelay((portTickType)1 * portTICK_RATE_MS) - #define ResMan_time_t portTickType -#endif - - -// Forward decl -struct Observer; - -/** - * Hold context information for a resource such as an audio channel. - * - * Each driver registers one or more Resource instances with the - * ResMan using ResMan_Register(). - * - * Clients can then allocate the resource through ResMan_Alloc() - * providing a desired priority and an Observer for asynchronous - * notification. - * - * Allocated resources can be stolen by other clients asking for a - * higher priority. ResMan notifies a preemption request by invoking - * the Observer of the current owner. - * - * The Observer callback must take whatever action is needed to - * release the resource as soon as possible to avoid blocking the - * new owner. - */ -typedef struct Resource -{ -//Private - /// Control access to fields below. - Semaphore lock; - - /// Pointer to current owner's observer. NULL if resource is free. - struct Observer *owner; - - /// Priority of current owner (higher values mean higher priority). - int pri; - - /// Queue of processes waiting to obtain the resource. - List queue; -} Resource; - -/// Event sent by ResMan to owners when to request resource release. -enum { EVENT_RELEASE = 1 }; - -/// Try to allocate a resource \a res with priority \a pri for at most \a timeout ticks. -bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest); - -/// Free resource \a res. Will eventually wake-up other queued owners. -void ResMan_Free(Resource *res); - -void ResMan_Init(Resource *res); - -#endif /* MWARE_RESOURCE_H */ diff --git a/mware/rle.c b/mware/rle.c deleted file mode 100644 index 3231833b..00000000 --- a/mware/rle.c +++ /dev/null @@ -1,167 +0,0 @@ -/** - * \file - * - * - * \brief General-purpose run-length {en,de}coding algorithm (implementation) - * - * Original source code from http://www.compuphase.com/compress.htm - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/07/19 12:56:28 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.2 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.1 2004/08/04 02:35:54 bernie - *#* Import simple RLE algorithm. - *#* - *#*/ - -#include "rle.h" - - -/** - * Run-length encode \a len bytes from the \a input buffer - * to the \a output buffer. - */ -int rle(unsigned char *output, const unsigned char *input, int len) -{ - int count, index, i; - unsigned char first; - unsigned char *out; - - - out = output; - count = 0; - while (count < len) - { - index = count; - first = input[index++]; - - /* Scan for bytes identical to the first one */ - while ((index < len) && (index - count < 127) && (input[index] == first)) - index++; - - if (index - count == 1) - { - /* Failed to "replicate" the current byte. See how many to copy. - */ - while ((index < len) && (index - count < 127)) - { - /* Avoid a replicate run of only 2-bytes after a literal run. - * There is no gain in this, and there is a risc of loss if the - * run after the two identical bytes is another literal run. - * So search for 3 identical bytes. - */ - if ((input[index] == input[index - 1]) && - ((index > 1) && (input[index] == input[index - 2]))) - { - /* Reset the index so we can back up these three identical - * bytes in the next run. - */ - index -= 2; - break; - } - - index++; - } - - /* Output a run of uncompressed bytes: write length and values */ - *out++ = (unsigned char)(count - index); - for (i = count; i < index; i++) - *out++ = input[i]; - } - else - { - /* Output a compressed run: write length and value */ - *out++ = (unsigned char)(index - count); - *out++ = first; - } - - count = index; - } - - /* Output EOF marker */ - *out++ = 0; - - return (out - output); -} - - -/** - * Run-length decode from the \a input buffer to the \a output - * buffer. - * - * \note The output buffer must be large enough to accomodate - * all decoded output. - */ -int unrle(unsigned char *output, const unsigned char *input) -{ - signed char count; - unsigned char *out; - unsigned char value; - - - out = output; - - for (;;) - { - count = (signed char)*input++; - if (count > 0) - { - /* replicate run */ - value = *input++; - while (count--) - *out++ = value; - } - else if (count < 0) - { - /* literal run */ - while (count++) - *out++ = *input++; - } - else - /* EOF */ - break; - } - - return (out - output); -} diff --git a/mware/rle.h b/mware/rle.h deleted file mode 100644 index 61693a68..00000000 --- a/mware/rle.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * \file - * - * - * \brief General-purpose run-length {en,de}coding algorithm (interface) - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/07/19 12:56:28 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.3 2005/11/04 16:20:02 bernie - *#* Fix reference to README.devlib in header. - *#* - *#* Revision 1.2 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS - *#* - *#* Revision 1.1 2004/08/04 02:35:54 bernie - *#* Import simple RLE algorithm. - *#* - *#*/ -#ifndef RLE_H -#define RLE_H - -int rle(unsigned char *output, const unsigned char *input, int length); -int unrle(unsigned char *output, const unsigned char *input); - -#endif /* RLE_H */ diff --git a/mware/sprintf.c b/mware/sprintf.c deleted file mode 100644 index 0b05ce7b..00000000 --- a/mware/sprintf.c +++ /dev/null @@ -1,154 +0,0 @@ -/** - * \file - * - * - * \brief sprintf() implementation based on _formatted_write() - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include -#include -#include - -#include - - -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_ARG(char, c), UNUSED_ARG(void *, ptr)) -{ - /* nop */ -} - - -int PGM_FUNC(vsprintf)(char *str, const char * PGM_ATTR fmt, va_list ap) -{ - int result; - - if (str) - { - result = PGM_FUNC(_formatted_write)(fmt, __str_put_char, &str, ap); - - /* Terminate string */ - *str = '\0'; - } - else - result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap); - - - return result; -} - - -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); - - return result; -} - -/** - * State information for __sn_put_char() - */ -struct __sn_state -{ - char *str; - size_t len; -}; - -/** - * formatted_write() callback used [v]snprintf(). - */ -static void __sn_put_char(char c, void *ptr) -{ - struct __sn_state *state = (struct __sn_state *)ptr; - - if (state->len) - { - --state->len; - *state->str++ = c; - } -} - - -int PGM_FUNC(vsnprintf)(char *str, size_t size, const char * PGM_ATTR fmt, va_list ap) -{ - int result = 0; - - /* Make room for traling '\0'. */ - if (size--) - { - if (str) - { - struct __sn_state state; - state.str = str; - state.len = size; - - result = PGM_FUNC(_formatted_write)(fmt, __sn_put_char, &state, ap); - - /* Terminate string. */ - *state.str = '\0'; - } - else - result = PGM_FUNC(_formatted_write)(fmt, __null_put_char, 0, ap); - } - - return result; -} - - -int PGM_FUNC(snprintf)(char *str, size_t size, const char * fmt, ...) -{ - int result; - va_list ap; - - va_start(ap, fmt); - result = PGM_FUNC(vsnprintf)(str, size, fmt, ap); - va_end(ap); - - return result; -} diff --git a/mware/sprintf_test.c b/mware/sprintf_test.c deleted file mode 100644 index 1bcedfd3..00000000 --- a/mware/sprintf_test.c +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file - * - * - * \brief sprintf() implementation based on _formatted_write() - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "sprintf.c" -#include "formatwr.c" -#include "hex.c" -#include -#include -#include - -#include /* assert() */ -#include /* strcmp() */ - - -int main(UNUSED_ARG(int, argc), UNUSED_ARG(char **,argv)) -{ - char buf[256]; - static const char test_string[] = "Hello, world!\n"; - static const pgm_char test_string_pgm[] = "Hello, world!\n"; - - snprintf(buf, sizeof buf, "%s", test_string); - assert(strcmp(buf, test_string) == 0); - - snprintf(buf, sizeof buf, "%S", test_string_pgm); - assert(strcmp(buf, test_string_pgm) == 0); - -#define TEST(FMT, VALUE, EXPECT) do { \ - snprintf(buf, sizeof buf, FMT, VALUE); \ - assert(strcmp(buf, EXPECT) == 0); \ - } while (0) - - TEST("%d", 12345, "12345"); - TEST("%ld", 123456789L, "123456789"); - TEST("%ld", -12345678L, "-12345678"); - TEST("%lu", 4294967295UL, "4294967295"); - TEST("%hd", -12345, "-12345"); - TEST("%hu", 65535U, "65535"); - - TEST("%8d", 123, " 123"); - TEST("%8d", -123, " -123"); - TEST("%-8d", -123, "-123 "); - TEST("%08d", -123, "-0000123"); - - TEST("%8.2f", -123.456, " -123.46"); - TEST("%-8.2f", -123.456, "-123.46 "); - TEST("%8.0f", -123.456, " -123"); - -#undef TEST - - /* - * Stress tests. - */ - snprintf(buf, sizeof buf, "%s", NULL); - assert(strcmp(buf, "") == 0); - snprintf(buf, sizeof buf, "%k"); - assert(strcmp(buf, "???") == 0); - sprintf(NULL, test_string); /* must not crash */ - - return 0; -} - diff --git a/mware/strtol10.c b/mware/strtol10.c deleted file mode 100644 index 6521a6a5..00000000 --- a/mware/strtol10.c +++ /dev/null @@ -1,100 +0,0 @@ -/** - * \file - * - * - * \brief Poor man's hex arrays (implementation). - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "strtol10.h" - -/** - * Convert a formatted base-10 ASCII number to unsigned long binary representation. - * - * Unlike the standard strtoul(), this function has an interface - * that makes it better suited for protocol parsers. It's also - * much simpler and smaller than a full featured strtoul(). - * - * \param first Pointer to first byte of input range (STL-style). - * \param last Pointer to end of input range (STL-style). - * Pass NULL to parse up to the first \\0. - * \param val Pointer to converted value. - * - * \return true for success, false for failure. - * - * \see strtol10() - */ -bool strtoul10(const char *first, const char *last, unsigned long *val) -{ - // Check for no input - if (*first == '\0') - return false; - - *val = 0; - for(/*nop*/; first != last && *first != '\0'; ++first) - { - if ((*first < '0') || (*first > '9')) - return false; - - *val = (*val * 10L) + (*first - '0'); - } - - return true; -} - - -/** - * Convert a formatted base-10 ASCII number to signed long binary representation. - * - * \see strtoul10() - */ -bool strtol10(const char *first, const char *last, long *val) -{ - bool negative = false; - - if (*first == '+') - ++first; /* skip unary plus sign */ - else if (*first == '-') - { - negative = true; - ++first; - } - - bool result = strtoul10(first, last, (unsigned long *)val); - - if (negative) - *val = - *val; - - return result; -} - diff --git a/mware/strtol10.h b/mware/strtol10.h deleted file mode 100644 index 4dfe7a47..00000000 --- a/mware/strtol10.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * \file - * - * - * \brief Poor man's hex arrays (implementation). - * - * \version $Id$ - * \author Bernardo Innocenti - */ - - -#ifndef MWARE_STRTOL10_H -#define MWARE_STRTOL10_H - -#include /* bool */ - -bool strtoul10(const char *first, const char *last, unsigned long *val); -bool strtol10(const char *first, const char *last, long *val); - -/** - * Replacement for standard library function atol(). - */ -INLINE long atol(const char *str) -{ - long val; - strtol10(str, NULL, &val); - return val; -} - -/** - * Replacement for standard library function atoi(). - */ -INLINE int atoi(const char *str) -{ - return (int)atol(str); -} - -#endif /* MWARE_STRTOL10_H */ diff --git a/mware/xmodem.c b/mware/xmodem.c deleted file mode 100644 index 030783d3..00000000 --- a/mware/xmodem.c +++ /dev/null @@ -1,433 +0,0 @@ -/** - * \file - * - * \brief X-Modem serial transmission protocol (implementation) - * - * Supports the CRC-16 and 1K-blocks variants of the standard. - * \see ymodem.txt for the protocol description. - * - * \todo Break xmodem_send() and xmodem_recv() in smaller functions. - * - * \todo Maybe convert drv/ser.c to the KFile interface for symmetry and - * flexibility. - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - - -#include "xmodem.h" - -#include -#include /* for memset() */ -#include -#include -#include - - - - -/** - * \name Protocol control codes - * \{ - */ -#define XM_SOH 0x01 /**< Start Of Header (128-byte block) */ -#define XM_STX 0x02 /**< Start Of Header (1024-byte block) */ -#define XM_EOT 0x04 /**< End Of Transmission */ -#define XM_ACK 0x06 /**< Acknowledge block */ -#define XM_NAK 0x15 /**< Negative Acknowledge */ -#define XM_C 0x43 /**< Request CRC-16 transmission */ -#define XM_CAN 0x18 /**< CANcel transmission */ -/*\}*/ - -#define XM_MAXRETRIES 15 /**< Max retries before giving up */ -#define XM_MAXCRCRETRIES 7 /**< Max retries before switching to BCC */ - -#if CONFIG_XMODEM_1KCRC == 1 - #define XM_BUFSIZE 1024 /**< 1024 bytes of block buffer */ -#else - #define XM_BUFSIZE 128 /**< 128 bytes of block buffer */ -#endif - - -#if CONFIG_XMODEM_RECV -/** - * \brief Receive a file using the XModem protocol. - * - * \param port Serial port to use for transfer - * \param fd Destination file - * - * \note This function allocates a large amount of stack (\see XM_BUFSIZE). - */ -bool xmodem_recv(struct Serial *port, KFile *fd) -{ - char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ - int c, i, blocksize; - int blocknr = 0, last_block_done = 0, retries = 0; - char *buf; - uint8_t checksum; - uint16_t crc; - bool purge = false; - bool usecrc = true; - - - XMODEM_PROGRESS("Starting Transfer...\n"); - purge = true; - ser_setstatus(port, 0); - - /* Send initial NAK to start transmission */ - for(;;) - { - if (XMODEM_CHECK_ABORT) - { - ser_putchar(XM_CAN, port); - ser_putchar(XM_CAN, port); - XMODEM_PROGRESS("Transfer aborted\n"); - return false; - } - - /* - * Discard incoming input until a timeout occurs, then send - * a NAK to the transmitter. - */ - if (purge) - { - purge = false; - - if (ser_getstatus(port)) - XMODEM_PROGRESS("Retries %d\n", retries); - - ser_resync(port, 200); - retries++; - - if (retries >= XM_MAXRETRIES) - { - ser_putchar(XM_CAN, port); - ser_putchar(XM_CAN, port); - XMODEM_PROGRESS("Transfer aborted\n"); - return false; - } - - /* Transmission start? */ - if (blocknr == 0) - { - if (retries < XM_MAXCRCRETRIES) - { - XMODEM_PROGRESS("Request Tx (CRC)\n"); - ser_putchar(XM_C, port); - } - else - { - /* Give up with CRC and fall back to checksum */ - usecrc = false; - XMODEM_PROGRESS("Request Tx (BCC)\n"); - ser_putchar(XM_NAK, port); - } - } - else - ser_putchar(XM_NAK, port); - } - - switch (ser_getchar(port)) - { - #if XM_BUFSIZE >= 1024 - case XM_STX: /* Start of header (1024-byte block) */ - blocksize = 1024; - goto getblock; - #endif - - case XM_SOH: /* Start of header (128-byte block) */ - blocksize = 128; - /* Needed to avoid warning if XM_BUFSIZE < 1024 */ - goto getblock; - getblock: - /* Get block number */ - c = ser_getchar(port); - - /* Check complemented block number */ - if ((~c & 0xff) != ser_getchar(port)) - { - XMODEM_PROGRESS("Bad blk (%d)\n", c); - purge = true; - break; - } - - /* Determine which block is being sent */ - if (c == (blocknr & 0xff)) - /* Last block repeated */ - XMODEM_PROGRESS("Repeat blk %d\n", blocknr); - else if (c == ((blocknr + 1) & 0xff)) - /* Next block */ - XMODEM_PROGRESS("Recv blk %d\n", ++blocknr); - else - { - /* Sync lost */ - XMODEM_PROGRESS("Sync lost (%d/%d)\n", c, blocknr); - purge = true; - break; - } - - buf = block_buffer; /* Reset pointer to start of buffer */ - checksum = 0; - crc = 0; - for (i = 0; i < blocksize; i++) - { - if ((c = ser_getchar(port)) == EOF) - { - purge = true; - break; - } - - /* Store in buffer */ - *buf++ = (char)c; - - /* Calculate block checksum or CRC */ - if (usecrc) - crc = UPDCRC16(c, crc); - else - checksum += (char)c; - } - - if (purge) - break; - - /* Get the checksum byte or the CRC-16 MSB */ - if ((c = ser_getchar(port)) == EOF) - { - purge = true; - break; - } - - if (usecrc) - { - crc = UPDCRC16(c, crc); - - /* Get CRC-16 LSB */ - if ((c = ser_getchar(port)) == EOF) - { - purge = true; - break; - } - - crc = UPDCRC16(c, crc); - - if (crc) - { - XMODEM_PROGRESS("Bad CRC: %04x\n", crc); - purge = true; - break; - } - } - /* Compare the checksum */ - else if (c != checksum) - { - XMODEM_PROGRESS("Bad sum: %04x/%04x\n", checksum, c); - purge = true; - break; - } - - /* - * Avoid flushing the same block twice. - * This could happen when the sender does not receive our - * acknowledge and resends the same block. - */ - if (last_block_done < blocknr) - { - /* Call user function to flush the buffer */ - if (fd->write(fd, block_buffer, blocksize)) - { - /* Acknowledge block and clear error counter */ - ser_putchar(XM_ACK, port); - retries = 0; - last_block_done = blocknr; - } - else - { - /* User callback failed: abort transfer immediately */ - retries = XM_MAXRETRIES; - purge = true; - } - } - break; - - case XM_EOT: /* End of transmission */ - ser_putchar(XM_ACK, port); - XMODEM_PROGRESS("Transfer completed\n"); - return true; - - case EOF: /* Timeout or serial error */ - purge = true; - break; - - default: - XMODEM_PROGRESS("Skipping garbage\n"); - purge = true; - break; - } - } /* End forever */ -} -#endif - - -#if CONFIG_XMODEM_SEND -/** - * \brief Transmit some data using the XModem protocol. - * - * \param port Serial port to use for transfer - * \param fd Source file - * - * \note This function allocates a large amount of stack for - * the XModem transfer buffer (\see XM_BUFSIZE). - */ -bool xmodem_send(struct Serial *port, KFile *fd) -{ - char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ - size_t size = -1; - int blocknr = 1, retries = 0, c, i; - bool proceed, usecrc = false; - uint16_t crc; - uint8_t sum; - - /* - * Reading a block can be very slow, so we read the first block early - * to avoid receiving double XM_C char. - * This could happen if we check for XM_C and then read the block, giving - * the receiving device time to send another XM_C char misinterpretating - * the blocks sent. - */ - size = fd->read(fd, block_buffer, XM_BUFSIZE); - - ser_setstatus(port, 0); - ser_purge(port); - XMODEM_PROGRESS("Wait remote host\n"); - - for(;;) - { - proceed = false; - do - { - if (XMODEM_CHECK_ABORT) - return false; - - switch (c = ser_getchar(port)) - { - case XM_NAK: - XMODEM_PROGRESS("Resend blk %d\n", blocknr); - proceed = true; - break; - - case XM_C: - if (c == XM_C) - { - XMODEM_PROGRESS("Tx start (CRC)\n"); - usecrc = true; - } - else - XMODEM_PROGRESS("Tx start (BCC)\n"); - - proceed = true; - break; - - case XM_ACK: - /* End of transfer? */ - if (!size) - return true; - - /* Call user function to read in one block */ - size = fd->read(fd, block_buffer, XM_BUFSIZE); - XMODEM_PROGRESS("Send blk %d\n", blocknr); - blocknr++; - retries = 0; - proceed = true; - break; - - case EOF: - ser_setstatus(port, 0); - retries++; - XMODEM_PROGRESS("Retries %d\n", retries); - if (retries <= XM_MAXRETRIES) - break; - /* falling through! */ - - case XM_CAN: - XMODEM_PROGRESS("Transfer aborted\n"); - return false; - - default: - XMODEM_PROGRESS("Skipping garbage\n"); - break; - } - } - while (!proceed); - - if (!size) - { - ser_putchar(XM_EOT, port); - continue; - } - - /* Pad block with 0xFF if it's partially full */ - memset(block_buffer + size, 0xFF, XM_BUFSIZE - size); - - /* Send block header (STX, blocknr, ~blocknr) */ - #if XM_BUFSIZE == 128 - ser_putchar(XM_SOH, port); - #else - ser_putchar(XM_STX, port); - #endif - ser_putchar(blocknr & 0xFF, port); - ser_putchar(~blocknr & 0xFF, port); - - /* Send block and compute its CRC/checksum */ - sum = 0; - crc = 0; - for (i = 0; i < XM_BUFSIZE; i++) - { - ser_putchar(block_buffer[i], port); - crc = UPDCRC16(block_buffer[i], crc); - sum += block_buffer[i]; - } - - /* Send CRC/Checksum */ - if (usecrc) - { - crc = UPDCRC16(0, crc); - crc = UPDCRC16(0, crc); - ser_putchar(crc >> 8, port); - ser_putchar(crc & 0xFF, port); - } - else - ser_putchar(sum, port); - } -} -#endif diff --git a/mware/xmodem.h b/mware/xmodem.h deleted file mode 100644 index 564a6ff7..00000000 --- a/mware/xmodem.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * \file - * - * \brief X-Modem serial transmission protocol (interface) - * - * \version $Id$ - * \author Bernardo Innocenti - * \author Francesco Sacchi - */ - - -#ifndef MWARE_XMODEM_H -#define MWARE_XMODEM_H -#include -#include - -/** - * Called to know if we want to abort data tranfer. - * Redefine to whatever you need. - * \{ - */ -#ifndef XMODEM_CHECK_ABORT -#define XMODEM_CHECK_ABORT (false) -#endif -/*\}*/ - - -/** - * Called to printf progress messages. - * Default to kprintf debug, redefine to whatever you need. - * \{ - */ -#ifndef XMODEM_PROGRESS -#define XMODEM_PROGRESS(msg, ...) kprintf(msg, ## __VA_ARGS__) -#endif - - -/* fwd decl */ -struct Serial; - -bool xmodem_recv(struct Serial *port, KFile *fd); -bool xmodem_send(struct Serial *port, KFile *fd); - -#endif /* MWARE_XMODEM_H */ diff --git a/net/keytag.c b/net/keytag.c deleted file mode 100644 index 861169b4..00000000 --- a/net/keytag.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * \file - * - * - * \author Andrea Grandi - * - * \brief Tag protocol (protocol). - * - * TAG protocol is decribed in this way: - *
- * ---------------------------------------------------
- * |STX (0x02)|data...(10 HEX chars)|CR|LF|ETX (0x03)|
- * ---------------------------------------------------
- * 
- */ - -#include "keytag.h" - -#include - -#include -#include - -#include -#include - -static void keytag_clearPkt(struct TagPacket *pkt) -{ - pkt->sync = false; - pkt->len = 0; -} - - void keytag_init(struct TagPacket *pkt) - { - keytag_clearPkt(pkt); - } - - void keytag_poll(struct TagPacket *pkt) -{ - int c; - - /* Get all chars from buffer */ - while ((c = kfile_getc(&pkt->tag_ser->fd)) != EOF) - { - /* Search for STX char in received chars */ - if (c == TAG_STX) - { - /* When STX is found a new packet begins */ - if (pkt->sync) - kprintf("TAG double sync!\n"); - keytag_clearPkt(pkt); - pkt->sync = true; - } - else if (pkt->sync) - { - /* Check for end of packet */ - if (c == TAG_ETX) - { - pkt->buf[TAG_MAX_PRINT_CHARS] = '\x0'; - /* Write read TAG on communication serial */ - kfile_printf(&pkt->comm_ser->fd, "tag %s", pkt->buf); - pkt->sync = false; - } - else - { - /* Check for buffer overflow */ - if (pkt->len >= TAG_MAX_LEN) - { - kprintf("TAG buffer overflow\n"); - pkt->sync = false; - } - else - { - /* Add every char after STX to tag reading buffer */ - if (pkt->sync) - { - pkt->buf[pkt->len] = c; - pkt->len++; - } - } - } - } - } -} diff --git a/net/keytag.h b/net/keytag.h deleted file mode 100644 index 541005ea..00000000 --- a/net/keytag.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \file - * - * - * \author Andrea Grandi - * - * \brief Tag protocol. (interface). - */ - -#ifndef NET_KEYTAG_H -#define NET_KEYTAG_H - -#include -#include - -/** - * Starting communication char (STX). - */ -#define TAG_STX 0x02 - -/** - * Ending communication char (ETX). - */ -#define TAG_ETX 0x03 - -/** - * Max buffer lenght - */ -#define TAG_MAX_LEN 14 - -#define TAG_SER_PORT 0 -#define TAG_SER_BAUDRATE 9600 - -/** - * Max number of chars to print in the communication serial - */ -#define TAG_MAX_PRINT_CHARS 12 - -/** - * Structure of a Tag packet - */ -typedef struct TagPacket -{ - KFileSerial *tag_ser; // Tag serial - KFileSerial *comm_ser; // Communication serial - bool sync; // Status flag: true if we find an STX - uint16_t len; // Packet lenght - uint8_t buf[TAG_MAX_LEN]; // Reception buffer -} TagPacket; - -void keytag_init(struct TagPacket *pkt); -void keytag_poll(struct TagPacket *pkt); - -#endif /* NET_TAG_H */ diff --git a/net/pocketbus.c b/net/pocketbus.c deleted file mode 100644 index e793f95d..00000000 --- a/net/pocketbus.c +++ /dev/null @@ -1,260 +0,0 @@ -/** - * \file - * - * - * \version $Id: pocketbus.c 20131 2007-12-13 17:39:55Z batt $ - * - * \author Francesco Sacchi - * - * \brief pocketBus protocol implementation. - * - * pocketBus protocol is a simple strictly master-slave protocol, usable - * in embedded systems. - * pocketBus frame is as follows: - *
- * +----------------------------------------+
- * | STX | VER | ADDR | PAYLOAD | CKS | ETX |
- * +----------------------------------------+
- * |     |     |      |         |     |     |
- * + 1B  + 1B  +  2B  + N Byte  + 2B  + 1B  +
- * 
- * - * - STX, 1 byte (0x02), packet start - * - VER, 1 byte, packet version - * - ADDR, 2 byte, slave address - * - PAYLOAD, N byte, data field - * - CKS, 2 byte, checksum - * - ETX, 1 byte, (0x03) packet end - * - * Protocol parsing start on STX reception. When the receiving routine - * finds an STX char, it starts to read characters from the bus - * until an ETX is received. Once a packet is received, - * the parser checks packet correctness and checksum. If all is OK - * the payload is returned. - * - * STX (0x02), ETX(0x03) and ESC(0x1B) are special characters and cannot be - * transmitted inside payload without escaping them. - * To escape a character you must precede it by the ESC char. - * E.G. STX -> ESC + STX - * ETX -> ESC + ETX - * ESC -> ESC + ESC - * - * In the ADDR field is always specified the slave address. - * In the case of master trasmitting, ADDR contains the slave destination - * address. - * In case of slave replying, ADDR contains the slave address itself. - * Thus, the master device does not have an address. Packet must be routed to - * master by hardware bus design. - * - * The checksum algorithm used is rotating hash algortihm, quite simple but more - * reliable than simple checksum. - * The checksum in computed on all fields excluding STX, ETX and CHK fields itself. - * Checksum is computed on the packet *before* escaping. - * Escape sequence counts for 1 character only (the escaped one). - */ - -#include "pocketbus.h" - -#include -#include - -#include - -#include - -#include - -/** - * Send a character over pocketBus channel stream, handling escape mode. - */ -void pocketbus_putchar(struct PocketBusCtx *ctx, uint8_t c) -{ - /* Update checksum */ - rotating_update1(c, &ctx->out_cks); - - /* Escape characters with special meaning */ - if (c == POCKETBUS_ESC || c == POCKETBUS_STX || c == POCKETBUS_ETX) - kfile_putc(POCKETBUS_ESC, ctx->fd); - - kfile_putc(c, ctx->fd); -} - -/** - * Send pocketBus packet header. - */ -void pocketbus_begin(struct PocketBusCtx *ctx, pocketbus_addr_t addr) -{ - PocketBusHdr hdr; - - hdr.ver = POCKETBUS_VER; - hdr.addr = cpu_to_be16(addr); - rotating_init(&ctx->out_cks); - - /* Send STX */ - kfile_putc(POCKETBUS_STX, ctx->fd); - - /* Send header */ - pocketbus_write(ctx, &hdr, sizeof(hdr)); -} - -/** - * Send buffer \a _data over bus, handling escape. - */ -void pocketbus_write(struct PocketBusCtx *ctx, const void *_data, size_t len) -{ - const uint8_t *data = (const uint8_t *)_data; - - while (len--) - pocketbus_putchar(ctx, *data++); -} - -/** - * Send pocketBus packet tail. - */ -void pocketbus_end(struct PocketBusCtx *ctx) -{ - /* Send checksum */ - rotating_t cks = cpu_to_be16(ctx->out_cks); - pocketbus_write(ctx, &cks, sizeof(cks)); - - /* Send ETX */ - kfile_putc(POCKETBUS_ETX, ctx->fd); -} - -/** - * Send buffer of \a data to address \a addr with a pocketBus packet over channel stream. - */ -void pocketbus_send(struct PocketBusCtx *ctx, pocketbus_addr_t addr, const void *data, size_t len) -{ - pocketbus_begin(ctx, addr); - - /* Send data */ - pocketbus_write(ctx, data, len); - - pocketbus_end(ctx); -} - - -/** - * Try to read a packet from the pocketBus. - * \return true if a packet is received, false otherwise. - */ -bool pocketbus_recv(struct PocketBusCtx *ctx, struct PocketMsg *msg) -{ - int c; - - /* Process incoming characters until buffer is not empty */ - while ((c = kfile_getc(ctx->fd)) != EOF) - { - /* Look for STX char */ - if (c == POCKETBUS_STX && !ctx->escape) - { - /* When an STX is found, inconditionally start a new packet */ - if (ctx->sync) - kprintf("pocketBus double sync!\n"); - - ctx->sync = true; - ctx->len = 0; - rotating_init(&ctx->in_cks); - continue; - } - - if (ctx->sync) - { - /* Handle escape mode */ - if (c == POCKETBUS_ESC && !ctx->escape) - { - ctx->escape = true; - continue; - } - - /* Handle message end */ - if (c == POCKETBUS_ETX && !ctx->escape) - { - ctx->sync = false; - - /* Check minimum size */ - if (ctx->len < sizeof(PocketBusHdr) + sizeof(rotating_t)) - { - kprintf("pocketBus short pkt!\n"); - continue; - } - - /* Remove checksum bytes from packet len */ - ctx->len -= sizeof(rotating_t); - - /* Compute checksum */ - rotating_update(ctx->buf, ctx->len, &ctx->in_cks); - rotating_t recv_cks = be16_to_cpu(*((rotating_t *)(ctx->buf + ctx->len))); - - /* Checksum check */ - if (recv_cks == ctx->in_cks) - { - PocketBusHdr *hdr = (PocketBusHdr *)(ctx->buf); - /* Check packet version */ - if (hdr->ver == POCKETBUS_VER) - { - /* Packet received, set msg fields */ - msg->payload = ctx->buf + sizeof(PocketBusHdr); - msg->addr = be16_to_cpu(hdr->addr); - msg->len = ctx->len - sizeof(PocketBusHdr); - msg->ctx = ctx; - return true; - } - else - { - kprintf("pocketBus version mismatch, here[%d], there[%d]\n", POCKETBUS_VER, hdr->ver); - continue; - } - } - else - { - kprintf("pocketBus cks error, here[%04X], there[%04X]\n", ctx->in_cks, recv_cks); - continue; - } - - } - - ctx->escape = false; - - /* Check buffer overflow: simply ignore - received data and go to unsynced state. */ - if (ctx->len >= CONFIG_POCKETBUS_BUFLEN) - { - kprintf("pocketBus buffer overflow\n"); - ctx->sync = false; - continue; - } - - /* Put received data in the buffer */ - ctx->buf[ctx->len] = c; - ctx->len++; - } - } - - /* - * Check stream status. - */ - if (kfile_error(ctx->fd)) - { - TRACEMSG("fd status[%04X]", kfile_error(ctx->fd)); - kfile_clearerr(ctx->fd); - } - - return false; -} - - -/** - * Initialize pocketBus protocol handler. - */ -void pocketbus_init(struct PocketBusCtx *ctx, struct KFile *fd) -{ - ASSERT(ctx); - ASSERT(fd); - - memset(ctx, 0, sizeof(*ctx)); - ctx->fd = fd; -} diff --git a/net/pocketbus.h b/net/pocketbus.h deleted file mode 100644 index 397cd6eb..00000000 --- a/net/pocketbus.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * \file - * - * - * \version $Id: pocketbus.h 20131 2007-12-13 17:39:55Z batt $ - * - * \author Francesco Sacchi - * - * \brief pocketBus protocol interface. - */ - -#ifndef NET_POCKETBUS_H -#define NET_POCKETBUS_H - -#include -#include -#include -#include -#include "appconfig.h" //for CONFIG_POCKETBUS_BUFLEN - -/** - * pocketBus special characters definitions. - * \{ - */ -#define POCKETBUS_STX 0x02 //ASCII STX -#define POCKETBUS_ETX 0x03 //ASCII ETX -#define POCKETBUS_ESC 0x1B //ASCII ESC -#define POCKETBUS_ACK 0x06 //ASCII ACK -#define POCKETBUS_NAK 0x15 //ASCII NAK -/*\}*/ - -#define POCKETBUS_BROADCAST_ADDR 0xFFFF ///< pocketBus broadcast address - -/** - * Type for pocketBus length. - */ -typedef uint16_t pocketbus_len_t; - -/** - * Type for pocketBus addresses. - */ -typedef uint16_t pocketbus_addr_t; - -/** - * Header of pocketBus messages. - */ -typedef struct PocketBusHdr -{ - #define POCKETBUS_VER 1 - uint8_t ver; ///< packet version - pocketbus_addr_t addr; ///< slave address -} PocketBusHdr; - -/** - * pocketBus context structure. - */ -typedef struct PocketBusCtx -{ - struct KFile *fd; ///< File descriptor - bool sync; ///< Status flag: true if we have received an STX, false otherwise - bool escape; ///< Status flag: true if we are in escape mode, false otherwise - rotating_t in_cks; ///< Checksum computation for received data. - rotating_t out_cks; ///< Checksum computation for transmitted data. - pocketbus_len_t len; ///< Received length - uint8_t buf[CONFIG_POCKETBUS_BUFLEN]; ///< receiving Buffer -} PocketBusCtx; - -/** - * Structure holding pocketBus message parameters. - */ -typedef struct PocketMsg -{ - struct PocketBusCtx *ctx; ///< pocketBus message context - pocketbus_addr_t addr; ///< address for received packet - pocketbus_len_t len; ///< payload length - const uint8_t *payload; ///< payload data -} PocketMsg; - -/** - * This ensure that endianess convertion functions work on - * the right data size. - * \{ - */ -STATIC_ASSERT(sizeof(pocketbus_addr_t) == sizeof(uint16_t)); -STATIC_ASSERT(sizeof(rotating_t) == sizeof(uint16_t)); -/*\}*/ - -void pocketbus_putchar(struct PocketBusCtx *ctx, uint8_t c); -void pocketbus_begin(struct PocketBusCtx *ctx, pocketbus_addr_t addr); -void pocketbus_write(struct PocketBusCtx *ctx, const void *_data, size_t len); -void pocketbus_end(struct PocketBusCtx *ctx); - -void pocketbus_send(struct PocketBusCtx *ctx, pocketbus_addr_t addr, const void *data, size_t len); -bool pocketbus_recv(struct PocketBusCtx *ctx, struct PocketMsg *msg); -void pocketbus_init(struct PocketBusCtx *ctx, struct KFile *fd); - -#endif /* NET_POCKETBUS_H */ diff --git a/net/pocketcmd.c b/net/pocketcmd.c deleted file mode 100644 index d59cbf41..00000000 --- a/net/pocketcmd.c +++ /dev/null @@ -1,167 +0,0 @@ -/** - * \file - * - * - * \version $Id: pocketcmd.c 16587 2007-10-02 14:31:02Z batt $ - * - * \author Francesco Sacchi - * - * \brief pocketBus protocol Command layer implementation. - * - * This module implements command layer over pocketBus - * protocol. - * Payload packets received by pocketBus are first checked for - * address matching. - * If a packet is addressed to us we look for a suitable - * callback function to call. - * - * The received payload format is as follows: - *
- * +----------------------------------------+
- * |  CMD |            DATA                 |
- * +----------------------------------------+
- * |      |                                 |
- * +  2B  +           0..N Byte             +
- * 
- * - * The CMD ID used is the same supplied by the master when - * the command was sent. - */ - -#include "pocketcmd.h" -#include "pocketbus.h" - -#include -#include -#include - -#include - -#include - -#include - -/** - * pocketBus Command poll function. - * Call it to read and process pocketBus commands. - */ -void pocketcmd_poll(struct PocketCmdCtx *ctx) -{ - PocketMsg msg; - - /* Try to read a packet from pocketBus */ - while (pocketbus_recv(ctx->bus_ctx, &msg)) - { - /* Check address */ - if (msg.addr == ctx->addr || - msg.addr == POCKETBUS_BROADCAST_ADDR) - { - const PocketCmdHdr *hdr = (const PocketCmdHdr *)msg.payload; - pocketcmd_t cmd = be16_to_cpu(hdr->cmd); - - /* We're no longer waiting for a reply (in case we were) */ - if (cmd == ctx->waiting) - ctx->waiting = PKTCMD_NULL; - - /* Check for command callback */ - pocketcmd_hook_t callback = ctx->search(cmd); - - /* Call it if exists */ - if (callback) - { - PocketCmdMsg cmd_msg; - - cmd_msg.cmd_ctx = ctx; - cmd_msg.cmd = cmd; - cmd_msg.len = msg.len - sizeof(PocketCmdHdr); - cmd_msg.buf = msg.payload + sizeof(PocketCmdHdr); - - callback(&cmd_msg); - } - } - } -} - -/** - * Send command \a cmd to/from slave adding \a len arguments in \a buf. - * Address used is contained in \a ctx->addr . - * If we are master and the message has a reply, you must set \a wait_reply to true. - * \return true if all is ok, false if we are already waiting a replay from another slave. - */ -bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool wait_reply) -{ - /* Check if we are waiting a reply from someone */ - if (ctx->waiting != PKTCMD_NULL) - { - /* Check is reply timeout is elapsed */ - if (timer_clock() - ctx->reply_timer < ms_to_ticks(PKTCMD_REPLY_TIMEOUT)) - { - TRACEMSG("Pkt discard! waiting cmd[%04X]\n", ctx->waiting); - return false; - } - else - { - TRACEMSG("Timeout waiting cmd[%04X]\n", ctx->waiting); - ctx->waiting = PKTCMD_NULL; - } - } - - /* Endianess! */ - cmd = cpu_to_be16(cmd); - - /* Send packet */ - pocketbus_begin(ctx->bus_ctx, ctx->addr); - pocketbus_write(ctx->bus_ctx, &cmd, sizeof(cmd)); - pocketbus_write(ctx->bus_ctx, buf, len); - pocketbus_end(ctx->bus_ctx); - - if (wait_reply) - { - ctx->waiting = cmd; - ctx->reply_timer = timer_clock(); - } - return true; -} - -/** - * Init pocketBus command layer. - * \a ctx is pocketBus command layer context. - * \a bus_ctx is pocketBus context. - * \a addr is slave address (see pocketcmd_setAddr for details.) - * \a search is the lookup function used to search command ID callbacks. - */ -void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search) -{ - ASSERT(ctx); - ASSERT(bus_ctx); - ASSERT(search); - MOD_CHECK(timer); - - memset(ctx, 0, sizeof(*ctx)); - ctx->bus_ctx = bus_ctx; - ctx->search = search; - pocketcmd_setAddr(ctx, addr); -} - -/** - * Helper function used to reply to master with an ACK. - */ -void pocketcmd_replyAck(struct PocketCmdMsg *msg) -{ - uint8_t ack[] = { POCKETBUS_ACK }; - - pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, ack, sizeof(ack)); -} - -/** - * Helper function used to reply to master with a NAK. - */ -void pocketcmd_replyNak(struct PocketCmdMsg *msg) -{ - uint8_t nak[] = { POCKETBUS_NAK }; - - pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, nak, sizeof(nak)); -} - diff --git a/net/pocketcmd.h b/net/pocketcmd.h deleted file mode 100644 index 7045f3fe..00000000 --- a/net/pocketcmd.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * \file - * - * - * \version $Id: pocketcmd.h 20030 2007-12-04 16:16:09Z batt $ - * - * \author Francesco Sacchi - * - * \brief pocketBus protocol command layer interface. - */ - -#ifndef NET_POCKETCMD_H -#define NET_POCKETCMD_H - -#include "pocketbus.h" -#include - -#define PKTCMD_NULL 0 ///< pocketBus Null command - -#define PKTCMD_REPLY_TIMEOUT 50 ///< Command replay timeout in milliseconds - -typedef uint16_t pocketcmd_t; ///< Type for Command IDs - -/** - * Header for transmitted pocketBus Commands. - */ -typedef struct PocketCmdHdr -{ - pocketcmd_t cmd; ///< command ID -} PocketCmdHdr; - -/** - * This ensure that endianess convertion functions work on - * the right data size. - * \{ - */ -STATIC_ASSERT(sizeof(pocketcmd_t) == sizeof(uint16_t)); -/*\}*/ - -/* fwd declaration */ -struct PocketCmdCtx; - -/** - * pocketBus command message structure. - */ -typedef struct PocketCmdMsg -{ - struct PocketCmdCtx *cmd_ctx; ///< command context - pocketcmd_t cmd; ///< command id - pocketbus_len_t len; ///< optional arg length - const uint8_t *buf; ///< optional arguments -} PocketCmdMsg; - -/** - * Type for command hooks. - */ -typedef void (*pocketcmd_hook_t)(struct PocketCmdMsg *cmd_msg); - -/** - * Type for lookup function hooks. - */ -typedef pocketcmd_hook_t (*pocketcmd_lookup_t)(pocketcmd_t cmd); - -/** - * pocketBus context for command layer communications. - */ -typedef struct PocketCmdCtx -{ - struct PocketBusCtx *bus_ctx; ///< pocketBus context - pocketbus_addr_t addr; ///< Our address - pocketcmd_lookup_t search; ///< Lookup function used to search for command callbacks - pocketcmd_t waiting; ///< The command ID we are waiting for or PKTCMD_NULL. - ticks_t reply_timer; ///< For waiting_reply -} PocketCmdCtx; - -/** - * Set slave address \a addr for pocketBus command layer. - * If we are a slave this is *our* address. - * If we are the master this is the slave address to send messages to. - */ -INLINE void pocketcmd_setAddr(struct PocketCmdCtx *ctx, pocketbus_addr_t addr) -{ - ctx->addr = addr; -} - -void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search); -void pocketcmd_poll(struct PocketCmdCtx *ctx); -bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool has_replay); -void pocketcmd_replyNak(struct PocketCmdMsg *msg); -void pocketcmd_replyAck(struct PocketCmdMsg *msg); - -/** - * Helper function used by master to send a command to slave \a addr. - */ -INLINE bool pocketcmd_masterSend(struct PocketCmdCtx *ctx, pocketbus_addr_t addr, pocketcmd_t cmd, const void *buf, size_t len) -{ - pocketcmd_setAddr(ctx, addr); - return pocketcmd_send(ctx, cmd, buf, len, true); -} - -/** - * Helper function used by slave to reply to a master command. - */ -INLINE bool pocketcmd_slaveReply(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len) -{ - return pocketcmd_send(ctx, cmd, buf, len, false); -} - - -#endif /* NET_POCKETCMD_H */ diff --git a/os/hptime.c b/os/hptime.c deleted file mode 100644 index b93712ba..00000000 --- a/os/hptime.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - * \file - * - * - * \brief Portable abstraction for high-resolution time handling (implementation) - * - * \version $Id$ - * \author Bernardo Innocenti - */ - -#include "hptime.h" - -#if defined(_WIN32) - -#include - -hptime_t hptime_get(void) -{ - FILETIME ft; - - /* - * La precisione dei FileTime sarebbe 100ns, ma il - * valore viene ottenuto convertendo una struttura - * SYSTEMTIME, che ha precisione di 1ms. Il numero - * che otteniamo e' quindi sempre un multiplo di - * 100000. - */ - GetSystemTimeAsFileTime(&ft); - - /* Copy the upper/lower into a quadword. */ - return (((hptime_t)ft.dwHighDateTime) << 32) + (hptime_t)ft.dwLowDateTime; -} - -#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - -#include /* for gettimeofday() */ -#include /* for NULL */ - -hptime_t hptime_get(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return (hptime_t)tv.tv_sec * HPTIME_TICKS_PER_SECOND - + (hptime_t)tv.tv_usec; -} - -#else /* !__unix__ */ - #error OS dependent support code missing for this OS -#endif /* !__unix__ */ - diff --git a/os/hptime.h b/os/hptime.h deleted file mode 100644 index 7e5b88a0..00000000 --- a/os/hptime.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * \file - * - * - * \brief Portable abstraction for high-resolution time handling (interface) - * - * \author Bernardo Innocenti - */ -#ifndef HPTIME_H -#define HPTIME_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef _WIN32 - - /** our type for "high precision absolute time" */ - typedef __int64 hptime_t; - - #define HPTIME_TICKS_PER_SECOND (10000000I64) - #define HPTIME_TICKS_PER_MILLISEC (10000I64) - #define HPTIME_TICKS_PER_MICRO (10I64) - -#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - - #include /* int64_t */ - - #ifndef DEVLIB_MTIME_DEFINED - #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with */ - typedef int32_t mtime_t; - #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR) - #define MTIME_INFINITE 0x7FFFFFFFL - #endif - - /** Type for "high precision absolute time". */ - typedef int64_t hptime_t; - - #define HPTIME_TICKS_PER_SECOND (1000000LL) - #define HPTIME_TICKS_PER_MILLISEC (1000LL) - #define HPTIME_TICKS_PER_MICRO (1LL) - -#else /* !__unix__ */ - #error OS dependent support code missing for this OS -#endif /* !__unix__ */ - -/** - * Return the current time with the maximum precision made available from the hosting OS - */ -extern hptime_t hptime_get(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* HPTIME_H */ diff --git a/rules.mk b/rules.mk deleted file mode 100644 index a3ce5842..00000000 --- a/rules.mk +++ /dev/null @@ -1,290 +0,0 @@ -# -# $Id$ -# Copyright 2002,2003,2004,2005,2006 Develer S.r.l. (http://www.develer.com/) -# All rights reserved. -# -# Based on: -# GCC-AVR standard Makefile part 2 -# Volker Oth 1/2000 -# -# Author: Bernardo Innocenti -# - -# Remove all default pattern rules -.SUFFIXES: - -# Verbosity -ifeq ($(V),1) -# Verbose build -Q := -L := @echo >/dev/null -else -# Quiet build -Q := @ -L := @echo -endif - -# Select Bourne Again SHell as default make shell -SHELL := bash - -# Checker build -ifeq ($(C),1) -CC = $(CHECKER) -CFLAGS += -Wundef -D__x86_64__=1 -D__unix__=1 -D__linux__=1 -D__STDC_VERSION__=199901L -endif - -# Initialize $(top_srcdir) with current directory, unless it was already initialized -top_srcdir ?= $(shell pwd) - -# Products -TRG_ELF = $(TRG:%=$(OUTDIR)/%.elf) -TRG_S19 = $(TRG:%=$(OUTDIR)/%.s19) -TRG_HEX = $(TRG:%=$(OUTDIR)/%.hex) -TRG_BIN = $(TRG:%=$(OUTDIR)/%.bin) -TRG_ROM = $(TRG:%=$(OUTDIR)/%.rom) -TRG_COF = $(TRG:%=$(OUTDIR)/%.cof) -TRG_EXE = $(TRG:%=$(OUTDIR)/%) - - -RECURSIVE_TARGETS = all-recursive install-recursive clean-recursive - -# The default target -.PHONY: all -ifeq ($(EMBEDDED_TARGET),1) -all:: all-recursive $(TRG_S19) $(TRG_HEX) $(TRG_BIN) -else -all:: all-recursive $(TRG_EXE) -endif - -# Generate project documentation -.PHONY: docs -docs: - $L "Building documentation" - $Q $(DOXYGEN) - -# Generate ctags -.PHONY: tags -tags: - $L "Rebuilding C tags database" - $Q ctags -R --exclude=doc - -# Run testsuite -.PHONY: check -check: - $L "Running testsuite" - $Q ./run_tests.sh - -define build_target - -ifneq ($$(strip $$($(1)_MCU)),) -# Define all project specific object files -$(1)_CFLAGS += -mmcu=$$($(1)_MCU) -$(1)_CXXFLAGS += -mmcu=$$($(1)_MCU) -$(1)_ASFLAGS += -mmcu=$$($(1)_MCU) -$(1)_CPPAFLAGS += -mmcu=$$($(1)_MCU) -$(1)_LDFLAGS += -mmcu=$$($(1)_MCU) -endif -ifneq ($$(strip $$($(1)_CPU)),) -# Define all project specific object files -$(1)_CFLAGS += -mcpu=$$($(1)_CPU) -$(1)_CXXFLAGS += -mcpu=$$($(1)_CPU) -$(1)_ASFLAGS += -mcpu=$$($(1)_CPU) -$(1)_CPPAFLAGS += -mcpu=$$($(1)_CPU) -$(1)_LDFLAGS += -mcpu=$$($(1)_CPU) -endif -ifneq ($$(strip $$($(1)_LDSCRIPT)),) -$(1)_LDFLAGS += -Wl,-T$$($(1)_LDSCRIPT) -endif - -$(1)_CC = $$($(1)_CROSS)$$(CC) -$(1)_CXX = $$($(1)_CROSS)$$(CXX) -$(1)_AS = $$($(1)_CROSS)$$(AS) -$(1)_OBJCOPY = $$($(1)_CROSS)$$(OBJCOPY) - -$(1)_COBJ = $$(foreach file,$$($(1)_CSRC:%.c=%.o),$$(OBJDIR)/$(1)/$$(file)) -$(1)_CXXOBJ = $$(foreach file,$$($(1)_CXXSRC:%.cpp=%.o),$$(OBJDIR)/$(1)/$$(file)) -$(1)_PCOBJ = $$(foreach file,$$($(1)_PCSRC:%.c=%_P.o),$$(OBJDIR)/$(1)/$$(file)) -$(1)_AOBJ = $$(foreach file,$$($(1)_ASRC:%.s=%.o),$$(OBJDIR)/$(1)/$$(file)) -$(1)_CPPAOBJ = $$(foreach file,$$($(1)_CPPASRC:%.S=%.o),$$(OBJDIR)/$(1)/$$(file)) -$(1)_OBJ := $$($(1)_COBJ) $$($(1)_CXXOBJ) $$($(1)_PCOBJ) $$($(1)_AOBJ) $$($(1)_CPPAOBJ) -$(1)_SRC := $$($(1)_CSRC) $$($(1)_CXXSRC) $$($(1)_PCSRC) $$($(1)_ASRC) $$($(1)_CPPASRC) -OBJ += $$($(1)_OBJ) - -ifneq ($$(strip $$($(1)_CXXSRC)),) -$(1)_LD = $$($(1)_CROSS)$$(LDXX) -else -$(1)_LD = $$($(1)_CROSS)$$(LD) -endif - -# Compile: instructions to create assembler and/or object files from C source -$$($(1)_COBJ) : $$(OBJDIR)/$(1)/%.o : %.c - $L "$(1): Compiling $$< (C)" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CC) -c $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ - -# Compile: instructions to create assembler and/or object files from C++ source -$$($(1)_CXXOBJ) : $$(OBJDIR)/$(1)/%.o : %.cpp - $L "$(1): Compiling $$< (C++)" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CXX) -c $$(CXXFLAGS) $$($(1)_CXXFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ - -# Generate assembly sources from C files (debug) -$$(OBJDIR)/$(1)/%.s : %.c - $L "$(1): Generating asm source $$<" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CC) -S $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$< -o $$@ - -# Generate special progmem variant of a source file -$$($(1)_PCOBJ) : $$(OBJDIR)/$(1)/%_P.o : %.c - $L "$(1): Compiling $$< (PROGMEM)" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CC) -c -D_PROGMEM $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ - -# Assemble: instructions to create object file from assembler files -$$($(1)_AOBJ): $$(OBJDIR)/$(1)/%.o : %.s - $L "$(1): Assembling $$<" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_AS) -c $$(ASFLAGS) $$($(1)_ASFLAGS) $$< -o $$@ - -$$($(1)_CPPAOBJ): $$(OBJDIR)/$(1)/%.o : %.S - $L "$(1): Assembling with CPP $$<" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CC) -c $$(CPPAFLAGS) $$($(1)_CPPAFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@ - - -# Link: instructions to create elf output file from object files -$$(OUTDIR)/$(1).elf $$(OUTDIR)/$(1)_nostrip: bumprev $$($(1)_OBJ) $$($(1)_LDSCRIPT) - $L "$(1): Linking $$@" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_LD) $$($(1)_OBJ) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@ - -# Strip debug info -$$(OUTDIR)/$(1): $$(OUTDIR)/$(1)_nostrip - $L "$(1): Generating stripped executable $$@" - $Q $$($(1)_STRIP) -o $$@ $$^ - -# Compile and link (program-at-a-time) -$$(OUTDIR)/$(1)_whole.elf: bumprev $$($(1)_SRC) $$($(1)_LDSCRIPT) - $L "$(1): Compiling and Linking whole program $$@" - @$$(MKDIR_P) $$(dir $$@) - $Q $$($(1)_CC) $$($(1)_SRC) $$(CFLAGS) $$($(1)_CFLAGS) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@ - -# Flash target -# NOTE: we retry in case of failure because the STK500 programmer is crappy -.PHONY: flash_$(1) -flash_$(1): $(OUTDIR)/$(1).s19 flash_$(1)_local - if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U flash:w:$$< ; then \ - $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U flash:w:$$< ; \ - fi - #avarice --mkII -j usb --erase --program --verify --file images/triface.elf - -.PHONY: flash_$(1)_local -flash_$(1)_local: - -.PHONY: fuses_$(!) -fuses_$(1): - if [ ! -z "$$($(1)_efuse)" ] ; then \ - if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U efuse:w:$$($(1)_efuse):m ; then \ - $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U efuse:w:$$($(1)_efuse):m ; \ - fi \ - fi - if [ ! -z "$$($(1)_hfuse)" ] ; then \ - if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U hfuse:w:$$($(1)_hfuse):m ; then \ - $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U hfuse:w:$$($(1)_hfuse):m ; \ - fi \ - fi - if [ ! -z "$$($(1)_lfuse)" ] ; then \ - if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lfuse:w:$$($(1)_lfuse):m ; then \ - $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lfuse:w:$$($(1)_lfuse):m ; \ - fi \ - fi - if [ ! -z "$$($(1)_lock)" ] ; then \ - if ! $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lock:w:$$($(1)_lock):m ; then \ - $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lock:w:$$($(1)_lock):m ; \ - fi \ - fi - -$$(OUTDIR)/$(1).hex: $$(OUTDIR)/$(1).elf - $$($(1)_OBJCOPY) -O ihex $$< $$@ - -$$(OUTDIR)/$(1).s19: $$(OUTDIR)/$(1).elf - $$($(1)_OBJCOPY) -O srec $$< $$@ - -$$(OUTDIR)/$(1).bin: $$(OUTDIR)/$(1).elf - $$($(1)_OBJCOPY) -O binary $$< $$@ - -$$(OUTDIR)/$(1).obj: $$(OUTDIR)/$(1).elf - $$($(1)_OBJCOPY) -O avrobj $$< $$@ - -$$(OUTDIR)/$(1).rom: $$(OUTDIR)/$(1).elf - $$($(1)_OBJCOPY) -O $$(FORMAT) $$< $$@ -# $$($(1)_OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" -O $$(FORMAT) $$< $$(@:.rom=.eep) - -endef - -# Generate build rules for all targets -$(foreach t,$(TRG),$(eval $(call build_target,$(t)))) - -# Generate Qt's moc files from headers -# NOTE: moc totally sucks and can generate empty files for some error conditions, -# leading to puzzling linker errors. Kill 'em and abort build. -%_moc.cpp: %.h - $(MOC) -o $@ $< - if [ ! -s $< ]; then \ - rm -f $@; \ - exit 1; \ - fi - - -%.cof: %.elf - $(COFFCONVERT) -O coff-ext-avr $< $@ -# $(COFFCONVERT) -O coff-avr $< $@ # For use with AVRstudio 3 - -#make instruction to delete created files -clean: clean-recursive - -$(RM_R) $(OBJDIR) - -$(RM_R) $(OUTDIR) - -$(RECURSIVE_TARGETS): - @target=`echo $@ | sed s/-recursive//`; \ - for dir in $(SUBDIRS); do \ - if [ -e $$dir/configure.in ] || [ -e $$dir/configure.ac ] && [ ! -x $$dir/configure ]; then \ - echo "Running autogen.sh in $$dir..."; \ - ( cd $$dir && chmod a+x autogen.sh && ./autogen.sh && rm -f Makefile || exit 1 ); \ - fi; \ - if [ ! -e $$dir/Makefile ]; then \ - if [ -e "$$dir/build-$(ARCH)" ]; then \ - echo "Running build script in $$dir..."; \ - ( cd $$dir && chmod a+x build && ./build || exit 1 ); \ - else \ - echo "Running configure in $$dir..."; \ - ( cd $$dir && ./configure --prefix=$(PREFIX) || exit 1 ); \ - fi; \ - fi; \ - $(MAKE) -C $$dir $$target || exit 1; \ - done - -BUILDREV_H = buildrev.h - -ifeq ($(shell [ -e verstag.c ] && echo yes),yes) -.PHONY: bumprev -bumprev: - @buildnr=0; \ - if [ -f $(BUILDREV_H) ]; then \ - buildnr=`sed <"$(BUILDREV_H)" -n -e 's/#define VERS_BUILD \([0-9][0-9]*\)/\1/p'`; \ - fi; \ - buildnr=`expr $$buildnr + 1`; \ - buildhost=`hostname`; \ - echo "#define VERS_BUILD $$buildnr" >"$(BUILDREV_H)"; \ - echo "#define VERS_HOST \"$$buildhost\"" >>"$(BUILDREV_H)"; \ - echo "Building revision $$buildnr" -else -.PHONY: bumprev -bumprev: - -endif - -# Include dependencies -ifneq ($(strip $(OBJ)),) --include $(OBJ:%.o=%.d) -endif diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index 7edc89df..00000000 --- a/run_tests.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -# -# Copyright 2005 Develer S.r.l. (http://www.develer.com/) -# All rights reserved. -# -# Author: Bernardo Innocenti -# -# $Id$ -# - - -VERBOSE=1 - -CC=gcc -CFLAGS="-W -Wall -Wextra -I. -fno-builtin -D_DEBUG" - -CXX=g++ -CXXFLAGS="$CFLAGS" - - -for test in `find . -name "*_test.*"`; do - [ $VERBOSE -gt 0 ] && echo "Running $test..." - case "$test" in - *.cpp) - $CXX $CXXFLAGS $test -o test || exit 1 - ./test || exit 1 - rm -f test - ;; - *.c) - $CC $CFLAGS $test -o test || exit 1 - ./test || exit 1 - rm -f test - ;; - esac -done - diff --git a/verstag.c b/verstag.c deleted file mode 100644 index a99e2b2c..00000000 --- a/verstag.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Define application version strings - */ -#include - -/* - * "buildrev.h" is auto-generated by the build infrastructure, - * incrementing VERS_BUILD each time the project is rebuilt. - */ -#include "buildrev.h" - -const char vers_tag[] = VERS_TAG; -const char vers_build_str[] = _STRINGIZE(VERS_BUILD); -const char vers_host[] = VERS_HOST; -const int vers_build_nr = VERS_BUILD; - diff --git a/verstag.h b/verstag.h deleted file mode 100644 index a37bcc11..00000000 --- a/verstag.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * - * \brief Declare application version strings - */ -#ifndef DEVLIB_VERSTAG_H -#define DEVLIB_VERSTAG_H - -#ifndef ARCH_CONFIG_H - #include -#endif - -#define APP_NAME "Appname" -#define APP_DESCRIPTION "Long application name description" -#define APP_AUTHOR "Develer" -#define APP_COPYRIGHT "Copyright 2006 Develer (http://www.develer.com/)" - -#if (ARCH & ARCH_FOO) - #define VERS_MAJOR 0 - #define VERS_MINOR 1 - #define VERS_REV 0 - #define VERS_LETTER "" -#elif (ARCH & ARCH_BAR) - #define VERS_MAJOR 0 - #define VERS_MINOR 1 - #define VERS_REV 0 - #define VERS_LETTER "" -#else - #error unknown architecture -#endif - -/** - * If _SNAPSHOT is defined, \c VERS_TAG contains the build date - * date instead of a numeric version string. - */ -#define _SNAPSHOT - -#ifdef _DEBUG - #define VERS_DBG "D" -#else - #define VERS_DBG "" -#endif - -#define __STRINGIZE(x) #x -#define _STRINGIZE(x) __STRINGIZE(x) - -/** Build application version string (i.e.: "1.7.0") */ -#define MAKE_VERS(maj,min,rev) _STRINGIZE(maj) "." _STRINGIZE(min) "." _STRINGIZE(rev) VERS_LETTER VERS_DBG -#ifdef _SNAPSHOT - #define VERS_TAG "snapshot" " " __DATE__ " " __TIME__ " " VERS_LETTER " " VERS_DBG -#else - #define VERS_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV) -#endif - -/** Build application version string suitable for MS windows resource files (i.e.: "1, 7, 0, 1") */ -#define MAKE_RCVERS(maj,min,rev,bld) _STRINGIZE(maj) ", " _STRINGIZE(min) ", " _STRINGIZE(rev) ", " _STRINGIZE(bld) -#define RCVERSION_TAG MAKE_VERS(VERS_MAJOR,VERS_MINOR,VERS_REV) - -/** The revision string (contains VERS_TAG) */ -extern const char vers_tag[]; - -/** Sequential build number (contains VERS_BUILD) */ -extern const int vers_build_nr; -//extern const char vers_build_str[]; - -/** Hostname of the machine used to build this binary (contains VERS_HOST) */ -extern const char vers_host[]; - -#endif /* DEVLIB_VERSTAG_H */