OSDN Git Service

Added logo display features.
authorShinichiro Nakamura <shinta.main.jp@gmail.com>
Thu, 31 May 2012 21:54:15 +0000 (06:54 +0900)
committerShinichiro Nakamura <shinta.main.jp@gmail.com>
Thu, 31 May 2012 21:54:15 +0000 (06:54 +0900)
19 files changed:
firm/07/bootload/Makefile
firm/07/os/Makefile
firm/07/os/NIJIMASU-KUN.BMP [new file with mode: 0644]
firm/07/os/bmpfile.c [new file with mode: 0644]
firm/07/os/bmpfile.h [new file with mode: 0644]
firm/07/os/bmpimg.c [new file with mode: 0644]
firm/07/os/bmpimg.h [new file with mode: 0644]
firm/07/os/bmplowio.c [new file with mode: 0644]
firm/07/os/bmplowio.h [new file with mode: 0644]
firm/07/os/clock.c
firm/07/os/defines.h
firm/07/os/diskio.h [new file with mode: 0644]
firm/07/os/integer.h [new file with mode: 0644]
firm/07/os/lcd.c
firm/07/os/logo.bmp [new file with mode: 0644]
firm/07/os/main.c
firm/07/os/mmc.c [new file with mode: 0644]
firm/07/os/pff.c [new file with mode: 0644]
firm/07/os/pff.h [new file with mode: 0644]

index 19991b3..eed2561 100644 (file)
@@ -29,14 +29,14 @@ OBJS += mmc.o pff.o
 
 TARGET = kzload
 
-CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin -lgcc
+CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
 #CFLAGS += -mint32 # int¤ò32¥Ó¥Ã¥È¤Ë¤¹¤ë¤È³Ý»»¡¿³ä»»¤¬¤Ç¤­¤Ê¤¯¤Ê¤ë
 CFLAGS += -I.
 #CFLAGS += -g
 CFLAGS += -Os
 CFLAGS += -DKZLOAD
 
-LFLAGS = -static -T ld.scr -L.
+LFLAGS = -static -T ld.scr -L. -lgcc
 
 .SUFFIXES: .c .o
 .SUFFIXES: .s .o
index 924749c..7e91b8b 100644 (file)
@@ -23,6 +23,8 @@ OBJS += re.o
 OBJS += sw.o
 OBJS += lcd.o
 OBJS += remocon.o
+OBJS += mmc.o pff.o
+OBJS += bmpfile.o bmpimg.o bmplowio.o
 
 # sources of kozos
 OBJS += kozos.o syscall.o memory.o consdrv.o timerdrv.o command.o clock.o
@@ -36,7 +38,7 @@ CFLAGS += -I.
 CFLAGS += -Os
 CFLAGS += -DKOZOS
 
-LFLAGS = -static -T ld.scr -L.
+LFLAGS = -static -T ld.scr -L. -lgcc
 
 .SUFFIXES: .c .o
 .SUFFIXES: .s .o
diff --git a/firm/07/os/NIJIMASU-KUN.BMP b/firm/07/os/NIJIMASU-KUN.BMP
new file mode 100644 (file)
index 0000000..0e2f7cd
Binary files /dev/null and b/firm/07/os/NIJIMASU-KUN.BMP differ
diff --git a/firm/07/os/bmpfile.c b/firm/07/os/bmpfile.c
new file mode 100644 (file)
index 0000000..f612990
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * @file bmpfile.c
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#include "bmpfile.h"
+#include "bmplowio.h"
+
+/**
+ * @brief BMPファイルを読み込む。
+ * @details
+ * この関数はBMPファイルが「どこに格納されているのか?」について全く感知しない。
+ * また、読み込んだピクセルデータを「どこに格納するのか?」についても感知しない。
+ * ユーザは、これら二つの抽象化された操作を提供する関数へのポインタを提供する必要がある。
+ *
+ * 例えば、小規模組み込みシステムにおいて、BMPファイルのイメージがSDカードやフラッシュ上に書かれているかもしれない。
+ * また、読み込んだピクセルをSPI接続されたSRAMに格納したり、そのままディスプレイに表示したい事もあるだろう。
+ * いずれにせよこれらの機能を実現するのは、この関数に渡すそれぞれの関数内部で実装詳細を提供すれば良い。
+ *
+ * @param func_fread ファイル読み込み関数。
+ * @param extobj_func_fread ファイル読み込み関数に渡すパラメータ。
+ * @param func_pixel_write ピクセル書き込み関数。
+ * @param extobj_pixel_write ピクセル書き込み関数に渡すパラメータ。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpfile_read(
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread,
+        void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+        void *extobj_pixel_write)
+{
+    bmp_file_t filehead;
+    bmp_info_t infohead;
+    bmp_rgbquad_t rgbquad;
+
+    bmplowio_header_read(func_fread, extobj_func_fread, &filehead, &infohead);
+    if (bmplowio_have_palette(BMP_INFO_GET_BIT_COUNT(&infohead))) {
+        bmplowio_palette_read(func_fread, extobj_func_fread, &rgbquad, (1 << infohead.biBitCount));
+    }
+    bmplowio_image_read(func_fread, extobj_func_fread, &filehead, &infohead, func_pixel_write, extobj_pixel_write);
+
+    return 0;
+}
+
+/**
+ * @brief BMPファイルを書き込む。
+ * @details
+ * この関数はBMPファイルが「どこに格納されているのか?」について全く感知しない。
+ * また、書き込むためのピクセルデータが「どこに格納されているのか?」についても感知しない。
+ * ユーザは、これら二つの抽象化された操作を提供する関数へのポインタを提供する必要がある。
+ *
+ * 例えば、小規模組み込みシステムにおいて、BMPファイルのイメージをSDカードやフラッシュ上に書きたいかもしれない。
+ * また、書き込むピクセルはSPI接続されたSRAMに格納されているか、ディスプレイ上のメモリから直接取得したい事もあるだろう。
+ * いずれにせよこれらの機能を実現するのは、この関数に渡すそれぞれの関数内部で実装詳細を提供すれば良い。
+ *
+ * @param func_fwrite ファイル書き込み関数。
+ * @param extobj_func_fwrite ファイル書き込み関数に渡すパラメータ。
+ * @param func_pixel_read ピクセル読み込み関数。
+ * @param extobj_pixel_read ピクセル読み込み関数に渡すパラメータ。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpfile_write(
+        const int w,
+        const int h,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite,
+        void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+        void *extobj_pixel_read)
+{
+    bmp_file_t filehead;
+    bmp_info_t infohead;
+    bmp_rgbquad_t rgbquad;
+
+    BMP_FILE_SET_TYPE(&filehead, BMP_FILE_MAGIC_TEXT);
+    BMP_FILE_SET_SIZE(&filehead, bmplowio_calc_framebytesize(24, w, h) + 54);
+    BMP_FILE_SET_RESERVED1(&filehead, 0);
+    BMP_FILE_SET_RESERVED2(&filehead, 0);
+    BMP_FILE_SET_OFFBITS(&filehead, 54);
+
+    BMP_INFO_SET_SIZE(&infohead, 40);
+    BMP_INFO_SET_WIDTH(&infohead, w);
+    BMP_INFO_SET_HEIGHT(&infohead, h);
+    BMP_INFO_SET_PLANES(&infohead, 1);
+    BMP_INFO_SET_BIT_COUNT(&infohead, 24);
+    BMP_INFO_SET_COMPRESSION(&infohead, 0);
+    BMP_INFO_SET_SIZE_IMAGE(&infohead, bmplowio_calc_framebytesize(24, w, h));
+    BMP_INFO_SET_X_PELS_PER_METER(&infohead, 0);
+    BMP_INFO_SET_Y_PELS_PER_METER(&infohead, 0);
+    BMP_INFO_SET_CLR_USED(&infohead, 0);
+    BMP_INFO_SET_CLR_IMPORTANT(&infohead, 0);
+
+    bmplowio_header_write(func_fwrite, extobj_func_fwrite, &filehead, &infohead);
+    if (bmplowio_have_palette(BMP_INFO_GET_BIT_COUNT(&infohead))) {
+        bmplowio_palette_write(func_fwrite, extobj_func_fwrite, &rgbquad, (1 << infohead.biBitCount));
+    }
+    bmplowio_image_write(func_fwrite, extobj_func_fwrite, &filehead, &infohead, func_pixel_read, extobj_pixel_read);
+
+    return 0;
+}
+
diff --git a/firm/07/os/bmpfile.h b/firm/07/os/bmpfile.h
new file mode 100644 (file)
index 0000000..da8cc05
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * @file bmpfile.h
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#ifndef BMPFILE_H
+#define BMPFILE_H
+
+#include "defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief BMPファイルを読み込む。
+ * @details
+ * この関数はBMPファイルが「どこに格納されているのか?」について全く感知しない。
+ * また、読み込んだピクセルデータを「どこに格納するのか?」についても感知しない。
+ * ユーザは、これら二つの抽象化された操作を提供する関数へのポインタを提供する必要がある。
+ *
+ * 例えば、小規模組み込みシステムにおいて、BMPファイルのイメージがSDカードやフラッシュ上に書かれているかもしれない。
+ * また、読み込んだピクセルをSPI接続されたSRAMに格納したり、そのままディスプレイに表示したい事もあるだろう。
+ * いずれにせよこれらの機能を実現するのは、この関数に渡すそれぞれの関数内部で実装詳細を提供すれば良い。
+ *
+ * @param func_fread ファイル読み込み関数。
+ * @param extobj_func_fread ファイル読み込み関数に渡すパラメータ。
+ * @param func_pixel_write ピクセル書き込み関数。
+ * @param extobj_pixel_write ピクセル書き込み関数に渡すパラメータ。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpfile_read(
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread,
+        void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+        void *extobj_pixel_write);
+
+/**
+ * @brief BMPファイルを書き込む。
+ * @details
+ * この関数はBMPファイルが「どこに格納されているのか?」について全く感知しない。
+ * また、書き込むためのピクセルデータが「どこに格納されているのか?」についても感知しない。
+ * ユーザは、これら二つの抽象化された操作を提供する関数へのポインタを提供する必要がある。
+ *
+ * 例えば、小規模組み込みシステムにおいて、BMPファイルのイメージをSDカードやフラッシュ上に書きたいかもしれない。
+ * また、書き込むピクセルはSPI接続されたSRAMに格納されているか、ディスプレイ上のメモリから直接取得したい事もあるだろう。
+ * いずれにせよこれらの機能を実現するのは、この関数に渡すそれぞれの関数内部で実装詳細を提供すれば良い。
+ *
+ * @param func_fwrite ファイル書き込み関数。
+ * @param extobj_func_fwrite ファイル書き込み関数に渡すパラメータ。
+ * @param func_pixel_read ピクセル読み込み関数。
+ * @param extobj_pixel_read ピクセル読み込み関数に渡すパラメータ。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpfile_write(
+        const int w,
+        const int h,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite,
+        void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+        void *extobj_pixel_read);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/firm/07/os/bmpimg.c b/firm/07/os/bmpimg.c
new file mode 100644 (file)
index 0000000..88b8494
--- /dev/null
@@ -0,0 +1,484 @@
+/**
+ * @file bmpimg.c
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#include "bmpimg.h"
+#include "bmpfile.h"
+
+static const unsigned char FONT_X = 5;              /**< フォントの横方向サイズ。 */
+static const unsigned char FONT_Y = 7;              /**< フォントの縦方向サイズ。 */
+static const unsigned char FONT_MIN_CODE = 0x20;    /**< フォントテーブルの最小コード番号。 */
+static const unsigned char FONT_MAX_CODE = 0x7F;    /**< フォントテーブルの最大コード番号。 */
+static const unsigned char font5x7_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
+    0x00, 0x00, 0x5F, 0x00, 0x00, // !
+    0x00, 0x07, 0x00, 0x07, 0x00, // "
+    0x14, 0x7F, 0x14, 0x7F, 0x14, // #
+    0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
+    0x23, 0x13, 0x08, 0x64, 0x62, // %
+    0x36, 0x49, 0x55, 0x22, 0x50, // &
+    0x00, 0x05, 0x03, 0x00, 0x00, // '
+    0x00, 0x1C, 0x22, 0x41, 0x00, // (
+    0x00, 0x41, 0x22, 0x1C, 0x00, // )
+    0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
+    0x08, 0x08, 0x3E, 0x08, 0x08, // +
+    0x00, 0x50, 0x30, 0x00, 0x00, // ,
+    0x08, 0x08, 0x08, 0x08, 0x08, // -
+    0x00, 0x60, 0x60, 0x00, 0x00, // .
+    0x20, 0x10, 0x08, 0x04, 0x02, // /
+    0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
+    0x00, 0x42, 0x7F, 0x40, 0x00, // 1
+    0x42, 0x61, 0x51, 0x49, 0x46, // 2
+    0x21, 0x41, 0x45, 0x4B, 0x31, // 3
+    0x18, 0x14, 0x12, 0x7F, 0x10, // 4
+    0x27, 0x45, 0x45, 0x45, 0x39, // 5
+    0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
+    0x01, 0x71, 0x09, 0x05, 0x03, // 7
+    0x36, 0x49, 0x49, 0x49, 0x36, // 8
+    0x06, 0x49, 0x49, 0x29, 0x1E, // 9
+    0x00, 0x36, 0x36, 0x00, 0x00, // :
+    0x00, 0x56, 0x36, 0x00, 0x00, // ;
+    0x00, 0x08, 0x14, 0x22, 0x41, // <
+    0x14, 0x14, 0x14, 0x14, 0x14, // =
+    0x41, 0x22, 0x14, 0x08, 0x00, // >
+    0x02, 0x01, 0x51, 0x09, 0x06, // ?
+    0x32, 0x49, 0x79, 0x41, 0x3E, // @
+    0x7E, 0x11, 0x11, 0x11, 0x7E, // A
+    0x7F, 0x49, 0x49, 0x49, 0x36, // B
+    0x3E, 0x41, 0x41, 0x41, 0x22, // C
+    0x7F, 0x41, 0x41, 0x22, 0x1C, // D
+    0x7F, 0x49, 0x49, 0x49, 0x41, // E
+    0x7F, 0x09, 0x09, 0x01, 0x01, // F
+    0x3E, 0x41, 0x41, 0x51, 0x32, // G
+    0x7F, 0x08, 0x08, 0x08, 0x7F, // H
+    0x00, 0x41, 0x7F, 0x41, 0x00, // I
+    0x20, 0x40, 0x41, 0x3F, 0x01, // J
+    0x7F, 0x08, 0x14, 0x22, 0x41, // K
+    0x7F, 0x40, 0x40, 0x40, 0x40, // L
+    0x7F, 0x02, 0x04, 0x02, 0x7F, // M
+    0x7F, 0x04, 0x08, 0x10, 0x7F, // N
+    0x3E, 0x41, 0x41, 0x41, 0x3E, // O
+    0x7F, 0x09, 0x09, 0x09, 0x06, // P
+    0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
+    0x7F, 0x09, 0x19, 0x29, 0x46, // R
+    0x46, 0x49, 0x49, 0x49, 0x31, // S
+    0x01, 0x01, 0x7F, 0x01, 0x01, // T
+    0x3F, 0x40, 0x40, 0x40, 0x3F, // U
+    0x1F, 0x20, 0x40, 0x20, 0x1F, // V
+    0x7F, 0x20, 0x18, 0x20, 0x7F, // W
+    0x63, 0x14, 0x08, 0x14, 0x63, // X
+    0x03, 0x04, 0x78, 0x04, 0x03, // Y
+    0x61, 0x51, 0x49, 0x45, 0x43, // Z
+    0x00, 0x00, 0x7F, 0x41, 0x41, // [
+    0x02, 0x04, 0x08, 0x10, 0x20, // /
+    0x41, 0x41, 0x7F, 0x00, 0x00, // ]
+    0x04, 0x02, 0x01, 0x02, 0x04, // ^
+    0x40, 0x40, 0x40, 0x40, 0x40, // _
+    0x00, 0x01, 0x02, 0x04, 0x00, // `
+    0x20, 0x54, 0x54, 0x54, 0x78, // a
+    0x7F, 0x48, 0x44, 0x44, 0x38, // b
+    0x38, 0x44, 0x44, 0x44, 0x20, // c
+    0x38, 0x44, 0x44, 0x48, 0x7F, // d
+    0x38, 0x54, 0x54, 0x54, 0x18, // e
+    0x08, 0x7E, 0x09, 0x01, 0x02, // f
+    0x08, 0x14, 0x54, 0x54, 0x3C, // g
+    0x7F, 0x08, 0x04, 0x04, 0x78, // h
+    0x00, 0x44, 0x7D, 0x40, 0x00, // i
+    0x20, 0x40, 0x44, 0x3D, 0x00, // j
+    0x00, 0x7F, 0x10, 0x28, 0x44, // k
+    0x00, 0x41, 0x7F, 0x40, 0x00, // l
+    0x7C, 0x04, 0x18, 0x04, 0x78, // m
+    0x7C, 0x08, 0x04, 0x04, 0x78, // n
+    0x38, 0x44, 0x44, 0x44, 0x38, // o
+    0x7C, 0x14, 0x14, 0x14, 0x08, // p
+    0x08, 0x14, 0x14, 0x18, 0x7C, // q
+    0x7C, 0x08, 0x04, 0x04, 0x08, // r
+    0x48, 0x54, 0x54, 0x54, 0x20, // s
+    0x04, 0x3F, 0x44, 0x40, 0x20, // t
+    0x3C, 0x40, 0x40, 0x20, 0x7C, // u
+    0x1C, 0x20, 0x40, 0x20, 0x1C, // v
+    0x3C, 0x40, 0x30, 0x40, 0x3C, // w
+    0x44, 0x28, 0x10, 0x28, 0x44, // x
+    0x0C, 0x50, 0x50, 0x50, 0x3C, // y
+    0x44, 0x64, 0x54, 0x4C, 0x44, // z
+    0x00, 0x08, 0x36, 0x41, 0x00, // {
+    0x00, 0x00, 0x7F, 0x00, 0x00, // |
+    0x00, 0x41, 0x36, 0x08, 0x00, // }
+    0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
+    0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
+};
+
+/**
+ * @brief 文字を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x 横方向描画開始ピクセル位置。
+ * @param y 縦方向描画開始ピクセル位置。
+ * @param size 1ピクセルのサイズ。
+ * @param c 文字。
+ * @param color 描画色。
+ */
+static void draw_char(bmpimg_t *p, const int x, const int y, const int size, const char c, bmpcol_t *color) {
+    int i, j;
+    if ((FONT_MIN_CODE <= c) && (c <= FONT_MAX_CODE)) {
+        int aofs = (c - FONT_MIN_CODE) * FONT_X;
+        for (i = 0; i < FONT_X; i++) {
+            unsigned char pat = font5x7_data[aofs + i];
+            for (j = 0; j < FONT_Y; j++) {
+                if (pat & (1 << j)) {
+                    bmpimg_fill_box(p, x + (i * size), y + (j * size), x + (i * size) + size - 1, y + (j * size) + size - 1, color);
+                }
+            }
+        }
+    } else {
+        for (i = 0; i < FONT_X; i++) {
+            unsigned char pat = (i % 2) ? 0x55 : 0xAA;
+            for (j = 0; j < FONT_Y; j++) {
+                if (pat & (1 << j)) {
+                    bmpimg_fill_box(p, x + (i * size), y + (j * size), x + (i * size) + size - 1, y + (j * size) + size - 1, color);
+                }
+            }
+        }
+    }
+}
+
+/**
+ * @brief BMP画像をオープンする。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param w 画像横方向サイズ。
+ * @param h 画像縦方向サイズ。
+ * @param func_pixel_write ピクセル書き込み関数。
+ * @param extobj_pixel_write ピクセル書き込み関数に渡すパラメータ。
+ * @param func_pixel_read ピクセル読み込み関数。
+ * @param extobj_pixel_read ピクセル読み込み関数に渡すパラメータ。
+ */
+void bmpimg_open(
+        bmpimg_t *p,
+        const int w,
+        const int h,
+        void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+        void *extobj_pixel_write,
+        void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+        void *extobj_pixel_read)
+{
+    p->w = w;
+    p->h = h;
+    p->func_pixel_write = func_pixel_write;
+    p->extobj_pixel_write = extobj_pixel_write;
+    p->func_pixel_read = func_pixel_read;
+    p->extobj_pixel_read = extobj_pixel_read;
+}
+
+/**
+ * @brief ボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_box(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color)
+{
+    int x, y;
+    if ((p->w < x1) || (p->w < x2) || (p->h < y1) || (p->h < y2)) {
+        return -1;
+    }
+    for (y = y1; y <= y2; y++) {
+        p->func_pixel_write(x1, y, color->r, color->g, color->b, p->extobj_pixel_write);
+        p->func_pixel_write(x2, y, color->r, color->g, color->b, p->extobj_pixel_write);
+    }
+    for (x = x1; x <= x2; x++) {
+        p->func_pixel_write(x, y1, color->r, color->g, color->b, p->extobj_pixel_write);
+        p->func_pixel_write(x, y2, color->r, color->g, color->b, p->extobj_pixel_write);
+    }
+    return 0;
+}
+
+/**
+ * @brief ボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_fill_box(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color)
+{
+    int x, y;
+    if ((p->w < x1) || (p->w < x2) || (p->h < y1) || (p->h < y2)) {
+        return -1;
+    }
+    for (y = y1; y <= y2; y++) {
+        for (x = x1; x <= x2; x++) {
+            p->func_pixel_write(x, y, color->r, color->g, color->b, p->extobj_pixel_write);
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief 文字列を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x 横方向描画開始ピクセル位置。
+ * @param y 縦方向描画開始ピクセル位置。
+ * @param size 1ピクセルのサイズ。
+ * @param text 文字列。
+ * @param color 描画色。
+ */
+int bmpimg_draw_string(bmpimg_t *p, const int x, const int y, const int size, const char *text, bmpcol_t *color)
+{
+    char *strp = (char *)text;
+    int cnt = 0;
+    while (*strp) {
+        draw_char(p, x + ((FONT_X * size) * cnt) + (size * cnt), y, size, *strp, color);
+        strp++;
+        cnt++;
+    }
+    return 0;
+}
+
+static void val_swap(int *a, int *b)
+{
+    int c;
+    c = *a;
+    *a = *b;
+    *b = c;
+}
+
+static int val_abs(int a)
+{
+    if (a < 0) {
+        return -a;
+    }
+    return a;
+}
+
+/**
+ * @brief 線を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_line(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color)
+{
+    int tmp_x1 = x1;
+    int tmp_y1 = y1;
+    int tmp_x2 = x2;
+    int tmp_y2 = y2;
+    int steep = val_abs(tmp_y2 - tmp_y1) > val_abs(tmp_x2 - tmp_x1);
+    if (steep) {
+        val_swap(&tmp_x1, &tmp_y1);
+        val_swap(&tmp_x2, &tmp_y2);
+    }
+    if (tmp_x1 > tmp_x2) {
+        val_swap(&tmp_x1, &tmp_x2);
+        val_swap(&tmp_y1, &tmp_y2);
+    }
+    int deltax = tmp_x2 - tmp_x1;
+    int deltay = val_abs(tmp_y2 - tmp_y1);
+    int error = deltax / 2;
+    int ystep;
+    int y = tmp_y1;
+    if (tmp_y1 < tmp_y2) {
+        ystep = 1;
+    } else {
+        ystep = -1;
+    }
+    int x;
+    for (x = tmp_x1; x <= tmp_x2; x++) {
+        if (steep) {
+            bmpimg_fill_box(p, y, x, y, x, color);
+        } else {
+            bmpimg_fill_box(p, x, y, x, y, color);
+        }
+        error = error - deltay;
+        if (error < 0) {
+            y = y + ystep;
+            error = error + deltax;
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief 点を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x X座標。
+ * @param y Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_pixel(bmpimg_t *p, const int x, const int y, bmpcol_t *color)
+{
+    p->func_pixel_write(x, y, color->r, color->g, color->b, p->extobj_pixel_write);
+    return 0;
+}
+
+/**
+ * @brief チェックボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param state 選択状態。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+void bmpimg_draw_checkbox(
+        bmpimg_t *p,
+        const int x1,
+        const int y1,
+        const int x2,
+        const int y2,
+        const int state,
+        bmpcol_t *color)
+{
+    bmpimg_draw_box(p, x1, y1, x2, y2, color);
+    if (state) {
+        bmpimg_draw_line(p, x1, y1, x2, y2, color);
+        bmpimg_draw_line(p, x1, y2, x2, y1, color);
+    }
+}
+
+/**
+ * @brief プログレスバーを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param min 最小値。
+ * @param max 最大値。
+ * @param value 現在値。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+void bmpimg_draw_progressbar(
+        bmpimg_t *p,
+        const int x1,
+        const int y1,
+        const int x2,
+        const int y2,
+        const int min,
+        const int max,
+        const int value,
+        bmpcol_t *color)
+{
+    bmpimg_draw_box(p, x1, y1, x2, y2, color);
+    if ((value < min) || (max < value)) {
+        return;
+    }
+    int tmp_max = max - min;
+    int tmp_val = value - min;
+    int pix = ((x2 - x1) * tmp_val) / tmp_max;
+    bmpimg_fill_box(p, x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, color);
+}
+
+/**
+ * @brief BMPファイルから読み込む。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param filename ファイル名。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_bmp_read(
+        bmpimg_t *p,
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread)
+{
+    return bmpfile_read(func_fread, extobj_func_fread, p->func_pixel_write, p->extobj_pixel_write);
+}
+
+/**
+ * @brief BMPファイルに書き込む。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param filename ファイル名。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_bmp_write(
+        bmpimg_t *p,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite)
+{
+    return bmpfile_write(p->w, p->h, func_fwrite, extobj_func_fwrite, p->func_pixel_read, p->extobj_pixel_read);
+}
+
+/**
+ * @brief BMP画像をクローズする。
+ *
+ * @param bit ビット深度。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_close(bmpimg_t *p)
+{
+    return 0;
+}
+
diff --git a/firm/07/os/bmpimg.h b/firm/07/os/bmpimg.h
new file mode 100644 (file)
index 0000000..9b4aa62
--- /dev/null
@@ -0,0 +1,280 @@
+/**
+ * @file bmpimg.h
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#ifndef BMPIMG_H
+#define BMPIMG_H
+
+#include "defines.h"
+
+/**
+ * @brief BMP画像ハンドラの実装。
+ */
+typedef struct {
+    int w;                  /**< 画像横方向サイズ。 */
+    int h;                  /**< 画像縦方向サイズ。 */
+    void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write);
+    void *extobj_pixel_write;
+    void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read);
+    void *extobj_pixel_read;
+} bmpimg_t;
+
+#define BMPIMG_GET_W(BMPIMG)    ((BMPIMG)->w)
+#define BMPIMG_GET_H(BMPIMG)    ((BMPIMG)->h)
+
+/**
+ * @brief 色定義。
+ * @brief 8ビットでフルレンジ。
+ */
+typedef struct {
+    unsigned char r; /**< 赤。 */
+    unsigned char g; /**< 緑。 */
+    unsigned char b; /**< 青。 */
+} bmpcol_t;
+
+#define BMPIMG_FONT_DOT_WIDTH   (5) /**< フォントの横方向ドット数。 */
+#define BMPIMG_FONT_DOT_HEIGHT  (7) /**< フォンとの縦方向ドット数。 */
+
+/**
+ * @brief 色を設定する。
+ *
+ * @param COL 色定義。
+ * @param R 赤。
+ * @param G 緑。
+ * @param B 青。
+ */
+#define BMPIMG_SET_COLOR(COL, R, G, B)  do { (COL).r = (unsigned char)(R); (COL).g = (unsigned char)(G); (COL).b = (unsigned char)(B); } while (0)
+
+/**
+ * @brief 文字列の幅を取得する。
+ *
+ * @param SIZE サイズ。
+ * @param NSTR 文字列の長さ。
+ *
+ * @return 文字列の幅。
+ */
+#define BMPIMG_GET_STRING_WIDTH(SIZE, NSTR) \
+    ((((SIZE) * (BMPIMG_FONT_DOT_WIDTH + 1)) * ((NSTR) - 1)) + ((SIZE) * (BMPIMG_FONT_DOT_WIDTH)))
+
+/**
+ * @brief 文字列の高さを取得する。
+ *
+ * @param SIZE サイズ。
+ *
+ * @return 文字列の高さ。
+ */
+#define BMPIMG_GET_STRING_HEIGHT(SIZE) \
+    ((SIZE) * (BMPIMG_FONT_DOT_HEIGHT))
+
+/**
+ * @brief BMP画像をオープンする。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param w 画像横方向サイズ。
+ * @param h 画像縦方向サイズ。
+ * @param func_pixel_write ピクセル書き込み関数。
+ * @param extobj_pixel_write ピクセル書き込み関数に渡すパラメータ。
+ * @param func_pixel_read ピクセル読み込み関数。
+ * @param extobj_pixel_read ピクセル読み込み関数に渡すパラメータ。
+ */
+void bmpimg_open(
+        bmpimg_t *p,
+        const int w,
+        const int h,
+        void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+        void *extobj_pixel_write,
+        void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+        void *extobj_pixel_read);
+
+/**
+ * @brief ボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_box(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color);
+
+/**
+ * @brief ボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_fill_box(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color);
+
+/**
+ * @brief 文字列を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x 横方向描画開始ピクセル位置。
+ * @param y 縦方向描画開始ピクセル位置。
+ * @param size 1ピクセルのサイズ。
+ * @param text 文字列。
+ * @param color 描画色。
+ */
+int bmpimg_draw_string(bmpimg_t *p, const int x, const int y, const int size, const char *text, bmpcol_t *color);
+
+/**
+ * @brief 線を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_line(bmpimg_t *p, const int x1, const int y1, const int x2, const int y2, bmpcol_t *color);
+
+/**
+ * @brief 点を描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x X座標。
+ * @param y Y座標。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_draw_pixel(bmpimg_t *p, const int x, const int y, bmpcol_t *color);
+
+/**
+ * @brief チェックボックスを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param state 選択状態。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+void bmpimg_draw_checkbox(
+        bmpimg_t *p,
+        const int x1,
+        const int y1,
+        const int x2,
+        const int y2,
+        const int state,
+        bmpcol_t *color);
+
+/**
+ * @brief プログレスバーを描画する。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param x1 始点X座標。
+ * @param y1 始点Y座標。
+ * @param x2 終点X座標。
+ * @param y2 終点Y座標。
+ * @param min 最小値。
+ * @param max 最大値。
+ * @param value 現在値。
+ * @param color 色。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+void bmpimg_draw_progressbar(
+        bmpimg_t *p,
+        const int x1,
+        const int y1,
+        const int x2,
+        const int y2,
+        const int min,
+        const int max,
+        const int value,
+        bmpcol_t *color);
+
+/**
+ * @brief BMPファイルから読み込む。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param filename ファイル名。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_bmp_read(
+        bmpimg_t *p,
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread);
+
+/**
+ * @brief BMPファイルに書き込む。
+ *
+ * @param p BMP画像ハンドラ。
+ * @param filename ファイル名。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_bmp_write(
+        bmpimg_t *p,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite);
+
+/**
+ * @brief BMP画像をクローズする。
+ *
+ * @param bit ビット深度。
+ *
+ * @retval 0 成功。
+ * @retval !0 失敗。
+ */
+int bmpimg_close(bmpimg_t *p);
+
+#endif
+
diff --git a/firm/07/os/bmplowio.c b/firm/07/os/bmplowio.c
new file mode 100644 (file)
index 0000000..9601e71
--- /dev/null
@@ -0,0 +1,334 @@
+/**
+ * @file bmplowio.c
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#include "bmplowio.h"
+
+static int fread_uint32(
+        uint32 *data,
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread)
+{
+    unsigned char temp[4];
+    if (!func_fread(temp, 4, extobj_func_fread)) {
+        return -1;
+    }
+    *data =
+        ((((uint32)temp[0]) <<  0) & 0x000000ff) |
+        ((((uint32)temp[1]) <<  8) & 0x0000ff00) |
+        ((((uint32)temp[2]) << 16) & 0x00ff0000) |
+        ((((uint32)temp[3]) << 24) & 0xff000000);
+    return 0;
+
+}
+
+static int fread_uint16(
+        uint16 *data,
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread)
+{
+    unsigned char temp[2];
+    if (!func_fread(temp, 2, extobj_func_fread)) {
+        return -1;
+    }
+    *data =
+        ((((uint16)temp[0]) << 0) & 0x00ff) |
+        ((((uint16)temp[1]) << 8) & 0xff00);
+    return 0;
+}
+
+static int fwrite_uint32(
+        uint32 data,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite)
+{
+    unsigned char temp[4];
+    temp[0] = ((data) >>  0) & 0x000000ff;
+    temp[1] = ((data) >>  8) & 0x000000ff;
+    temp[2] = ((data) >> 16) & 0x000000ff;
+    temp[3] = ((data) >> 24) & 0x000000ff;
+    if (!func_fwrite(temp, 4, extobj_func_fwrite)) {
+        return -1;
+    }
+    return 0;
+}
+
+static int fwrite_uint16(
+        uint16 data,
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite)
+{
+    unsigned char temp[2];
+    temp[0] = ((data) >> 0) & 0x00ff;
+    temp[1] = ((data) >> 8) & 0x00ff;
+    if (!func_fwrite(temp, 2, extobj_func_fwrite)) {
+        return -1;
+    }
+    return 0;
+}
+
+int bmplowio_header_init(bmp_file_t* filehead, bmp_info_t *infohead)
+{
+    BMP_FILE_SET_TYPE(filehead, 0);
+    BMP_FILE_SET_SIZE(filehead, 0);
+    BMP_FILE_SET_RESERVED1(filehead, 0);
+    BMP_FILE_SET_RESERVED2(filehead, 0);
+    BMP_FILE_SET_OFFBITS(filehead, 0);
+
+    BMP_INFO_SET_SIZE(infohead, 0);
+    BMP_INFO_SET_WIDTH(infohead, 0);
+    BMP_INFO_SET_HEIGHT(infohead, 0);
+    BMP_INFO_SET_PLANES(infohead, 0);
+    BMP_INFO_SET_BIT_COUNT(infohead, 0);
+    BMP_INFO_SET_COMPRESSION(infohead, 0);
+    BMP_INFO_SET_SIZE_IMAGE(infohead, 0);
+    BMP_INFO_SET_X_PELS_PER_METER(infohead, 0);
+    BMP_INFO_SET_Y_PELS_PER_METER(infohead, 0);
+    BMP_INFO_SET_CLR_USED(infohead, 0);
+    BMP_INFO_SET_CLR_IMPORTANT(infohead, 0);
+
+    return 0;
+}
+
+int bmplowio_header_write(
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite,
+        bmp_file_t *filehead,
+        bmp_info_t *infohead)
+{
+    fwrite_uint16(filehead->bfType, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(filehead->bfSize, func_fwrite, extobj_func_fwrite);
+    fwrite_uint16(filehead->bfReserved1, func_fwrite, extobj_func_fwrite);
+    fwrite_uint16(filehead->bfReserved2, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(filehead->bfOffBits, func_fwrite, extobj_func_fwrite);
+
+    fwrite_uint32(infohead->biSize, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biWidth, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biHeight, func_fwrite, extobj_func_fwrite);
+    fwrite_uint16(infohead->biPlanes, func_fwrite, extobj_func_fwrite);
+    fwrite_uint16(infohead->biBitCount, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biCompression, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biSizeImage, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biXPelsPerMeter, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biYPelsPerMeter, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biClrUsed, func_fwrite, extobj_func_fwrite);
+    fwrite_uint32(infohead->biClrImportant, func_fwrite, extobj_func_fwrite);
+
+    return 0;
+}
+
+int bmplowio_palette_write(
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite,
+        bmp_rgbquad_t *rgbquad,
+        uint32 n)
+{
+    bmp_rgbquad_t *p = rgbquad;
+    int i;
+    for (i = 0; i < (int)n; i++) {
+        func_fwrite(&(p->red), 1, extobj_func_fwrite);
+        func_fwrite(&(p->green), 1, extobj_func_fwrite);
+        func_fwrite(&(p->blue), 1, extobj_func_fwrite);
+        func_fwrite(&(p->reserved), 1, extobj_func_fwrite);
+        p++;
+    }
+    return 0;
+}
+
+int bmplowio_image_write(
+        int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+        void *extobj_func_fwrite,
+        bmp_file_t *filehead,
+        bmp_info_t *infohead,
+        void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+        void *extobj_pixel_read)
+{
+    const int w = infohead->biWidth;
+    const int h = infohead->biHeight;
+    const int pad = (w * infohead->biBitCount + 31) / 32 * 4 - (w * infohead->biBitCount + 7 ) / 8;
+    int x, y;
+    int i;
+    for (y = 0; y < (int)infohead->biHeight; y++) {
+        for (x = 0; x < (int)infohead->biWidth; x++) {
+            if (infohead->biBitCount == 24) {
+                uint8 a, b, c;
+                func_pixel_read(x, h - y - 1, &c, &b, &a, extobj_pixel_read);
+                func_fwrite(&a, 1, extobj_func_fwrite);
+                func_fwrite(&b, 1, extobj_func_fwrite);
+                func_fwrite(&c, 1, extobj_func_fwrite);
+            } else {
+                /*
+                 * @todo 24ビット深度以外は必要になったら対応する。
+                 */
+            }
+        }
+        for (i = 0; i < pad; i++) {
+            uint8 a = 0x00;
+            func_fwrite(&a, 1, extobj_func_fwrite);
+        }
+    }
+    return 0;
+}
+
+int bmplowio_image_read(
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread,
+        bmp_file_t *filehead,
+        bmp_info_t *infohead,
+        void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+        void *extobj_pixel_write)
+{
+    const int w = infohead->biWidth;
+    const int h = infohead->biHeight;
+    const int pad = (w * infohead->biBitCount + 31) / 32 * 4 - (w * infohead->biBitCount + 7 ) / 8;
+    int x, y;
+    int i;
+    for (y = 0; y < (int)infohead->biHeight; y++) {
+        for (x = 0; x < (int)infohead->biWidth; x++) {
+            if (infohead->biBitCount == 24) {
+                uint8 a, b, c;
+                func_fread(&a, 1, extobj_func_fread);
+                func_fread(&b, 1, extobj_func_fread);
+                func_fread(&c, 1, extobj_func_fread);
+                func_pixel_write(x, h - y - 1, c, b, a, extobj_pixel_write);
+            } else {
+                /*
+                 * @todo 24ビット深度以外は必要になったら対応する。
+                 */
+            }
+        }
+        for (i = 0; i < pad; i++) {
+            uint8 a;
+            func_fread(&a, 1, extobj_func_fread);
+        }
+    }
+    return 0;
+}
+
+int bmplowio_header_read(
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread,
+        bmp_file_t *filehead,
+        bmp_info_t *infohead)
+{
+    fread_uint16(&filehead->bfType, func_fread, extobj_func_fread);
+    fread_uint32(&filehead->bfSize, func_fread, extobj_func_fread);
+    fread_uint16(&filehead->bfReserved1, func_fread, extobj_func_fread);
+    fread_uint16(&filehead->bfReserved2, func_fread, extobj_func_fread);
+    fread_uint32(&filehead->bfOffBits, func_fread, extobj_func_fread);
+
+    fread_uint32(&infohead->biSize, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biWidth, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biHeight, func_fread, extobj_func_fread);
+    fread_uint16(&infohead->biPlanes, func_fread, extobj_func_fread);
+    fread_uint16(&infohead->biBitCount, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biCompression, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biSizeImage, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biXPelsPerMeter, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biYPelsPerMeter, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biClrUsed, func_fread, extobj_func_fread);
+    fread_uint32(&infohead->biClrImportant, func_fread, extobj_func_fread);
+
+    return 0;
+}
+
+int bmplowio_palette_read(
+        int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+        void *extobj_func_fread,
+        bmp_rgbquad_t *rgbquad,
+        uint32 n)
+{
+    bmp_rgbquad_t *p = rgbquad;
+    int i;
+    for (i = 0; i < (int)n; i++) {
+        func_fread(&(p->red), 1, extobj_func_fread);
+        func_fread(&(p->green), 1, extobj_func_fread);
+        func_fread(&(p->blue), 1, extobj_func_fread);
+        func_fread(&(p->reserved), 1, extobj_func_fread);
+        p++;
+    }
+    return 0;
+}
+
+int bmplowio_have_palette(const int biBitCount)
+{
+    if ((biBitCount == 8)
+            || (biBitCount == 4)
+            || (biBitCount == 2)
+            || (biBitCount == 1)) {
+        return 1;
+    }
+    return 0;
+}
+
+int bmplowio_calc_framebytesize(
+        const int biBitCount,
+        const int biWidth,
+        const int biHeight)
+{
+    int bmp_frame_bytesize = -1;
+
+    if (biBitCount == 32) {
+        bmp_frame_bytesize = biWidth * 4 * biHeight;
+    }
+
+    if (biBitCount == 24) {
+        bmp_frame_bytesize =
+            ((biWidth * 3 + 3) / 4) * 4 * biHeight;
+    }
+
+    if (biBitCount == 8) {
+        bmp_frame_bytesize =
+            ((biWidth     + 3) / 4) * 4 * biHeight;
+    }
+
+    if (biBitCount == 4) {
+        bmp_frame_bytesize =
+            ((biWidth / 2 + 3) / 4) * 4 * biHeight;
+    }
+
+    if (biBitCount == 2) {
+        bmp_frame_bytesize =
+            ((biWidth / 4 + 3) / 4) * 4 * biHeight;
+    }
+
+    if (biBitCount == 1) {
+        bmp_frame_bytesize =
+            ((biWidth / 8 + 3) / 4) * 4 * biHeight;
+    }
+
+    return bmp_frame_bytesize;
+}
+
diff --git a/firm/07/os/bmplowio.h b/firm/07/os/bmplowio.h
new file mode 100644 (file)
index 0000000..fc2dabd
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * @file bmplowio.h
+ * @author Shinichiro Nakamura
+ * @brief 小規模組み込みシステム向けBMP I/Oの実装。
+ */
+
+/*
+ * ===============================================================
+ *  Tiny BMP I/O Module for KOZOS
+ *  Version 0.0.1
+ * ===============================================================
+ * Copyright (c) 2010-2011 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#ifndef BMPLOWIO_H
+#define BMPLOWIO_H
+
+#include "defines.h"
+
+/**
+ * @brief ビットマップファイルを示すマジックテキスト。
+ */
+#define BMP_FILE_MAGIC_TEXT                 (('B' << 0) | ('M' << 8))
+
+#define BMP_FILE_GET_TYPE(P)                ((P)->bfType)
+#define BMP_FILE_GET_SIZE(P)                ((P)->bfSize)
+#define BMP_FILE_GET_RESERVED1(P)           ((P)->bfReserved1)
+#define BMP_FILE_GET_RESERVED2(P)           ((P)->bfReserved2)
+#define BMP_FILE_GET_OFFBITS(P)             ((P)->bfOffBits)
+
+#define BMP_FILE_SET_TYPE(P, N)             do { (P)->bfType = (N); } while (0)
+#define BMP_FILE_SET_SIZE(P, N)             do { (P)->bfSize = (N); } while (0)
+#define BMP_FILE_SET_RESERVED1(P, N)        do { (P)->bfReserved1 = (N); } while (0)
+#define BMP_FILE_SET_RESERVED2(P, N)        do { (P)->bfReserved2 = (N); } while (0)
+#define BMP_FILE_SET_OFFBITS(P, N)          do { (P)->bfOffBits = (N); } while (0)
+
+#define BMP_INFO_GET_SIZE(P)                ((P)->biSize)
+#define BMP_INFO_GET_WIDTH(P)               ((P)->biWidth)
+#define BMP_INFO_GET_HEIGHT(P)              ((P)->biHeight)
+#define BMP_INFO_GET_PLANES(P)              ((P)->biPlanes)
+#define BMP_INFO_GET_BIT_COUNT(P)           ((P)->biBitCount)
+#define BMP_INFO_GET_COMPRESSION(P)         ((P)->biCompression)
+#define BMP_INFO_GET_SIZE_IMAGE(P)          ((P)->biSizeImage)
+#define BMP_INFO_GET_X_PELS_PER_METER(P)    ((P)->biXPelsPerMeter)
+#define BMP_INFO_GET_Y_PELS_PER_METER(P)    ((P)->biYPelsPerMeter)
+#define BMP_INFO_GET_CLR_USED(P)            ((P)->biClrUsed)
+#define BMP_INFO_GET_CLR_IMPORTANT(P)       ((P)->biClrImportant)
+
+#define BMP_INFO_SET_SIZE(P, N)             do { (P)->biSize = (N); } while (0)
+#define BMP_INFO_SET_WIDTH(P, N)            do { (P)->biWidth = (N); } while (0)
+#define BMP_INFO_SET_HEIGHT(P, N)           do { (P)->biHeight = (N); } while (0)
+#define BMP_INFO_SET_PLANES(P, N)           do { (P)->biPlanes = (N); } while (0)
+#define BMP_INFO_SET_BIT_COUNT(P, N)        do { (P)->biBitCount = (N); } while (0)
+#define BMP_INFO_SET_COMPRESSION(P, N)      do { (P)->biCompression = (N); } while (0)
+#define BMP_INFO_SET_SIZE_IMAGE(P, N)       do { (P)->biSizeImage = (N); } while (0)
+#define BMP_INFO_SET_X_PELS_PER_METER(P, N) do { (P)->biXPelsPerMeter = (N); } while (0)
+#define BMP_INFO_SET_Y_PELS_PER_METER(P, N) do { (P)->biYPelsPerMeter = (N); } while (0)
+#define BMP_INFO_SET_CLR_USED(P, N)         do { (P)->biClrUsed = (N); } while (0)
+#define BMP_INFO_SET_CLR_IMPORTANT(P, N)    do { (P)->biClrImportant = (N); } while (0)
+
+#define BMP_FILE_PRINT(P) \
+    fprintf(stderr, "BMP FILE HEADER : (Type=0x%04x, Size=0x%08x, Reserved1=0x%04x, Reserved2=0x%04x, OffBits=0x%08x)\n", \
+            BMP_FILE_GET_TYPE(P), \
+            BMP_FILE_GET_SIZE(P), \
+            BMP_FILE_GET_RESERVED1(P), \
+            BMP_FILE_GET_RESERVED2(P), \
+            BMP_FILE_GET_OFFBITS(P))
+
+#define BMP_INFO_PRINT(P) \
+    fprintf(stderr, "BMP INFO HEADER : (Size=0x%08x, Width=0x%08x, Height=0x%08x, Planes=0x%04x, BitCount=0x%04x, Compression=0x%08x, SizeImage=0x%08x, XPelsPerMeter=0x%08x, YPelsPerMeter=0x%08x, ClrUsed=0x%08x, ClrImportant=0x%08x)\n", \
+            BMP_INFO_GET_SIZE(P), \
+            BMP_INFO_GET_WIDTH(P), \
+            BMP_INFO_GET_HEIGHT(P), \
+            BMP_INFO_GET_PLANES(P), \
+            BMP_INFO_GET_BIT_COUNT(P), \
+            BMP_INFO_GET_COMPRESSION(P), \
+            BMP_INFO_GET_SIZE_IMAGE(P), \
+            BMP_INFO_GET_X_PELS_PER_METER(P), \
+            BMP_INFO_GET_Y_PELS_PER_METER(P), \
+            BMP_INFO_GET_CLR_USED(P), \
+            BMP_INFO_GET_CLR_IMPORTANT(P))
+
+typedef struct bmp_file {
+    uint16 bfType;
+    uint32 bfSize;
+    uint16 bfReserved1;
+    uint16 bfReserved2;
+    uint32 bfOffBits;
+} bmp_file_t;
+
+typedef struct bmp_info {
+    uint32 biSize;
+    uint32 biWidth;
+    uint32 biHeight;
+    uint16 biPlanes;
+    uint16 biBitCount;
+    uint32 biCompression;
+    uint32 biSizeImage;
+    uint32 biXPelsPerMeter;
+    uint32 biYPelsPerMeter;
+    uint32 biClrUsed;
+    uint32 biClrImportant;
+} bmp_info_t;
+
+typedef struct bmp_rgbquad {
+    uint8 blue;
+    uint8 green;
+    uint8 red;
+    uint8 reserved;
+} bmp_rgbquad_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int bmplowio_header_init(
+    bmp_file_t* filehead,
+    bmp_info_t *infohead);
+
+int bmplowio_header_write(
+    int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+    void *extobj_func_fwrite,
+    bmp_file_t* filehead,
+    bmp_info_t *infohead);
+
+int bmplowio_palette_write(
+    int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+    void *extobj_func_fwrite,
+    bmp_rgbquad_t *rgbquad,
+    uint32 n);
+
+int bmplowio_image_write(
+    int (*func_fwrite)(const void *buf, const uint32 size, void *extobj_func_fwrite),
+    void *extobj_func_fwrite,
+    bmp_file_t *filehead,
+    bmp_info_t *infohead,
+    void (*func_pixel_read)(const int x, const int y, uint8 *r, uint8 *g, uint8 *b, void *extobj_pixel_read),
+    void *extobj_pixel_read);
+
+int bmplowio_image_read(
+    int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+    void *extobj_func_fread,
+    bmp_file_t *filehead,
+    bmp_info_t *infohead,
+    void (*func_pixel_write)(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj_pixel_write),
+    void *extobj_pixel_write);
+
+int bmplowio_header_read(
+    int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+    void *extobj_func_fread,
+    bmp_file_t *filehead,
+    bmp_info_t *infohead);
+
+int bmplowio_palette_read(
+    int (*func_fread)(void *buf, const uint32 size, void *extobj_func_fread),
+    void *extobj_func_fread,
+    bmp_rgbquad_t *rgbquad,
+    uint32 n);
+
+int bmplowio_have_palette(const int biBitCount);
+
+int bmplowio_calc_framebytesize(
+        const int biBitCount,
+        const int biWidth,
+        const int biHeight);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
index 4794401..9ab27f7 100644 (file)
@@ -7,6 +7,8 @@
 #include "sw.h"
 #include "lcd.h"
 #include "re.h"
+#include "pff.h"
+#include "bmpfile.h"
 
 /* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎϤò¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
 static void send_write(char *str)
@@ -49,16 +51,66 @@ static void send_led_toggle(int target)
   kz_send(MSGBOX_ID_LEDDRIVE, 2, p);
 }
 
+static void die(int code)
+{
+  puts("die with code 0x");
+  putxval(code, 4);
+  puts(".\n");
+  while (1) { }
+}
+
+static int func_fread(void *buf, const uint32 size, void *extobj)
+{
+  WORD br;
+  int rc = pf_read(buf, size, &br);
+  return rc ? 1 : 0;
+}
+
+static void func_pixel_write(const int x, const int y, const uint8 r, const uint8 g, const uint8 b, void *extobj)
+{
+  lcd_set_pixel(x, y, 0);
+}
+
+static void splash(void)
+{
+  FATFS fatfs;
+  int rc;
+
+  lcd_draw_box(0, 0, 121, 31, 0);
+  lcd_draw_string(2, 2, "KOZOS", 0);
+
+  lcd_draw_string(2, 10, "Mount", 0);
+  rc = pf_mount(&fatfs);
+  if (rc) {
+    lcd_draw_string(2, 10, "SD mount failed.", 0);
+    die(rc);
+  }
+
+  /*
+   * SD¥«¡¼¥É¾å¤Î24¥Ó¥Ã¥ÈBMP¥Õ¥¡¥¤¥ë¤ò¥í¥´¥Õ¥¡¥¤¥ë¤È¤·¤Æ°·¤¦¡£
+   */
+  lcd_draw_string(2, 10, "Open ", 0);
+  rc = pf_open("logo.bmp");
+  if (rc) {
+    lcd_draw_string(2, 10, "No Logo File.", 0);
+    die(rc);
+  }
+
+  lcd_draw_string(2, 10, "Read ", 0);
+  bmpfile_read(func_fread, NULL, func_pixel_write, NULL);
+  lcd_draw_string(2, 10, "Done ", 0);
+}
+
 int clock_main(int argc, char *argv[])
 {
   uint8 val = 0;
 
   re_init();
   lcd_init();
-  lcd_clear();
-  lcd_draw_string(5, 5, "KOZOS EXPBRD #00", 0);
   sw_init();
 
+  splash();
+
   uint16 prev = 0, curr = 0;
   while (1) {
     val = (val + 1) % 101;
index d13f64b..d16d22f 100644 (file)
@@ -5,6 +5,9 @@
 #define SERIAL_DEFAULT_DEVICE 1
 #define TIMER_DEFAULT_DEVICE  1
 
+typedef char  int8;
+typedef short int16;
+typedef long  int32;
 typedef unsigned char  uint8;
 typedef unsigned short uint16;
 typedef unsigned long  uint32;
diff --git a/firm/07/os/diskio.h b/firm/07/os/diskio.h
new file mode 100644 (file)
index 0000000..b2b181a
--- /dev/null
@@ -0,0 +1,39 @@
+/*-----------------------------------------------------------------------\r
+/  PFF - Low level disk interface modlue include file    (C)ChaN, 2010\r
+/-----------------------------------------------------------------------*/\r
+\r
+#ifndef _DISKIO\r
+#define _DISKIO\r
+\r
+#include "integer.h"\r
+#include "pff.h"\r
+\r
+\r
+/* Status of Disk Functions */\r
+typedef BYTE   DSTATUS;\r
+\r
+#define STA_NOINIT             0x01    /* Drive not initialized */\r
+#define STA_NODISK             0x02    /* No medium in the drive */\r
+\r
+\r
+/* Results of Disk Functions */\r
+typedef enum {\r
+       RES_OK = 0,             /* 0: Function succeeded */\r
+       RES_ERROR,              /* 1: Disk error */\r
+       RES_NOTRDY,             /* 2: Not ready */\r
+       RES_PARERR              /* 3: Invalid parameter */\r
+} DRESULT;\r
+\r
+\r
+/*---------------------------------------*/\r
+/* Prototypes for disk control functions */\r
+\r
+DSTATUS disk_initialize (void);\r
+#if _USE_READ\r
+DRESULT disk_readp (BYTE*, DWORD, WORD, WORD);\r
+#endif\r
+#if _USE_WRITE\r
+DRESULT disk_writep (const BYTE*, DWORD);\r
+#endif\r
+\r
+#endif\r
diff --git a/firm/07/os/integer.h b/firm/07/os/integer.h
new file mode 100644 (file)
index 0000000..0e24bdb
--- /dev/null
@@ -0,0 +1,30 @@
+/*-------------------------------------------*/\r
+/* Integer type definitions for FatFs module */\r
+/*-------------------------------------------*/\r
+\r
+#ifndef _INTEGER\r
+#define _INTEGER\r
+\r
+#include "defines.h"\r
+\r
+/* These types must be 16-bit, 32-bit or larger integer */\r
+typedef int16       INT;\r
+typedef uint16      UINT;\r
+\r
+/* These types must be 8-bit integer */\r
+typedef int8        CHAR;\r
+typedef uint8       UCHAR;\r
+typedef uint8       BYTE;\r
+\r
+/* These types must be 16-bit integer */\r
+typedef int16       SHORT;\r
+typedef uint16      USHORT;\r
+typedef uint16      WORD;\r
+typedef uint16      WCHAR;\r
+\r
+/* These types must be 32-bit integer */\r
+typedef int32       LONG;\r
+typedef uint32      ULONG;\r
+typedef uint32      DWORD;\r
+\r
+#endif\r
index 0392bc5..1023edc 100644 (file)
@@ -19,6 +19,7 @@ static const uint16 FONT_MAX_CODE = 0x7F;
 #define LCD_AOFS_DAT    (1 << 3)
 
 #define BIT_LCD_RES     (1 << 7)
+#define BIT_SDC_CS      (1 << 0)
 
 #define LCD1_CMD(VAL) \
   do { \
@@ -145,7 +146,7 @@ static const uint8 font5x7_data[] = {
 
 void lcd_init(void)
 {
-  *H8_3069F_P4DDR = BIT_LCD_RES;
+  *H8_3069F_P4DDR = BIT_LCD_RES | BIT_SDC_CS;
 
   /*
    * L->H : 68K mode.
diff --git a/firm/07/os/logo.bmp b/firm/07/os/logo.bmp
new file mode 100644 (file)
index 0000000..5d35e32
Binary files /dev/null and b/firm/07/os/logo.bmp differ
index 5112cfe..bef24bd 100644 (file)
@@ -10,7 +10,7 @@ static int start_threads(int argc, char *argv[])
   kz_run(command_main,  "command",  8, 0x200, 0, NULL);
   kz_run(timerdrv_main, "timerdrv", 2, 0x100, 0, NULL);
   kz_run(leddrv_main,   "leddrv",   7, 0x100, 0, NULL);
-  kz_run(clock_main,    "clock",    9, 0x100, 0, NULL);
+  kz_run(clock_main,    "clock",    9, 0x200, 0, NULL);
   kz_run(remocon_main,  "remocon", 10, 0x100, 0, NULL);
 
   kz_chpri(15); /* Í¥Àè½ç°Ì¤ò²¼¤²¤Æ¡¤¥¢¥¤¥É¥ë¥¹¥ì¥Ã¥É¤Ë°Ü¹Ô¤¹¤ë */
diff --git a/firm/07/os/mmc.c b/firm/07/os/mmc.c
new file mode 100644 (file)
index 0000000..4a2d4aa
--- /dev/null
@@ -0,0 +1,390 @@
+/*------------------------------------------------------------------------/\r
+/  Bitbanging MMCv3/SDv1/SDv2 (in SPI mode) control module for PFF\r
+/-------------------------------------------------------------------------/\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * This software is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/--------------------------------------------------------------------------/\r
+ Features:\r
+\r
+ * Very Easy to Port\r
+   It uses only 4-6 bit of GPIO port. No interrupt, no SPI port is used.\r
+\r
+ * Platform Independent\r
+   You need to modify only a few macros to control GPIO ports.\r
+\r
+/-------------------------------------------------------------------------*/\r
+\r
+\r
+#include "diskio.h"\r
+\r
+#define H8_3069F_P4DR   ((volatile uint8 *)0xFFFFD3)\r
+#define H8_3069F_PBDR   ((volatile uint8 *)0xFFFFDA)\r
+\r
+#define PB_BIT_SCLK     (1 << 5)\r
+#define PB_BIT_MOSI     (1 << 6)\r
+#define PB_BIT_MISO     (1 << 7)\r
+#define P4_BIT_CS       (1 << 0)\r
+\r
+/*-------------------------------------------------------------------------*/\r
+/* Platform dependent macros and functions needed to be modified           */\r
+/*-------------------------------------------------------------------------*/\r
+\r
+#define INIT_PORT()    do { } while (0)    /* Initialize MMC control port (CS/CLK/DI:output, DO:input) */\r
+#define DLY_US(n)      do { volatile uint32 dlycnt; for (dlycnt = 0; dlycnt < (n) * 10; dlycnt++) {} } while (0)    /* Delay n microseconds */\r
+#define FORWARD(d)     do { } while (0)    /* Data in-time processing function (depends on the project) */\r
+\r
+#define CS_H()         do { *H8_3069F_P4DR |=  P4_BIT_CS; } while (0)      /* Set MMC CS "high" */\r
+#define CS_L()         do { *H8_3069F_P4DR &= ~P4_BIT_CS; } while (0)      /* Set MMC CS "low" */\r
+#define CK_H()         do { *H8_3069F_PBDR |=  PB_BIT_SCLK; } while (0)    /* Set MMC SCLK "high" */\r
+#define CK_L()         do { *H8_3069F_PBDR &= ~PB_BIT_SCLK; } while (0)    /* Set MMC SCLK "low" */\r
+#define DI_H()         do { *H8_3069F_PBDR |=  PB_BIT_MOSI; } while (0)    /* Set MMC DI "high" */\r
+#define DI_L()         do { *H8_3069F_PBDR &= ~PB_BIT_MOSI; } while (0)    /* Set MMC DI "low" */\r
+#define DO             ((*H8_3069F_PBDR & PB_BIT_MISO) ? 1 : 0)            /* Get MMC DO value (high:true, low:false) */\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Module Private Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+/* Definitions for MMC/SDC command */\r
+#define CMD0   (0x40+0)        /* GO_IDLE_STATE */\r
+#define CMD1   (0x40+1)        /* SEND_OP_COND (MMC) */\r
+#define        ACMD41  (0xC0+41)       /* SEND_OP_COND (SDC) */\r
+#define CMD8   (0x40+8)        /* SEND_IF_COND */\r
+#define CMD16  (0x40+16)       /* SET_BLOCKLEN */\r
+#define CMD17  (0x40+17)       /* READ_SINGLE_BLOCK */\r
+#define CMD24  (0x40+24)       /* WRITE_BLOCK */\r
+#define CMD55  (0x40+55)       /* APP_CMD */\r
+#define CMD58  (0x40+58)       /* READ_OCR */\r
+\r
+/* Card type flags (CardType) */\r
+#define CT_MMC                         0x01    /* MMC ver 3 */\r
+#define CT_SD1                         0x02    /* SD ver 1 */\r
+#define CT_SD2                         0x04    /* SD ver 2 */\r
+#define CT_SDC                         (CT_SD1|CT_SD2) /* SD */\r
+#define CT_BLOCK                       0x08    /* Block addressing */\r
+\r
+\r
+\r
+static\r
+BYTE CardType;                 /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Transmit a byte to the MMC (bitbanging)                               */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void xmit_mmc (\r
+       BYTE d                  /* Data to be sent */\r
+)\r
+{\r
+       if (d & 0x80) DI_H(); else DI_L();      /* bit7 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x40) DI_H(); else DI_L();      /* bit6 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x20) DI_H(); else DI_L();      /* bit5 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x10) DI_H(); else DI_L();      /* bit4 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x08) DI_H(); else DI_L();      /* bit3 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x04) DI_H(); else DI_L();      /* bit2 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x02) DI_H(); else DI_L();      /* bit1 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x01) DI_H(); else DI_L();      /* bit0 */\r
+       CK_H(); CK_L();\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Receive a byte from the MMC (bitbanging)                              */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE rcvr_mmc (void)\r
+{\r
+       BYTE r;\r
+\r
+\r
+       DI_H(); /* Send 0xFF */\r
+\r
+       r = 0;   if (DO) r++;   /* bit7 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit6 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit5 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit4 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit3 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit2 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit1 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit0 */\r
+       CK_H(); CK_L();\r
+\r
+       return r;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Skip bytes on the MMC (bitbanging)                                    */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void skip_mmc (\r
+       WORD n          /* Number of bytes to skip */\r
+)\r
+{\r
+       DI_H(); /* Send 0xFF */\r
+\r
+       do {\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+       } while (--n);\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Deselect the card and release SPI bus                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void release_spi (void)\r
+{\r
+       CS_H();\r
+       rcvr_mmc();\r
+}\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Send a command packet to MMC                                          */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE send_cmd (\r
+       BYTE cmd,               /* Command byte */\r
+       DWORD arg               /* Argument */\r
+)\r
+{\r
+       BYTE n, res;\r
+\r
+\r
+       if (cmd & 0x80) {       /* ACMD<n> is the command sequense of CMD55-CMD<n> */\r
+               cmd &= 0x7F;\r
+               res = send_cmd(CMD55, 0);\r
+               if (res > 1) return res;\r
+       }\r
+\r
+       /* Select the card */\r
+       CS_H(); rcvr_mmc();\r
+       CS_L(); rcvr_mmc();\r
+\r
+       /* Send a command packet */\r
+       xmit_mmc(cmd);                                  /* Start + Command index */\r
+       xmit_mmc((BYTE)(arg >> 24));    /* Argument[31..24] */\r
+       xmit_mmc((BYTE)(arg >> 16));    /* Argument[23..16] */\r
+       xmit_mmc((BYTE)(arg >> 8));             /* Argument[15..8] */\r
+       xmit_mmc((BYTE)arg);                    /* Argument[7..0] */\r
+       n = 0x01;                                               /* Dummy CRC + Stop */\r
+       if (cmd == CMD0) n = 0x95;              /* Valid CRC for CMD0(0) */\r
+       if (cmd == CMD8) n = 0x87;              /* Valid CRC for CMD8(0x1AA) */\r
+       xmit_mmc(n);\r
+\r
+       /* Receive a command response */\r
+       n = 10;                                                         /* Wait for a valid response in timeout of 10 attempts */\r
+       do {\r
+               res = rcvr_mmc();\r
+       } while ((res & 0x80) && --n);\r
+\r
+       return res;                     /* Return with the response value */\r
+}\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Public Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Initialize Disk Drive                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+DSTATUS disk_initialize (void)\r
+{\r
+       BYTE n, cmd, ty, buf[4];\r
+       UINT tmr;\r
+\r
+\r
+       INIT_PORT();\r
+\r
+       CS_H();\r
+       skip_mmc(10);                   /* Dummy clocks */\r
+\r
+       ty = 0;\r
+       if (send_cmd(CMD0, 0) == 1) {                   /* Enter Idle state */\r
+               if (send_cmd(CMD8, 0x1AA) == 1) {       /* SDv2 */\r
+                       for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();    /* Get trailing return value of R7 resp */\r
+                       if (buf[2] == 0x01 && buf[3] == 0xAA) {                 /* The card can work at vdd range of 2.7-3.6V */\r
+                               for (tmr = 1000; tmr; tmr--) {                          /* Wait for leaving idle state (ACMD41 with HCS bit) */\r
+                                       if (send_cmd(ACMD41, 1UL << 30) == 0) break;\r
+                                       DLY_US(1000);\r
+                               }\r
+                               if (tmr && send_cmd(CMD58, 0) == 0) {           /* Check CCS bit in the OCR */\r
+                                       for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();\r
+                                       ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;      /* SDv2 (HC or SC) */\r
+                               }\r
+                       }\r
+               } else {                                                        /* SDv1 or MMCv3 */\r
+                       if (send_cmd(ACMD41, 0) <= 1)   {\r
+                               ty = CT_SD1; cmd = ACMD41;      /* SDv1 */\r
+                       } else {\r
+                               ty = CT_MMC; cmd = CMD1;        /* MMCv3 */\r
+                       }\r
+                       for (tmr = 1000; tmr; tmr--) {                  /* Wait for leaving idle state */\r
+                               if (send_cmd(ACMD41, 0) == 0) break;\r
+                               DLY_US(1000);\r
+                       }\r
+                       if (!tmr || send_cmd(CMD16, 512) != 0)                  /* Set R/W block length to 512 */\r
+                               ty = 0;\r
+               }\r
+       }\r
+       CardType = ty;\r
+       release_spi();\r
+\r
+       return ty ? 0 : STA_NOINIT;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read partial sector                                                   */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+DRESULT disk_readp (\r
+       BYTE *buff,             /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */\r
+       DWORD lba,              /* Sector number (LBA) */\r
+       WORD ofs,               /* Byte offset to read from (0..511) */\r
+       WORD cnt                /* Number of bytes to read (ofs + cnt mus be <= 512) */\r
+)\r
+{\r
+       DRESULT res;\r
+       BYTE d;\r
+       WORD bc, tmr;\r
+\r
+\r
+       if (!(CardType & CT_BLOCK)) lba *= 512;         /* Convert to byte address if needed */\r
+\r
+       res = RES_ERROR;\r
+       if (send_cmd(CMD17, lba) == 0) {                /* READ_SINGLE_BLOCK */\r
+\r
+               tmr = 1000;\r
+               do {                                                    /* Wait for data packet in timeout of 100ms */\r
+                       DLY_US(100);\r
+                       d = rcvr_mmc();\r
+               } while (d == 0xFF && --tmr);\r
+\r
+               if (d == 0xFE) {                                /* A data packet arrived */\r
+                       bc = 514 - ofs - cnt;\r
+\r
+                       /* Skip leading bytes */\r
+                       if (ofs) skip_mmc(ofs);\r
+\r
+                       /* Receive a part of the sector */\r
+                       if (buff) {     /* Store data to the memory */\r
+                               do\r
+                                       *buff++ = rcvr_mmc();\r
+                               while (--cnt);\r
+                       } else {        /* Forward data to the outgoing stream */\r
+                               do {\r
+                                       d = rcvr_mmc();\r
+                                       FORWARD(d);\r
+                               } while (--cnt);\r
+                       }\r
+\r
+                       /* Skip trailing bytes and CRC */\r
+                       skip_mmc(bc);\r
+\r
+                       res = RES_OK;\r
+               }\r
+       }\r
+\r
+       release_spi();\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Write partial sector                                                  */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_WRITE\r
+\r
+DRESULT disk_writep (\r
+       const BYTE *buff,       /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */\r
+       DWORD sa                        /* Number of bytes to send, Sector number (LBA) or zero */\r
+)\r
+{\r
+       DRESULT res;\r
+       WORD bc, tmr;\r
+       static WORD wc;\r
+\r
+\r
+       res = RES_ERROR;\r
+\r
+       if (buff) {             /* Send data bytes */\r
+               bc = (WORD)sa;\r
+               while (bc && wc) {              /* Send data bytes to the card */\r
+                       xmit_mmc(*buff++);\r
+                       wc--; bc--;\r
+               }\r
+               res = RES_OK;\r
+       } else {\r
+               if (sa) {       /* Initiate sector write process */\r
+                       if (!(CardType & CT_BLOCK)) sa *= 512;  /* Convert to byte address if needed */\r
+                       if (send_cmd(CMD24, sa) == 0) {                 /* WRITE_SINGLE_BLOCK */\r
+                               xmit_mmc(0xFF); xmit_mmc(0xFE);         /* Data block header */\r
+                               wc = 512;                                                       /* Set byte counter */\r
+                               res = RES_OK;\r
+                       }\r
+               } else {        /* Finalize sector write process */\r
+                       bc = wc + 2;\r
+                       while (bc--) xmit_mmc(0);       /* Fill left bytes and CRC with zeros */\r
+                       if ((rcvr_mmc() & 0x1F) == 0x05) {      /* Receive data resp and wait for end of write process in timeout of 300ms */\r
+                               for (tmr = 10000; rcvr_mmc() != 0xFF && tmr; tmr--)     /* Wait for ready (max 1000ms) */\r
+                                       DLY_US(100);\r
+                               if (tmr) res = RES_OK;\r
+                       }\r
+                       release_spi();\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+#endif\r
diff --git a/firm/07/os/pff.c b/firm/07/os/pff.c
new file mode 100644 (file)
index 0000000..802e8a3
--- /dev/null
@@ -0,0 +1,1114 @@
+/*----------------------------------------------------------------------------/\r
+/  Petit FatFs - FAT file system module  R0.02a                (C)ChaN, 2010\r
+/-----------------------------------------------------------------------------/\r
+/ Petit FatFs module is an open source software to implement FAT file system to\r
+/ small embedded systems. This is a free software and is opened for education,\r
+/ research and commercial developments under license policy of following trems.\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/-----------------------------------------------------------------------------/\r
+/ Jun 15,'09  R0.01a  First release. (Branched from FatFs R0.07b.)\r
+/\r
+/ Dec 14,'09  R0.02   Added multiple code page support.\r
+/                     Added write funciton.\r
+/                     Changed stream read mode interface.\r
+/ Dec 07,'10  R0.02a  Added some configuration options.\r
+/                     Fixed fails to open objects with DBCS character.\r
+/----------------------------------------------------------------------------*/\r
+\r
+#include "pff.h"               /* Petit FatFs configurations and declarations */\r
+#include "diskio.h"            /* Declarations of low level disk I/O functions */\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Module Private Definitions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+#if _FS_FAT32\r
+#define LD_CLUST(dir)  (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))\r
+#else\r
+#define LD_CLUST(dir)  LD_WORD(dir+DIR_FstClusLO)\r
+#endif\r
+\r
+\r
+/*--------------------------------------------------------*/\r
+/* DBCS code ranges and SBCS extend char conversion table */\r
+\r
+#if _CODE_PAGE == 932  /* Japanese Shift-JIS */\r
+#define _DF1S  0x81    /* DBC 1st byte range 1 start */\r
+#define _DF1E  0x9F    /* DBC 1st byte range 1 end */\r
+#define _DF2S  0xE0    /* DBC 1st byte range 2 start */\r
+#define _DF2E  0xFC    /* DBC 1st byte range 2 end */\r
+#define _DS1S  0x40    /* DBC 2nd byte range 1 start */\r
+#define _DS1E  0x7E    /* DBC 2nd byte range 1 end */\r
+#define _DS2S  0x80    /* DBC 2nd byte range 2 start */\r
+#define _DS2E  0xFC    /* DBC 2nd byte range 2 end */\r
+\r
+#elif _CODE_PAGE == 936        /* Simplified Chinese GBK */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x40\r
+#define _DS1E  0x7E\r
+#define _DS2S  0x80\r
+#define _DS2E  0xFE\r
+\r
+#elif _CODE_PAGE == 949        /* Korean */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x41\r
+#define _DS1E  0x5A\r
+#define _DS2S  0x61\r
+#define _DS2E  0x7A\r
+#define _DS3S  0x81\r
+#define _DS3E  0xFE\r
+\r
+#elif _CODE_PAGE == 950        /* Traditional Chinese Big5 */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x40\r
+#define _DS1E  0x7E\r
+#define _DS2S  0xA1\r
+#define _DS2E  0xFE\r
+\r
+#elif _CODE_PAGE == 437        /* U.S. (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 720        /* Arabic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 737        /* Greek (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \\r
+                               0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 775        /* Baltic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 850        /* Multilingual Latin 1 (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 852        /* Latin 2 (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 855        /* Cyrillic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \\r
+                               0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \\r
+                               0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 857        /* Turkish (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 858        /* Multilingual Latin 1 + Euro (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 862        /* Hebrew (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 866        /* Russian (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 874        /* Thai (OEM, Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \\r
+                               0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}\r
+\r
+#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1253 /* Greek (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \\r
+                               0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}\r
+\r
+#elif _CODE_PAGE == 1254 /* Turkish (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1256 /* Arabic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1257 /* Baltic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1  /* ASCII (for only non-LFN cfg) */\r
+#define _DF1S  0\r
+\r
+#else\r
+#error Unknown code page\r
+\r
+#endif\r
+\r
+\r
+\r
+/* Character code support macros */\r
+\r
+#define IsUpper(c)     (((c)>='A')&&((c)<='Z'))\r
+#define IsLower(c)     (((c)>='a')&&((c)<='z'))\r
+\r
+#if _DF1S              /* DBCS configuration */\r
+\r
+#ifdef _DF2S   /* Two 1st byte areas */\r
+#define IsDBCS1(c)     (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))\r
+#else                  /* One 1st byte area */\r
+#define IsDBCS1(c)     ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)\r
+#endif\r
+\r
+#ifdef _DS3S   /* Three 2nd byte areas */\r
+#define IsDBCS2(c)     (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))\r
+#else                  /* Two 2nd byte areas */\r
+#define IsDBCS2(c)     (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))\r
+#endif\r
+\r
+#else                  /* SBCS configuration */\r
+\r
+#define IsDBCS1(c)     0\r
+#define IsDBCS2(c)     0\r
+\r
+#endif /* _DF1S */\r
+\r
+\r
+/* FatFs refers the members in the FAT structures with byte offset instead\r
+/ of structure member because there are incompatibility of the packing option\r
+/ between various compilers. */\r
+\r
+#define BS_jmpBoot                     0\r
+#define BS_OEMName                     3\r
+#define BPB_BytsPerSec         11\r
+#define BPB_SecPerClus         13\r
+#define BPB_RsvdSecCnt         14\r
+#define BPB_NumFATs                    16\r
+#define BPB_RootEntCnt         17\r
+#define BPB_TotSec16           19\r
+#define BPB_Media                      21\r
+#define BPB_FATSz16                    22\r
+#define BPB_SecPerTrk          24\r
+#define BPB_NumHeads           26\r
+#define BPB_HiddSec                    28\r
+#define BPB_TotSec32           32\r
+#define BS_55AA                                510\r
+\r
+#define BS_DrvNum                      36\r
+#define BS_BootSig                     38\r
+#define BS_VolID                       39\r
+#define BS_VolLab                      43\r
+#define BS_FilSysType          54\r
+\r
+#define BPB_FATSz32                    36\r
+#define BPB_ExtFlags           40\r
+#define BPB_FSVer                      42\r
+#define BPB_RootClus           44\r
+#define BPB_FSInfo                     48\r
+#define BPB_BkBootSec          50\r
+#define BS_DrvNum32                    64\r
+#define BS_BootSig32           66\r
+#define BS_VolID32                     67\r
+#define BS_VolLab32                    71\r
+#define BS_FilSysType32                82\r
+\r
+#define MBR_Table                      446\r
+\r
+#define        DIR_Name                        0\r
+#define        DIR_Attr                        11\r
+#define        DIR_NTres                       12\r
+#define        DIR_CrtTime                     14\r
+#define        DIR_CrtDate                     16\r
+#define        DIR_FstClusHI           20\r
+#define        DIR_WrtTime                     22\r
+#define        DIR_WrtDate                     24\r
+#define        DIR_FstClusLO           26\r
+#define        DIR_FileSize            28\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Private Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+static\r
+FATFS *FatFs;  /* Pointer to the file system object (logical drive) */\r
+\r
+\r
+/* Fill memory */\r
+static\r
+void mem_set (void* dst, int val, int cnt) {\r
+       char *d = (char*)dst;\r
+       while (cnt--) *d++ = (char)val;\r
+}\r
+\r
+/* Compare memory to memory */\r
+static\r
+int mem_cmp (const void* dst, const void* src, int cnt) {\r
+       const char *d = (const char *)dst, *s = (const char *)src;\r
+       int r = 0;\r
+       while (cnt-- && (r = *d++ - *s++) == 0) ;\r
+       return r;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* FAT access - Read value of a FAT entry                                */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+CLUST get_fat (        /* 1:IO error, Else:Cluster status */\r
+       CLUST clst      /* Cluster# to get the link information */\r
+)\r
+{\r
+       WORD wc, bc, ofs;\r
+       BYTE buf[4];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (clst < 2 || clst >= fs->n_fatent)   /* Range check */\r
+               return 1;\r
+\r
+       switch (fs->fs_type) {\r
+#if _FS_FAT12\r
+       case FS_FAT12 :\r
+               bc = (WORD)clst; bc += bc / 2;\r
+               ofs = bc % 512; bc /= 512;\r
+               if (ofs != 511) {\r
+                       if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;\r
+               } else {\r
+                       if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;\r
+                       if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;\r
+               }\r
+               wc = LD_WORD(buf);\r
+               return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);\r
+#endif\r
+       case FS_FAT16 :\r
+               if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;\r
+               return LD_WORD(buf);\r
+#if _FS_FAT32\r
+       case FS_FAT32 :\r
+               if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;\r
+               return LD_DWORD(buf) & 0x0FFFFFFF;\r
+#endif\r
+       }\r
+\r
+       return 1;       /* An error occured at the disk I/O layer */\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Get sector# from cluster#                                             */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+DWORD clust2sect (     /* !=0: Sector number, 0: Failed - invalid cluster# */\r
+       CLUST clst              /* Cluster# to be converted */\r
+)\r
+{\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       clst -= 2;\r
+       if (clst >= (fs->n_fatent - 2)) return 0;               /* Invalid cluster# */\r
+       return (DWORD)clst * fs->csize + fs->database;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Rewind directory index                           */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_rewind (\r
+       DIR *dj                 /* Pointer to directory object */\r
+)\r
+{\r
+       CLUST clst;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       dj->index = 0;\r
+       clst = dj->sclust;\r
+       if (clst == 1 || clst >= fs->n_fatent)  /* Check start cluster range */\r
+               return FR_DISK_ERR;\r
+       if (_FS_FAT32 && !clst && fs->fs_type == FS_FAT32)      /* Replace cluster# 0 with root cluster# if in FAT32 */\r
+               clst = (CLUST)fs->dirbase;\r
+       dj->clust = clst;                                               /* Current cluster */\r
+       dj->sect = clst ? clust2sect(clst) : fs->dirbase;       /* Current sector */\r
+\r
+       return FR_OK;   /* Seek succeeded */\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Move directory index next                        */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_next (     /* FR_OK:Succeeded, FR_NO_FILE:End of table */\r
+       DIR *dj                 /* Pointer to directory object */\r
+)\r
+{\r
+       CLUST clst;\r
+       WORD i;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       i = dj->index + 1;\r
+       if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */\r
+               return FR_NO_FILE;\r
+\r
+       if (!(i % 16)) {                /* Sector changed? */\r
+               dj->sect++;                     /* Next sector */\r
+\r
+               if (dj->clust == 0) {   /* Static table */\r
+                       if (i >= fs->n_rootdir) /* Report EOT when end of table */\r
+                               return FR_NO_FILE;\r
+               }\r
+               else {                                  /* Dynamic table */\r
+                       if (((i / 16) & (fs->csize-1)) == 0) {  /* Cluster changed? */\r
+                               clst = get_fat(dj->clust);              /* Get next cluster */\r
+                               if (clst <= 1) return FR_DISK_ERR;\r
+                               if (clst >= fs->n_fatent)               /* When it reached end of dynamic table */\r
+                                       return FR_NO_FILE;                      /* Report EOT */\r
+                               dj->clust = clst;                               /* Initialize data for new cluster */\r
+                               dj->sect = clust2sect(clst);\r
+                       }\r
+               }\r
+       }\r
+\r
+       dj->index = i;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Find an object in the directory                  */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_find (\r
+       DIR *dj,                /* Pointer to the directory object linked to the file name */\r
+       BYTE *dir               /* 32-byte working buffer */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE c;\r
+\r
+\r
+       res = dir_rewind(dj);                   /* Rewind directory object */\r
+       if (res != FR_OK) return res;\r
+\r
+       do {\r
+               res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
+                       ? FR_DISK_ERR : FR_OK;\r
+               if (res != FR_OK) break;\r
+               c = dir[DIR_Name];      /* First character */\r
+               if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
+               if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */\r
+                       break;\r
+               res = dir_next(dj);                                     /* Next entry */\r
+       } while (res == FR_OK);\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read an object from the directory                                     */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+static\r
+FRESULT dir_read (\r
+       DIR *dj,                /* Pointer to the directory object to store read object name */\r
+       BYTE *dir               /* 32-byte working buffer */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE a, c;\r
+\r
+\r
+       res = FR_NO_FILE;\r
+       while (dj->sect) {\r
+               res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
+                       ? FR_DISK_ERR : FR_OK;\r
+               if (res != FR_OK) break;\r
+               c = dir[DIR_Name];\r
+               if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
+               a = dir[DIR_Attr] & AM_MASK;\r
+               if (c != 0xE5 && c != '.' && !(a & AM_VOL))     /* Is it a valid entry? */\r
+                       break;\r
+               res = dir_next(dj);                     /* Next entry */\r
+               if (res != FR_OK) break;\r
+       }\r
+\r
+       if (res != FR_OK) dj->sect = 0;\r
+\r
+       return res;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Pick a segment and create the object name in directory form           */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+#ifdef _EXCVT\r
+       static const BYTE cvt[] = _EXCVT;\r
+#endif\r
+\r
+static\r
+FRESULT create_name (\r
+       DIR *dj,                        /* Pointer to the directory object */\r
+       const char **path       /* Pointer to pointer to the segment in the path string */\r
+)\r
+{\r
+       BYTE c, d, ni, si, i, *sfn;\r
+       const char *p;\r
+\r
+       /* Create file name in directory form */\r
+       sfn = dj->fn;\r
+       mem_set(sfn, ' ', 11);\r
+       si = i = 0; ni = 8;\r
+       p = *path;\r
+       for (;;) {\r
+               c = p[si++];\r
+               if (c <= ' ' || c == '/') break;        /* Break on end of segment */\r
+               if (c == '.' || i >= ni) {\r
+                       if (ni != 8 || c != '.') break;\r
+                       i = 8; ni = 11;\r
+                       continue;\r
+               }\r
+#ifdef _EXCVT\r
+               if (c >= 0x80)                                  /* To upper extended char (SBCS) */\r
+                       c = cvt[c - 0x80];\r
+#endif\r
+               if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */\r
+                       d = p[si++];                            /* Get 2nd byte */\r
+                       sfn[i++] = c;\r
+                       sfn[i++] = d;\r
+               } else {                                                /* Single byte code */\r
+                       if (IsLower(c)) c -= 0x20;      /* toupper */\r
+                       sfn[i++] = c;\r
+               }\r
+       }\r
+       *path = &p[si];                                         /* Rerurn pointer to the next segment */\r
+\r
+       sfn[11] = (c <= ' ') ? 1 : 0;           /* Set last segment flag if end of path */\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Get file information from directory entry                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+static\r
+void get_fileinfo (            /* No return code */\r
+       DIR *dj,                        /* Pointer to the directory object */\r
+       BYTE *dir,                      /* 32-byte working buffer */\r
+       FILINFO *fno            /* Pointer to store the file information */\r
+)\r
+{\r
+       BYTE i, c;\r
+       char *p;\r
+\r
+\r
+       p = fno->fname;\r
+       if (dj->sect) {\r
+               for (i = 0; i < 8; i++) {       /* Copy file name body */\r
+                       c = dir[i];\r
+                       if (c == ' ') break;\r
+                       if (c == 0x05) c = 0xE5;\r
+                       *p++ = c;\r
+               }\r
+               if (dir[8] != ' ') {            /* Copy file name extension */\r
+                       *p++ = '.';\r
+                       for (i = 8; i < 11; i++) {\r
+                               c = dir[i];\r
+                               if (c == ' ') break;\r
+                               *p++ = c;\r
+                       }\r
+               }\r
+               fno->fattrib = dir[DIR_Attr];                           /* Attribute */\r
+               fno->fsize = LD_DWORD(dir+DIR_FileSize);        /* Size */\r
+               fno->fdate = LD_WORD(dir+DIR_WrtDate);          /* Date */\r
+               fno->ftime = LD_WORD(dir+DIR_WrtTime);          /* Time */\r
+       }\r
+       *p = 0;\r
+}\r
+#endif /* _USE_DIR */\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Follow a file path                                                    */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT follow_path (  /* FR_OK(0): successful, !=0: error code */\r
+       DIR *dj,                        /* Directory object to return last directory and found object */\r
+       BYTE *dir,                      /* 32-byte working buffer */\r
+       const char *path        /* Full-path string to find a file or directory */\r
+)\r
+{\r
+       FRESULT res;\r
+\r
+\r
+       while (*path == ' ') path++;            /* Skip leading spaces */\r
+       if (*path == '/') path++;                       /* Strip heading separator */\r
+       dj->sclust = 0;                                         /* Set start directory (always root dir) */\r
+\r
+       if ((BYTE)*path <= ' ') {                       /* Null path means the root directory */\r
+               res = dir_rewind(dj);\r
+               dir[0] = 0;\r
+\r
+       } else {                                                        /* Follow path */\r
+               for (;;) {\r
+                       res = create_name(dj, &path);   /* Get a segment */\r
+                       if (res != FR_OK) break;\r
+                       res = dir_find(dj, dir);                /* Find it */\r
+                       if (res != FR_OK) {                             /* Could not find the object */\r
+                               if (res == FR_NO_FILE && !*(dj->fn+11))\r
+                                       res = FR_NO_PATH;\r
+                               break;\r
+                       }\r
+                       if (*(dj->fn+11)) break;                /* Last segment match. Function completed. */\r
+                       if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */\r
+                               res = FR_NO_PATH; break;\r
+                       }\r
+                       dj->sclust = LD_CLUST(dir);\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Check a sector if it is an FAT boot record                            */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE check_fs (        /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */\r
+       BYTE *buf,      /* Working buffer */\r
+       DWORD sect      /* Sector# (lba) to check if it is an FAT boot record or not */\r
+)\r
+{\r
+       if (disk_readp(buf, sect, 510, 2))              /* Read the boot sector */\r
+               return 3;\r
+       if (LD_WORD(buf) != 0xAA55)                             /* Check record signature */\r
+               return 2;\r
+\r
+       if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */\r
+               return 0;\r
+       if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)  /* Check FAT32 */\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Public Functions\r
+\r
+--------------------------------------------------------------------------*/\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Mount/Unmount a Locical Drive                                         */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_mount (\r
+       FATFS *fs               /* Pointer to new file system object (NULL: Unmount) */\r
+)\r
+{\r
+       BYTE fmt, buf[36];\r
+       DWORD bsect, fsize, tsect, mclst;\r
+\r
+\r
+       FatFs = 0;\r
+       if (!fs) return FR_OK;                          /* Unregister fs object */\r
+\r
+       if (disk_initialize() & STA_NOINIT)     /* Check if the drive is ready or not */\r
+               return FR_NOT_READY;\r
+\r
+       /* Search FAT partition on the drive */\r
+       bsect = 0;\r
+       fmt = check_fs(buf, bsect);                     /* Check sector 0 as an SFD format */\r
+       if (fmt == 1) {                                         /* Not an FAT boot record, it may be FDISK format */\r
+               /* Check a partition listed in top of the partition table */\r
+               if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */\r
+                       fmt = 3;\r
+               } else {\r
+                       if (buf[4]) {                                   /* Is the partition existing? */\r
+                               bsect = LD_DWORD(&buf[8]);      /* Partition offset in LBA */\r
+                               fmt = check_fs(buf, bsect);     /* Check the partition */\r
+                       }\r
+               }\r
+       }\r
+       if (fmt == 3) return FR_DISK_ERR;\r
+       if (fmt) return FR_NO_FILESYSTEM;       /* No valid FAT patition is found */\r
+\r
+       /* Initialize the file system object */\r
+       if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;\r
+\r
+       fsize = LD_WORD(buf+BPB_FATSz16-13);                            /* Number of sectors per FAT */\r
+       if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);\r
+\r
+       fsize *= buf[BPB_NumFATs-13];                                           /* Number of sectors in FAT area */\r
+       fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */\r
+       fs->csize = buf[BPB_SecPerClus-13];                                     /* Number of sectors per cluster */\r
+       fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);         /* Nmuber of root directory entries */\r
+       tsect = LD_WORD(buf+BPB_TotSec16-13);                           /* Number of sectors on the file system */\r
+       if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);\r
+       mclst = (tsect                                          /* Last cluster# + 1 */\r
+               - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16\r
+               ) / fs->csize + 2;\r
+       fs->n_fatent = (CLUST)mclst;\r
+\r
+       fmt = FS_FAT16;                                                 /* Determine the FAT sub type */\r
+       if (mclst < 0xFF7)                                              /* Number of clusters < 0xFF5 */\r
+#if _FS_FAT12\r
+               fmt = FS_FAT12;\r
+#else\r
+               return FR_NO_FILESYSTEM;\r
+#endif\r
+       if (mclst >= 0xFFF7)                                    /* Number of clusters >= 0xFFF5 */\r
+#if _FS_FAT32\r
+               fmt = FS_FAT32;\r
+#else\r
+               return FR_NO_FILESYSTEM;\r
+#endif\r
+\r
+       fs->fs_type = fmt;              /* FAT sub-type */\r
+       if (_FS_FAT32 && fmt == FS_FAT32)\r
+               fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));  /* Root directory start cluster */\r
+       else\r
+               fs->dirbase = fs->fatbase + fsize;                              /* Root directory start sector (lba) */\r
+       fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;        /* Data start sector (lba) */\r
+\r
+       fs->flag = 0;\r
+       FatFs = fs;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Open or Create a File                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_open (\r
+       const char *path        /* Pointer to the file name */\r
+)\r
+{\r
+       FRESULT res;\r
+       DIR dj;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs)                                                /* Check file system */\r
+               return FR_NOT_ENABLED;\r
+\r
+       fs->flag = 0;\r
+       dj.fn = sp;\r
+       res = follow_path(&dj, dir, path);      /* Follow the file path */\r
+       if (res != FR_OK) return res;           /* Follow failed */\r
+       if (!dir[0] || (dir[DIR_Attr] & AM_DIR))        /* It is a directory */\r
+               return FR_NO_FILE;\r
+\r
+       fs->org_clust = LD_CLUST(dir);                  /* File start cluster */\r
+       fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */\r
+       fs->fptr = 0;                                           /* File pointer */\r
+       fs->flag = FA_OPENED;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read File                                                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_READ\r
+\r
+FRESULT pf_read (\r
+       void* buff,             /* Pointer to the read buffer (NULL:Forward data to the stream)*/\r
+       WORD btr,               /* Number of bytes to read */\r
+       WORD* br                /* Pointer to number of bytes read */\r
+)\r
+{\r
+       DRESULT dr;\r
+       CLUST clst;\r
+       DWORD sect, remain;\r
+       WORD rcnt;\r
+       BYTE cs, *rbuff = buff;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       *br = 0;\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+               return FR_NOT_OPENED;\r
+\r
+       remain = fs->fsize - fs->fptr;\r
+       if (btr > remain) btr = (WORD)remain;                   /* Truncate btr by remaining bytes */\r
+\r
+       while (btr)     {                                                                       /* Repeat until all data transferred */\r
+               if ((fs->fptr % 512) == 0) {                            /* On the sector boundary? */\r
+                       cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
+                       if (!cs) {                                                              /* On the cluster boundary? */\r
+                               clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
+                                       fs->org_clust : get_fat(fs->curr_clust);\r
+                               if (clst <= 1) goto fr_abort;\r
+                               fs->curr_clust = clst;                          /* Update current cluster */\r
+                       }\r
+                       sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
+                       if (!sect) goto fr_abort;\r
+                       fs->dsect = sect + cs;\r
+               }\r
+               rcnt = (WORD)(512 - (fs->fptr % 512));          /* Get partial sector data from sector buffer */\r
+               if (rcnt > btr) rcnt = btr;\r
+               dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);\r
+               if (dr) goto fr_abort;\r
+               fs->fptr += rcnt; rbuff += rcnt;                        /* Update pointers and counters */\r
+               btr -= rcnt; *br += rcnt;\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fr_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Write File                                                            */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_WRITE\r
+\r
+FRESULT pf_write (\r
+       const void* buff,       /* Pointer to the data to be written */\r
+       WORD btw,                       /* Number of bytes to write (0:Finalize the current write operation) */\r
+       WORD* bw                        /* Pointer to number of bytes written */\r
+)\r
+{\r
+       CLUST clst;\r
+       DWORD sect, remain;\r
+       const BYTE *p = buff;\r
+       BYTE cs;\r
+       WORD wcnt;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       *bw = 0;\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+               return FR_NOT_OPENED;\r
+\r
+       if (!btw) {             /* Finalize request */\r
+               if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;\r
+               fs->flag &= ~FA__WIP;\r
+               return FR_OK;\r
+       } else {                /* Write data request */\r
+               if (!(fs->flag & FA__WIP))              /* Round-down fptr to the sector boundary */\r
+                       fs->fptr &= 0xFFFFFE00;\r
+       }\r
+       remain = fs->fsize - fs->fptr;\r
+       if (btw > remain) btw = (WORD)remain;                   /* Truncate btw by remaining bytes */\r
+\r
+       while (btw)     {                                                                       /* Repeat until all data transferred */\r
+               if (((WORD)fs->fptr % 512) == 0) {                      /* On the sector boundary? */\r
+                       cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
+                       if (!cs) {                                                              /* On the cluster boundary? */\r
+                               clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
+                                       fs->org_clust : get_fat(fs->curr_clust);\r
+                               if (clst <= 1) goto fw_abort;\r
+                               fs->curr_clust = clst;                          /* Update current cluster */\r
+                       }\r
+                       sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
+                       if (!sect) goto fw_abort;\r
+                       fs->dsect = sect + cs;\r
+                       if (disk_writep(0, fs->dsect)) goto fw_abort;   /* Initiate a sector write operation */\r
+                       fs->flag |= FA__WIP;\r
+               }\r
+               wcnt = 512 - ((WORD)fs->fptr % 512);            /* Number of bytes to write to the sector */\r
+               if (wcnt > btw) wcnt = btw;\r
+               if (disk_writep(p, wcnt)) goto fw_abort;        /* Send data to the sector */\r
+               fs->fptr += wcnt; p += wcnt;                            /* Update pointers and counters */\r
+               btw -= wcnt; *bw += wcnt;\r
+               if (((WORD)fs->fptr % 512) == 0) {\r
+                       if (disk_writep(0, 0)) goto fw_abort;   /* Finalize the currtent secter write operation */\r
+                       fs->flag &= ~FA__WIP;\r
+               }\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fw_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Seek File R/W Pointer                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_LSEEK\r
+\r
+FRESULT pf_lseek (\r
+       DWORD ofs               /* File pointer from top of file */\r
+)\r
+{\r
+       CLUST clst;\r
+       DWORD bcs, sect, ifptr;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+                       return FR_NOT_OPENED;\r
+\r
+       if (ofs > fs->fsize) ofs = fs->fsize;   /* Clip offset with the file size */\r
+       ifptr = fs->fptr;\r
+       fs->fptr = 0;\r
+       if (ofs > 0) {\r
+               bcs = (DWORD)fs->csize * 512;   /* Cluster size (byte) */\r
+               if (ifptr > 0 &&\r
+                       (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */\r
+                       fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */\r
+                       ofs -= fs->fptr;\r
+                       clst = fs->curr_clust;\r
+               } else {                                                        /* When seek to back cluster, */\r
+                       clst = fs->org_clust;                   /* start from the first cluster */\r
+                       fs->curr_clust = clst;\r
+               }\r
+               while (ofs > bcs) {                             /* Cluster following loop */\r
+                       clst = get_fat(clst);           /* Follow cluster chain */\r
+                       if (clst <= 1 || clst >= fs->n_fatent) goto fe_abort;\r
+                       fs->curr_clust = clst;\r
+                       fs->fptr += bcs;\r
+                       ofs -= bcs;\r
+               }\r
+               fs->fptr += ofs;\r
+               sect = clust2sect(clst);                /* Current sector */\r
+               if (!sect) goto fe_abort;\r
+               fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1));\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fe_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Create a Directroy Object                                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+\r
+FRESULT pf_opendir (\r
+       DIR *dj,                        /* Pointer to directory object to create */\r
+       const char *path        /* Pointer to the directory path */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) {                              /* Check file system */\r
+               res = FR_NOT_ENABLED;\r
+       } else {\r
+               dj->fn = sp;\r
+               res = follow_path(dj, dir, path);               /* Follow the path to the directory */\r
+               if (res == FR_OK) {                                             /* Follow completed */\r
+                       if (dir[0]) {                                           /* It is not the root dir */\r
+                               if (dir[DIR_Attr] & AM_DIR)             /* The object is a directory */\r
+                                       dj->sclust = LD_CLUST(dir);\r
+                               else                                                    /* The object is not a directory */\r
+                                       res = FR_NO_PATH;\r
+                       }\r
+                       if (res == FR_OK)\r
+                               res = dir_rewind(dj);                   /* Rewind dir */\r
+               }\r
+               if (res == FR_NO_FILE) res = FR_NO_PATH;\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read Directory Entry in Sequense                                      */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_readdir (\r
+       DIR *dj,                        /* Pointer to the open directory object */\r
+       FILINFO *fno            /* Pointer to file information to return */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) {                              /* Check file system */\r
+               res = FR_NOT_ENABLED;\r
+       } else {\r
+               dj->fn = sp;\r
+               if (!fno) {\r
+                       res = dir_rewind(dj);\r
+               } else {\r
+                       res = dir_read(dj, dir);\r
+                       if (res == FR_NO_FILE) {\r
+                               dj->sect = 0;\r
+                               res = FR_OK;\r
+                       }\r
+                       if (res == FR_OK) {                             /* A valid entry is found */\r
+                               get_fileinfo(dj, dir, fno);     /* Get the object information */\r
+                               res = dir_next(dj);                     /* Increment index for next */\r
+                               if (res == FR_NO_FILE) {\r
+                                       dj->sect = 0;\r
+                                       res = FR_OK;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+#endif /* _USE_DIR */\r
+\r
diff --git a/firm/07/os/pff.h b/firm/07/os/pff.h
new file mode 100644 (file)
index 0000000..85be222
--- /dev/null
@@ -0,0 +1,188 @@
+/*---------------------------------------------------------------------------/\r
+/  Petit FatFs - FAT file system module include file  R0.02a   (C)ChaN, 2010\r
+/----------------------------------------------------------------------------/\r
+/ Petit FatFs module is an open source software to implement FAT file system to\r
+/ small embedded systems. This is a free software and is opened for education,\r
+/ research and commercial developments under license policy of following trems.\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/----------------------------------------------------------------------------*/\r
+\r
+#include "integer.h"\r
+\r
+/*---------------------------------------------------------------------------/\r
+/ Petit FatFs Configuration Options\r
+/\r
+/ CAUTION! Do not forget to make clean the project after any changes to\r
+/ the configuration options.\r
+/\r
+/----------------------------------------------------------------------------*/\r
+#ifndef _FATFS\r
+#define _FATFS\r
+\r
+#define        _USE_READ       1       /* 1:Enable pf_read() */\r
+\r
+#define        _USE_DIR        1       /* 1:Enable pf_opendir() and pf_readdir() */\r
+\r
+#define        _USE_LSEEK      1       /* 1:Enable pf_lseek() */\r
+\r
+#define        _USE_WRITE      1       /* 1:Enable pf_write() */\r
+\r
+#define _FS_FAT12      1       /* 1:Enable FAT12 support */\r
+#define _FS_FAT32      1       /* 1:Enable FAT32 support */\r
+\r
+\r
+#define        _CODE_PAGE      1\r
+/* Defines which code page is used for path name. Supported code pages are:\r
+/  932, 936, 949, 950, 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866,\r
+/  874, 1250, 1251, 1252, 1253, 1254, 1255, 1257, 1258 and 1 (ASCII only).\r
+/  SBCS code pages except for 1 requiers a case conversion table. This\r
+/  might occupy 128 bytes on the RAM on some platforms, e.g. avr-gcc. */\r
+\r
+\r
+#define _WORD_ACCESS   0\r
+/* The _WORD_ACCESS option defines which access method is used to the word\r
+/  data in the FAT structure.\r
+/\r
+/   0: Byte-by-byte access. Always compatible with all platforms.\r
+/   1: Word access. Do not choose this unless following condition is met.\r
+/\r
+/  When the byte order on the memory is big-endian or address miss-aligned\r
+/  word access results incorrect behavior, the _WORD_ACCESS must be set to 0.\r
+/  If it is not the case, the value can also be set to 1 to improve the\r
+/  performance and code efficiency. */\r
+\r
+\r
+/* End of configuration options. Do not change followings without care.     */\r
+/*--------------------------------------------------------------------------*/\r
+\r
+\r
+\r
+#if _FS_FAT32\r
+#define        CLUST   DWORD\r
+#else\r
+#define        CLUST   WORD\r
+#endif\r
+\r
+\r
+/* File system object structure */\r
+\r
+typedef struct {\r
+       BYTE    fs_type;        /* FAT sub type */\r
+       BYTE    flag;           /* File status flags */\r
+       BYTE    csize;          /* Number of sectors per cluster */\r
+       BYTE    pad1;\r
+       WORD    n_rootdir;      /* Number of root directory entries (0 on FAT32) */\r
+       CLUST   n_fatent;       /* Number of FAT entries (= number of clusters + 2) */\r
+       DWORD   fatbase;        /* FAT start sector */\r
+       DWORD   dirbase;        /* Root directory start sector (Cluster# on FAT32) */\r
+       DWORD   database;       /* Data start sector */\r
+       DWORD   fptr;           /* File R/W pointer */\r
+       DWORD   fsize;          /* File size */\r
+       CLUST   org_clust;      /* File start cluster */\r
+       CLUST   curr_clust;     /* File current cluster */\r
+       DWORD   dsect;          /* File current data sector */\r
+} FATFS;\r
+\r
+/* Directory object structure */\r
+\r
+typedef struct {\r
+       WORD    index;          /* Current read/write index number */\r
+       BYTE*   fn;                     /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */\r
+       CLUST   sclust;         /* Table start cluster (0:Static table) */\r
+       CLUST   clust;          /* Current cluster */\r
+       DWORD   sect;           /* Current sector */\r
+} DIR;\r
+\r
+/* File status structure */\r
+\r
+typedef struct {\r
+       DWORD   fsize;          /* File size */\r
+       WORD    fdate;          /* Last modified date */\r
+       WORD    ftime;          /* Last modified time */\r
+       BYTE    fattrib;        /* Attribute */\r
+       char    fname[13];      /* File name */\r
+} FILINFO;\r
+\r
+\r
+\r
+/* File function return code (FRESULT) */\r
+\r
+typedef enum {\r
+       FR_OK = 0,                      /* 0 */\r
+       FR_DISK_ERR,            /* 1 */\r
+       FR_NOT_READY,           /* 2 */\r
+       FR_NO_FILE,                     /* 3 */\r
+       FR_NO_PATH,                     /* 4 */\r
+       FR_NOT_OPENED,          /* 5 */\r
+       FR_NOT_ENABLED,         /* 6 */\r
+       FR_NO_FILESYSTEM        /* 7 */\r
+} FRESULT;\r
+\r
+\r
+\r
+/*--------------------------------------------------------------*/\r
+/* Petit FatFs module application interface                     */\r
+\r
+FRESULT pf_mount (FATFS*);                                             /* Mount/Unmount a logical drive */\r
+FRESULT pf_open (const char*);                                 /* Open a file */\r
+FRESULT pf_read (void*, WORD, WORD*);                  /* Read data from the open file */\r
+FRESULT pf_write (const void*, WORD, WORD*);   /* Write data to the open file */\r
+FRESULT pf_lseek (DWORD);                                              /* Move file pointer of the open file */\r
+FRESULT pf_opendir (DIR*, const char*);                        /* Open a directory */\r
+FRESULT pf_readdir (DIR*, FILINFO*);                   /* Read a directory item from the open directory */\r
+\r
+\r
+\r
+/*--------------------------------------------------------------*/\r
+/* Flags and offset address                                     */\r
+\r
+/* File status flag (FATFS.flag) */\r
+\r
+#define        FA_OPENED       0x01\r
+#define        FA_WPRT         0x02\r
+#define        FA__WIP         0x40\r
+\r
+\r
+/* FAT sub type (FATFS.fs_type) */\r
+\r
+#define FS_FAT12       1\r
+#define FS_FAT16       2\r
+#define FS_FAT32       3\r
+\r
+\r
+/* File attribute bits for directory entry */\r
+\r
+#define        AM_RDO  0x01    /* Read only */\r
+#define        AM_HID  0x02    /* Hidden */\r
+#define        AM_SYS  0x04    /* System */\r
+#define        AM_VOL  0x08    /* Volume label */\r
+#define AM_LFN 0x0F    /* LFN entry */\r
+#define AM_DIR 0x10    /* Directory */\r
+#define AM_ARC 0x20    /* Archive */\r
+#define AM_MASK        0x3F    /* Mask of defined bits */\r
+\r
+\r
+/*--------------------------------*/\r
+/* Multi-byte word access macros  */\r
+\r
+#if _WORD_ACCESS == 1  /* Enable word access to the FAT structure */\r
+#define        LD_WORD(ptr)            (WORD)(*(WORD*)(BYTE*)(ptr))\r
+#define        LD_DWORD(ptr)           (DWORD)(*(DWORD*)(BYTE*)(ptr))\r
+#define        ST_WORD(ptr,val)        *(WORD*)(BYTE*)(ptr)=(WORD)(val)\r
+#define        ST_DWORD(ptr,val)       *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)\r
+#else                                  /* Use byte-by-byte access to the FAT structure */\r
+#define        LD_WORD(ptr)            (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))\r
+#define        LD_DWORD(ptr)           (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))\r
+#define        ST_WORD(ptr,val)        *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)\r
+#define        ST_DWORD(ptr,val)       *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)\r
+#endif\r
+\r
+\r
+#endif /* _FATFS */\r