Mbed OS version of IoT.js implementation running on GR-PEACH

ビルド方法

ビルド環境セットアップ

Host PC要件 : Ubuntu 16.04 (64-bit)



1. 以下のコマンドを実行し、下表に示すツールをインストールします。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install [Package]
PackageVersion
build-essential12.1ubuntu2
gyp0.1+20150913git1f374df9-1ubuntu1
mercurial3.7.3-1ubuntu1
cmake3.5.1-1ubuntu3
git1:2.7.4-0ubuntu1.4
python2.72.7.12-1ubuntu016.04.3
valgrind1:3.11.0-1ubuntu4.2
python-pip8.1.1-2ubuntu0.4

2. 以下のコマンドを実行してMbed OS用ビルドツール mbed CLIをインストールします。

$ sudo -H pip install mbed-cli

3. GNU Arm Embedded Toolchainをインストールします。

  • ダウンロードしたファイルを任意のディレクトリに展開します。
    (以下、展開先を${TOOLCHAIN}と記載します)

tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2
  • ツールチェインのパスを設定します。

環境変数を使用する場合

$ export GCC_ARM_ROOT=${TOOLCHAIN}/gcc-arm-none-eabi-6-2017-q2-update/bin
$ export PATH=$GCC_ARM_ROOT:$PATH

mbed CLIで指定する場合

$ mbed config -G GCC_ARM_PATH $GCC_ARM_ROOT

iotjs環境のビルド

1. 本プログラムのクローン

下記コマンドを実行し、本プログラムをクローンしてください。

$ hg clone https://HinoNaka@os.mbed.com/users/HinoNaka/code/GR-PEACH_mbed-os-iotjs/

クローンが正常に終了すると、GR-PEACH_mbed-os-iotjs という名称のディレクトリが生成されますので、下記コマンドで当該ディレクトリへ移動してください。

$ cd GR-PEACH_mbed-os-iotjs

(Optional)
GR-PEACH-mbed-os-iotjsディレクトリを指す環境変数 ROOTを設定してください。以降の記載は本環境変数が設定されているものとします。

$ export ROOT=$(PWD)

2. 作業用ディレクトリ(e.g. work)を作成し、当該ディレクトリに移動してください。

$ mkdir -p work
$ cd work

(Optional)
作業用ディレクトリを指す環境変数 WORK を設定してください。以降の記載は本環境変数 が設定されているものとします。

$ export WORK=$(PWD)

3. iotjsのソースツリーを取得します。

$ git clone https://github.com/pando-project/iotjs

クローンが正常に終了するとiotjsというディレクトリが生成されますので、当該ディレクトリに移動してください。

$cd iotjs

コミットID: acae9c8b2d40e7598b8d39b630b79113ce880a7e を取得します。
(下記例では、あわせてposixというブランチを作成し、当該ブランチへ切り替えています)

$ git checkout -b posix acae9c8b2d40e7598b8d39b630b79113ce880a7e

4. mbed-osセットアップ
Mbed OSソースツリーを格納するフォルダを生成し、当該フォルダへ移動します。

$ mkdir -p $(WORK)/iotjs/src/platform/mbedos5
$ cd $(WORK)/iotjs/src/platform/mbedos5

Mbed OSのソースツリーをクローンします。

$ git clone -b mbed-os-5.9 https://github.com/ARMmbed/mbed-os.git

クローンが正常に終了するとmbed-osというディレクトリが生成されますので、当該ディレクトリに移動してください。

$ cd mbed-os

コミットID: 50bd61a4a72332baa6b1bac6caccb44dc5423309 を取得します。
(下記例では、あわせてposixというブランチを作成し、当該ブランチへ切り替えています)

$ git checkout -b posix 50bd61a4a72332baa6b1bac6caccb44dc5423309

5. sd-driverの取得
下記コマンドでmbedos5ディレクトリへ移動します。

$ cd $(WORK)/iotjs/src/platform/mbedos5

sd-driverをクローンします。

$ git clone https://github.com/ARMmbed/sd-driver.git

クローンが正常終了するとsd-driverディレクトリが生成されますので、当該ディレクトリへ移動します。

$ cd sd-driver

コミットID: c8ae38fb291e086232566b0f1372cfb69c277e84 を取得します。
(下記例では、あわせてposixというブランチを作成し、当該ブランチへ切り替えています)

$ git checkout -b posix c8ae38fb291e086232566b0f1372cfb69c277e84

6. mbed-gr-libsの取得
下記コマンドでmbedos5ディレクトリへ移動します。

$ cd $(WORK)/iotjs/src/platform/mbedos5

mbed-gr-libsをクローンします。

$ git clone https://github.com/d-kato/mbed-gr-libs

クローンが正常終了するとmbed-gr-libsディレクトリが生成されますので、当該ディレクトリへ移動します。

$ cd mbed-gr-libs

コミットID: d921d611d596ecaebaab49070ef82450c583309c を取得します。
(下記例では、あわせてposixというブランチを作成し、当該ブランチへ切り替えています)

$ git checkout -b posix d921d611d596ecaebaab49070ef82450c583309c

7. AsciiFONTの取得
下記コマンドでmbedos5ディレクトリへ移動します。

$ cd $(WORK)/iotjs/src/platform/mbedos5

AsciiFONTライブラリを追加します。

$ mbed add https://os.mbed.com/teams/Renesas/code/AsciiFont/

8. iotjs環境のビルド
下記コマンドでiotjs環境のビルドディレクトリに移動し、ビルドを実行します。

$ cd $(WORK)/iotjs
$ ./tools/build.py --no-snapshot

9. GR-PEACH用コードのコピー
(Optional) 既存のiotjs環境に上書きする場合、下記コマンドを実行してください。

$ rm -rf $(WORK)/iotjs/deps/posix
$ rm -rf $(WORK)/iotjs/src/ext-modules
$ rm -rf $(WORK)/iotjs/src/platform/mbedos5/iotjs_def.h

下記コマンドでGR-PEACH用コードをコピーします。

$ cp -pr $(ROOT)/src/iotjs/* $(WORK)/iotjs/

10. lwipパッチ適用
以下コマンドでlwipパッチを適用します。

$ cd $(WORK)/iotjs/src/platform/mbedos5/mbed-os
$ git apply lwip_improve.patch

11. ESP32 TRNG対応パッチ適用
以下コマンドでESP32のTRNGを活用するためのパッチを適用します。

$ cd $(WORK)/iotjs/src/platform/mbedos5/mbed-os
$ git apply trng_support.patch

12. Mbed OS版iotjs環境のビルド
下記コマンドを実行してMbed OS版iotjs環境をビルドします。
(リリースビルドの場合)

$ cd $(WORK)/iotjs/src/platform/mbedos5
$ make clean; make DEBUG=0

(デバッグビルドの場合)

$ cd $(WORK)/iotjs/src/platform/mbedos5
$ make clean; make DEBUG=1

13. ビルドが正常に終了すると、以下の通りバイナリが生成されます。
(リリースビルドの場合)

$ ls -l ${WORK}/iotjs/src/platform/mbedos5/BUILD/RZ_A1H/GCC_ARM-RELEASE/iotjs.bin

(デバッグビルドの場合)

$ ls -l ${WORK}/iotjs/src/platform/mbedos5/BUILD/RZ_A1H/GCC_ARM-DEBUG/iotjs.bin

実行方法

1. GR-PEACHにmicro SDカードを挿入します。

2. GR-PEACHのEthernetポートから遠い側のUSBポートとHost PCをマイクロUSBケーブルで接続します。

3. Host PCでGR-PEACHが『mbed:』ドライブとして認識されたら、iotjs.binをmbedドライブにコピーします。

4. ターミナルS/Wを立上げ、『mbed Serial Port』と接続します。
/media/uploads/HinoNaka/img1.jpg
シリアルポートは下記設定としてください。

Baud rate115200
Data8 bit
Paritynone
Stop1 bit
Flow controlnone

5. 正常に書込みが終了したらGR-PEACHのRESETボタンを押下します。

6. ターミナルS/W上に下記メッセージが表示されます。
/media/uploads/HinoNaka/img2.jpg

7. Enterキーを押下してコード入力モードに移行します。
/media/uploads/HinoNaka/img3.jpg

8. 実行するJavascriptコードをターミナルソフトウェアに貼り付けてEnterキーを押下すると、実行開始します。Javascriptコード例については、test/case.txtを参照ください。

Revision:
1:c3d69f309845
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/api/jpeg.html	Thu Jul 11 18:49:37 2019 +0900
@@ -0,0 +1,967 @@
+<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description"><meta name="keywords"><meta name="robots"><title>GR-PEACH JPEGモジュール</title><style>@font-face {
+  font-family: octicons-link;
+  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');
+}
+
+.markdown-body {
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+  line-height: 1.5;
+  color: #24292e;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+  font-size: 16px;
+  line-height: 1.5;
+  word-wrap: break-word;
+}
+
+.markdown-body .pl-c {
+  color: #6a737d;
+}
+
+.markdown-body .pl-c1,
+.markdown-body .pl-s .pl-v {
+  color: #005cc5;
+}
+
+.markdown-body .pl-e,
+.markdown-body .pl-en {
+  color: #6f42c1;
+}
+
+.markdown-body .pl-smi,
+.markdown-body .pl-s .pl-s1 {
+  color: #24292e;
+}
+
+.markdown-body .pl-ent {
+  color: #22863a;
+}
+
+.markdown-body .pl-k {
+  color: #d73a49;
+}
+
+.markdown-body .pl-s,
+.markdown-body .pl-pds,
+.markdown-body .pl-s .pl-pse .pl-s1,
+.markdown-body .pl-sr,
+.markdown-body .pl-sr .pl-cce,
+.markdown-body .pl-sr .pl-sre,
+.markdown-body .pl-sr .pl-sra {
+  color: #032f62;
+}
+
+.markdown-body .pl-v,
+.markdown-body .pl-smw {
+  color: #e36209;
+}
+
+.markdown-body .pl-bu {
+  color: #b31d28;
+}
+
+.markdown-body .pl-ii {
+  color: #fafbfc;
+  background-color: #b31d28;
+}
+
+.markdown-body .pl-c2 {
+  color: #fafbfc;
+  background-color: #d73a49;
+}
+
+.markdown-body .pl-c2::before {
+  content: "^M";
+}
+
+.markdown-body .pl-sr .pl-cce {
+  font-weight: bold;
+  color: #22863a;
+}
+
+.markdown-body .pl-ml {
+  color: #735c0f;
+}
+
+.markdown-body .pl-mh,
+.markdown-body .pl-mh .pl-en,
+.markdown-body .pl-ms {
+  font-weight: bold;
+  color: #005cc5;
+}
+
+.markdown-body .pl-mi {
+  font-style: italic;
+  color: #24292e;
+}
+
+.markdown-body .pl-mb {
+  font-weight: bold;
+  color: #24292e;
+}
+
+.markdown-body .pl-md {
+  color: #b31d28;
+  background-color: #ffeef0;
+}
+
+.markdown-body .pl-mi1 {
+  color: #22863a;
+  background-color: #f0fff4;
+}
+
+.markdown-body .pl-mc {
+  color: #e36209;
+  background-color: #ffebda;
+}
+
+.markdown-body .pl-mi2 {
+  color: #f6f8fa;
+  background-color: #005cc5;
+}
+
+.markdown-body .pl-mdr {
+  font-weight: bold;
+  color: #6f42c1;
+}
+
+.markdown-body .pl-ba {
+  color: #586069;
+}
+
+.markdown-body .pl-sg {
+  color: #959da5;
+}
+
+.markdown-body .pl-corl {
+  text-decoration: underline;
+  color: #032f62;
+}
+
+.markdown-body .octicon {
+  display: inline-block;
+  vertical-align: text-top;
+  fill: currentColor;
+}
+
+.markdown-body a {
+  background-color: transparent;
+}
+
+.markdown-body a:active,
+.markdown-body a:hover {
+  outline-width: 0;
+}
+
+.markdown-body strong {
+  font-weight: inherit;
+}
+
+.markdown-body strong {
+  font-weight: bolder;
+}
+
+.markdown-body h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+.markdown-body img {
+  border-style: none;
+}
+
+.markdown-body code,
+.markdown-body kbd,
+.markdown-body pre {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+.markdown-body hr {
+  box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+.markdown-body input {
+  font: inherit;
+  margin: 0;
+}
+
+.markdown-body input {
+  overflow: visible;
+}
+
+.markdown-body [type="checkbox"] {
+  box-sizing: border-box;
+  padding: 0;
+}
+
+.markdown-body * {
+  box-sizing: border-box;
+}
+
+.markdown-body input {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+
+.markdown-body a {
+  color: #0366d6;
+  text-decoration: none;
+}
+
+.markdown-body a:hover {
+  text-decoration: underline;
+}
+
+.markdown-body strong {
+  font-weight: 600;
+}
+
+.markdown-body hr {
+  height: 0;
+  margin: 15px 0;
+  overflow: hidden;
+  background: transparent;
+  border: 0;
+  border-bottom: 1px solid #dfe2e5;
+}
+
+.markdown-body hr::before {
+  display: table;
+  content: "";
+}
+
+.markdown-body hr::after {
+  display: table;
+  clear: both;
+  content: "";
+}
+
+.markdown-body table {
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+.markdown-body td,
+.markdown-body th {
+  padding: 0;
+}
+
+.markdown-body h1,
+.markdown-body h2,
+.markdown-body h3,
+.markdown-body h4,
+.markdown-body h5,
+.markdown-body h6 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.markdown-body h1 {
+  font-size: 32px;
+  font-weight: 600;
+}
+
+.markdown-body h2 {
+  font-size: 24px;
+  font-weight: 600;
+}
+
+.markdown-body h3 {
+  font-size: 20px;
+  font-weight: 600;
+}
+
+.markdown-body h4 {
+  font-size: 16px;
+  font-weight: 600;
+}
+
+.markdown-body h5 {
+  font-size: 14px;
+  font-weight: 600;
+}
+
+.markdown-body h6 {
+  font-size: 12px;
+  font-weight: 600;
+}
+
+.markdown-body p {
+  margin-top: 0;
+  margin-bottom: 10px;
+}
+
+.markdown-body blockquote {
+  margin: 0;
+}
+
+.markdown-body ul,
+.markdown-body ol {
+  padding-left: 0;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.markdown-body ol ol,
+.markdown-body ul ol {
+  list-style-type: lower-roman;
+}
+
+.markdown-body ul ul ol,
+.markdown-body ul ol ol,
+.markdown-body ol ul ol,
+.markdown-body ol ol ol {
+  list-style-type: lower-alpha;
+}
+
+.markdown-body dd {
+  margin-left: 0;
+}
+
+.markdown-body code {
+  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  font-size: 12px;
+}
+
+.markdown-body pre {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  font-size: 12px;
+}
+
+.markdown-body .octicon {
+  vertical-align: text-bottom;
+}
+
+.markdown-body .pl-0 {
+  padding-left: 0 !important;
+}
+
+.markdown-body .pl-1 {
+  padding-left: 4px !important;
+}
+
+.markdown-body .pl-2 {
+  padding-left: 8px !important;
+}
+
+.markdown-body .pl-3 {
+  padding-left: 16px !important;
+}
+
+.markdown-body .pl-4 {
+  padding-left: 24px !important;
+}
+
+.markdown-body .pl-5 {
+  padding-left: 32px !important;
+}
+
+.markdown-body .pl-6 {
+  padding-left: 40px !important;
+}
+
+.markdown-body::before {
+  display: table;
+  content: "";
+}
+
+.markdown-body::after {
+  display: table;
+  clear: both;
+  content: "";
+}
+
+.markdown-body>*:first-child {
+  margin-top: 0 !important;
+}
+
+.markdown-body>*:last-child {
+  margin-bottom: 0 !important;
+}
+
+.markdown-body a:not([href]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+.markdown-body .anchor {
+  float: left;
+  padding-right: 4px;
+  margin-left: -20px;
+  line-height: 1;
+}
+
+.markdown-body .anchor:focus {
+  outline: none;
+}
+
+.markdown-body p,
+.markdown-body blockquote,
+.markdown-body ul,
+.markdown-body ol,
+.markdown-body dl,
+.markdown-body table,
+.markdown-body pre {
+  margin-top: 0;
+  margin-bottom: 16px;
+}
+
+.markdown-body hr {
+  height: 0.25em;
+  padding: 0;
+  margin: 24px 0;
+  background-color: #e1e4e8;
+  border: 0;
+}
+
+.markdown-body blockquote {
+  padding: 0 1em;
+  color: #6a737d;
+  border-left: 0.25em solid #dfe2e5;
+}
+
+.markdown-body blockquote>:first-child {
+  margin-top: 0;
+}
+
+.markdown-body blockquote>:last-child {
+  margin-bottom: 0;
+}
+
+.markdown-body kbd {
+  display: inline-block;
+  padding: 3px 5px;
+  font-size: 11px;
+  line-height: 10px;
+  color: #444d56;
+  vertical-align: middle;
+  background-color: #fafbfc;
+  border: solid 1px #c6cbd1;
+  border-bottom-color: #959da5;
+  border-radius: 3px;
+  box-shadow: inset 0 -1px 0 #959da5;
+}
+
+.markdown-body h1,
+.markdown-body h2,
+.markdown-body h3,
+.markdown-body h4,
+.markdown-body h5,
+.markdown-body h6 {
+  margin-top: 24px;
+  margin-bottom: 16px;
+  font-weight: 600;
+  line-height: 1.25;
+}
+
+.markdown-body h1 .octicon-link,
+.markdown-body h2 .octicon-link,
+.markdown-body h3 .octicon-link,
+.markdown-body h4 .octicon-link,
+.markdown-body h5 .octicon-link,
+.markdown-body h6 .octicon-link {
+  color: #1b1f23;
+  vertical-align: middle;
+  visibility: hidden;
+}
+
+.markdown-body h1:hover .anchor,
+.markdown-body h2:hover .anchor,
+.markdown-body h3:hover .anchor,
+.markdown-body h4:hover .anchor,
+.markdown-body h5:hover .anchor,
+.markdown-body h6:hover .anchor {
+  text-decoration: none;
+}
+
+.markdown-body h1:hover .anchor .octicon-link,
+.markdown-body h2:hover .anchor .octicon-link,
+.markdown-body h3:hover .anchor .octicon-link,
+.markdown-body h4:hover .anchor .octicon-link,
+.markdown-body h5:hover .anchor .octicon-link,
+.markdown-body h6:hover .anchor .octicon-link {
+  visibility: visible;
+}
+
+.markdown-body h1 {
+  padding-bottom: 0.3em;
+  font-size: 2em;
+  border-bottom: 1px solid #eaecef;
+}
+
+.markdown-body h2 {
+  padding-bottom: 0.3em;
+  font-size: 1.5em;
+  border-bottom: 1px solid #eaecef;
+}
+
+.markdown-body h3 {
+  font-size: 1.25em;
+}
+
+.markdown-body h4 {
+  font-size: 1em;
+}
+
+.markdown-body h5 {
+  font-size: 0.875em;
+}
+
+.markdown-body h6 {
+  font-size: 0.85em;
+  color: #6a737d;
+}
+
+.markdown-body ul,
+.markdown-body ol {
+  padding-left: 2em;
+}
+
+.markdown-body ul ul,
+.markdown-body ul ol,
+.markdown-body ol ol,
+.markdown-body ol ul {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.markdown-body li {
+  word-wrap: break-all;
+}
+
+.markdown-body li>p {
+  margin-top: 16px;
+}
+
+.markdown-body li+li {
+  margin-top: 0.25em;
+}
+
+.markdown-body dl {
+  padding: 0;
+}
+
+.markdown-body dl dt {
+  padding: 0;
+  margin-top: 16px;
+  font-size: 1em;
+  font-style: italic;
+  font-weight: 600;
+}
+
+.markdown-body dl dd {
+  padding: 0 16px;
+  margin-bottom: 16px;
+}
+
+.markdown-body table {
+  display: block;
+  width: 100%;
+  overflow: auto;
+}
+
+.markdown-body table th {
+  font-weight: 600;
+}
+
+.markdown-body table th,
+.markdown-body table td {
+  padding: 6px 13px;
+  border: 1px solid #dfe2e5;
+}
+
+.markdown-body table tr {
+  background-color: #fff;
+  border-top: 1px solid #c6cbd1;
+}
+
+.markdown-body table tr:nth-child(2n) {
+  background-color: #f6f8fa;
+}
+
+.markdown-body img {
+  max-width: 100%;
+  box-sizing: content-box;
+  background-color: #fff;
+}
+
+.markdown-body img[align=right] {
+  padding-left: 20px;
+}
+
+.markdown-body img[align=left] {
+  padding-right: 20px;
+}
+
+.markdown-body code {
+  padding: 0.2em 0.4em;
+  margin: 0;
+  font-size: 85%;
+  background-color: rgba(27,31,35,0.05);
+  border-radius: 3px;
+}
+
+.markdown-body pre {
+  word-wrap: normal;
+}
+
+.markdown-body pre>code {
+  padding: 0;
+  margin: 0;
+  font-size: 100%;
+  word-break: normal;
+  white-space: pre;
+  background: transparent;
+  border: 0;
+}
+
+.markdown-body .highlight {
+  margin-bottom: 16px;
+}
+
+.markdown-body .highlight pre {
+  margin-bottom: 0;
+  word-break: normal;
+}
+
+.markdown-body .highlight pre,
+.markdown-body pre {
+  padding: 16px;
+  overflow: auto;
+  font-size: 85%;
+  line-height: 1.45;
+  background-color: #f6f8fa;
+  border-radius: 3px;
+}
+
+.markdown-body pre code {
+  display: inline;
+  max-width: auto;
+  padding: 0;
+  margin: 0;
+  overflow: visible;
+  line-height: inherit;
+  word-wrap: normal;
+  background-color: transparent;
+  border: 0;
+}
+
+.markdown-body .full-commit .btn-outline:not(:disabled):hover {
+  color: #005cc5;
+  border-color: #005cc5;
+}
+
+.markdown-body kbd {
+  display: inline-block;
+  padding: 3px 5px;
+  font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  line-height: 10px;
+  color: #444d56;
+  vertical-align: middle;
+  background-color: #fafbfc;
+  border: solid 1px #d1d5da;
+  border-bottom-color: #c6cbd1;
+  border-radius: 3px;
+  box-shadow: inset 0 -1px 0 #c6cbd1;
+}
+
+.markdown-body :checked+.radio-label {
+  position: relative;
+  z-index: 1;
+  border-color: #0366d6;
+}
+
+.markdown-body .task-list-item {
+  list-style-type: none;
+}
+
+.markdown-body .task-list-item+.task-list-item {
+  margin-top: 3px;
+}
+
+.markdown-body .task-list-item input {
+  margin: 0 0.2em 0.25em -1.6em;
+  vertical-align: middle;
+}
+
+.markdown-body hr {
+  border-bottom-color: #eee;
+}
+/*
+
+Sunburst-like style (c) Vasily Polovnyov <vast@whiteants.net>
+
+*/
+
+.hljs {
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
+  background: #000;
+  color: #f8f8f8;
+}
+
+.hljs-comment,
+.hljs-quote {
+  color: #aeaeae;
+  font-style: italic;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #e28964;
+}
+
+.hljs-string {
+  color: #65b042;
+}
+
+.hljs-subst {
+  color: #daefa3;
+}
+
+.hljs-regexp,
+.hljs-link {
+  color: #e9c062;
+}
+
+.hljs-title,
+.hljs-section,
+.hljs-tag,
+.hljs-name {
+  color: #89bdff;
+}
+
+.hljs-class .hljs-title,
+.hljs-doctag {
+  text-decoration: underline;
+}
+
+.hljs-symbol,
+.hljs-bullet,
+.hljs-number {
+  color: #3387cc;
+}
+
+.hljs-params,
+.hljs-variable,
+.hljs-template-variable {
+  color: #3e87e3;
+}
+
+.hljs-attribute {
+  color: #cda869;
+}
+
+.hljs-meta {
+  color: #8996a8;
+}
+
+.hljs-formula {
+  background-color: #0e2231;
+  color: #f8f8f8;
+  font-style: italic;
+}
+
+.hljs-addition {
+  background-color: #253b22;
+  color: #f8f8f8;
+}
+
+.hljs-deletion {
+  background-color: #420e09;
+  color: #f8f8f8;
+}
+
+.hljs-selector-class {
+  color: #9b703f;
+}
+
+.hljs-selector-id {
+  color: #8b98ab;
+}
+
+.hljs-emphasis {
+  font-style: italic;
+}
+
+.hljs-strong {
+  font-weight: bold;
+}
+</style></head><body class="markdown-body"><h1 id="gr-peach-jpeg-jpeg-">GR-PEACH JPEGモジュール (jpeg)</h1>
+<p><code>jpeg</code> モジュールは、GR-PEACHマイコンに搭載されたJPEGコーデックを用いてJPEG画像のエンコード・デコードを行います。</p>
+<h2 id="jpeg-encode-image-callback-">jpeg.encode(image, callback)</h2>
+<ul>
+<li><code>image</code> {Object} エンコードする画像<ul>
+<li><code>width</code> {number} 画像の幅(ピクセル数)。必須項目です。この値は偶数でなければなりません。</li>
+<li><code>height</code> {number} 画像の高さ(ピクセル数)。必須項目です。</li>
+<li><code>format</code> {string} 画像のピクセルフォーマット。<code>&quot;ycbcr422&quot;</code>のみが指定可能です。必須項目です。</li>
+<li><code>bitmap</code> {AlignedBuffer} 画素データ。必須項目です。32バイトのアライメントである必要があります。</li>
+</ul>
+</li>
+<li><code>callback</code> {Function} コールバック関数<ul>
+<li><code>err</code> {Error|null} エラーオブジェクト(失敗のとき) または <code>null</code>(成功のとき)。</li>
+<li><code>jpegData</code> {AlignedBuffer} JPEGデータを格納したバッファ。32バイトのアライメントです。</li>
+</ul>
+</li>
+<li>戻り値: {undefined}</li>
+</ul>
+<p>ビットマップ画像をJPEG画像に変換します。処理は非同期で行われ、処理が完了または失敗すると、コールバック関数が呼び出されます。</p>
+<!--
+* C++ライブラリ側API
+  * JPEG_Converter::encode
+-->
+<h4 id="-">使用例</h4>
+<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> jpeg = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jpeg'</span>);
+<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
+<span class="hljs-keyword">var</span> AlignedBuffer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aligned_buffer'</span>).AlignedBuffer;
+
+<span class="hljs-keyword">var</span> bitmap = <span class="hljs-keyword">new</span> AlignedBuffer(<span class="hljs-number">480</span> * <span class="hljs-number">272</span> * <span class="hljs-number">2</span>, <span class="hljs-number">32</span>);
+<span class="hljs-comment">/* bitmap に画像データを格納する... */</span>
+<span class="hljs-keyword">var</span> image = {
+  <span class="hljs-attr">width</span>: <span class="hljs-number">480</span>,
+  <span class="hljs-attr">height</span>: <span class="hljs-number">272</span>,
+  <span class="hljs-attr">format</span>: <span class="hljs-string">'ycbcr422'</span>,
+  <span class="hljs-attr">bitmap</span>: bitmap
+};
+jpeg.encode(image, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, jpegData</span>) </span>{
+  <span class="hljs-keyword">if</span> (err) {
+    <span class="hljs-built_in">console</span>.log(err);
+    <span class="hljs-keyword">return</span>;
+  }
+  <span class="hljs-comment">/* ファイルに保存する */</span>
+  fs.writeFile(<span class="hljs-string">'/sd/output.jpg'</span>, jpegData.toBuffer(), <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err</span>) </span>{
+  });
+});
+</code></pre>
+<h2 id="jpeg-encodesync-image-">jpeg.encodeSync(image)</h2>
+<ul>
+<li><code>image</code> {Object} エンコードするビットマップ画像<ul>
+<li><code>jpeg.encode()</code>の説明を参照</li>
+</ul>
+</li>
+<li>戻り値: {AlignedBuffer} JPEGデータを格納したバッファ。32バイトのアライメントです。</li>
+</ul>
+<p><code>jpeg.encode()</code>の同期版です。処理は同期で行われ、処理が完了するとJPEGデータを格納したバッファを返却します。失敗すると例外をスローします。</p>
+<h4 id="-">使用例</h4>
+<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> jpeg = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jpeg'</span>);
+<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
+<span class="hljs-keyword">var</span> AlignedBuffer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aligned_buffer'</span>).AlignedBuffer;
+
+<span class="hljs-keyword">var</span> bitmap = <span class="hljs-keyword">new</span> AlignedBuffer(<span class="hljs-number">480</span> * <span class="hljs-number">272</span> * <span class="hljs-number">2</span>, <span class="hljs-number">32</span>);
+<span class="hljs-comment">/* bitmap に画像データを格納する... */</span>
+<span class="hljs-keyword">var</span> image = {
+  <span class="hljs-attr">width</span>: <span class="hljs-number">480</span>,
+  <span class="hljs-attr">height</span>: <span class="hljs-number">272</span>,
+  <span class="hljs-attr">format</span>: <span class="hljs-string">'ycbcr422'</span>,
+  <span class="hljs-attr">bitmap</span>: bitmap
+};
+<span class="hljs-keyword">try</span> {
+  <span class="hljs-keyword">var</span> jpegData = jpeg.encodeSync(image);
+  <span class="hljs-comment">/* ファイルに保存する */</span>
+  fs.writeFileSync(<span class="hljs-string">'/sd/output.jpg'</span>, jpegData.toBuffer());
+} <span class="hljs-keyword">catch</span> (err) {
+  <span class="hljs-built_in">console</span>.log(err);
+}
+</code></pre>
+<h2 id="jpeg-decode-jpegdata-config-callback-">jpeg.decode(jpegData, config, callback)</h2>
+<ul>
+<li><code>jpegData</code> {AlignedBuffer} JPEGデータを格納したバッファ。32バイトのアライメントである必要があります。</li>
+<li><code>config</code> {Object} デコード設定。<ul>
+<li><code>width</code> {number} 出力するビットマップの幅(ピクセル数)。この値は偶数でなければなりません。</li>
+<li><code>height</code> {number} 出力するビットマップの高さ(ピクセル数)。</li>
+<li><code>format</code> {string} 出力するビットマップのピクセルフォーマット。<code>&quot;ycbcr422&quot;</code>,<code>&quot;rgb565&quot;</code>,<code>&quot;argb8888&quot;</code>のいずれか。</li>
+<li><code>alpha</code> {number} ピクセルフォーマットが<code>&quot;argb8888&quot;</code>のときの透過度。<code>0</code>~<code>255</code>の値。(省略時: <code>255</code>)</li>
+</ul>
+</li>
+<li><code>callback</code> {Function} コールバック関数<ul>
+<li><code>err</code> {Error|null} エラーオブジェクト(失敗のとき) または <code>null</code>(成功のとき)。</li>
+<li><code>image</code> {Object} デコードされたビットマップ画像<ul>
+<li><code>width</code> {number} 画像の幅(ピクセル数)。</li>
+<li><code>height</code> {number} 画像の高さ(ピクセル数)。</li>
+<li><code>format</code> {string} 画像のピクセルフォーマット。<code>&quot;ycbcr422&quot;</code>,<code>&quot;rgb565&quot;</code>,<code>&quot;argb8888&quot;</code>のいずれか。</li>
+<li><code>bitmap</code> {AlignedBuffer} 画素データ。32バイトのアライメントです。</li>
+</ul>
+</li>
+</ul>
+</li>
+<li>戻り値: {undefined}</li>
+</ul>
+<p>JPEGデータをビットマップ画像に変換します。処理は非同期で行われ、処理が完了または失敗すると、コールバック関数が呼び出されます。</p>
+<!--
+* C++ライブラリ側API
+  * JPEG_Converter::decode
+-->
+<h4 id="-">使用例</h4>
+<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> AlignedBuffer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aligned_buffer'</span>).AlignedBuffer;
+<span class="hljs-keyword">var</span> jpeg = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jpeg'</span>);
+<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
+<span class="hljs-keyword">var</span> config = {
+  <span class="hljs-attr">width</span>: <span class="hljs-number">480</span>,
+  <span class="hljs-attr">height</span>: <span class="hljs-number">272</span>,
+  <span class="hljs-attr">format</span>: <span class="hljs-string">'argb8888'</span>,
+  <span class="hljs-attr">alpha</span>: <span class="hljs-number">0xFF</span>
+};
+fs.readFile(<span class="hljs-string">'/sd/input.jpg'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, jpegData</span>) </span>{
+  <span class="hljs-keyword">if</span> (err) {
+    <span class="hljs-comment">/* ファイル読み込み失敗... */</span>
+    <span class="hljs-built_in">console</span>.log(err);
+    <span class="hljs-keyword">return</span>;
+  }
+  <span class="hljs-keyword">var</span> buf = <span class="hljs-keyword">new</span> AlignedBuffer(jpegData, <span class="hljs-number">32</span>);
+  jpeg.decode(buf, config, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, image</span>) </span>{
+    <span class="hljs-keyword">if</span> (err) {
+      <span class="hljs-comment">/* デコード失敗... */</span>
+      <span class="hljs-built_in">console</span>.log(err);
+      <span class="hljs-keyword">return</span>;
+    }
+    <span class="hljs-comment">/* 成功... */</span>
+  });
+});
+</code></pre>
+<h2 id="jpeg-decodesync-jpegdata-config-">jpeg.decodeSync(jpegData, config)</h2>
+<ul>
+<li><code>jpegData</code> {AlignedBuffer} JPEGデータを格納したバッファ。32バイトのアライメントである必要があります。</li>
+<li><code>config</code> {Object} デコード設定。<ul>
+<li><code>width</code> {number} 出力するビットマップの幅(ピクセル数)。この値は偶数でなければなりません。</li>
+<li><code>height</code> {number} 出力するビットマップの高さ(ピクセル数)。</li>
+<li><code>format</code> {string} 出力するビットマップのピクセルフォーマット。<code>&quot;ycbcr422&quot;</code>,<code>&quot;rgb565&quot;</code>,<code>&quot;argb8888&quot;</code>のいずれか。</li>
+<li><code>alpha</code> {number} ピクセルフォーマットが<code>&quot;argb8888&quot;</code>のときの透過度。<code>0</code>~<code>255</code>の値。(省略時: <code>255</code>)</li>
+</ul>
+</li>
+<li>戻り値: {Object} デコードされたビットマップ画像<ul>
+<li><code>width</code> {number} 画像の幅(ピクセル数)。</li>
+<li><code>height</code> {number} 画像の高さ(ピクセル数)。</li>
+<li><code>format</code> {string} 画像のピクセルフォーマット。<code>&quot;ycbcr422&quot;</code>,<code>&quot;rgb565&quot;</code>,<code>&quot;argb8888&quot;</code>のいずれか。</li>
+<li><code>bitmap</code> {AlignedBuffer} 画素データ。32バイトのアライメントです。</li>
+</ul>
+</li>
+</ul>
+<p><code>jpeg.decode()</code>の同期版です。処理は同期で行われ、処理が完了するとビットマップ画像を格納したオブジェクトを返却します。失敗すると例外をスローします。</p>
+<h4 id="-">使用例</h4>
+<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> AlignedBuffer = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aligned_buffer'</span>).AlignedBuffer;
+<span class="hljs-keyword">var</span> jpeg = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jpeg'</span>);
+<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
+<span class="hljs-keyword">var</span> config = {
+  <span class="hljs-attr">width</span>: <span class="hljs-number">480</span>,
+  <span class="hljs-attr">height</span>: <span class="hljs-number">272</span>,
+  <span class="hljs-attr">format</span>: <span class="hljs-string">'argb8888'</span>,
+  <span class="hljs-attr">alpha</span>: <span class="hljs-number">0xFF</span>
+};
+<span class="hljs-keyword">try</span> {
+  <span class="hljs-keyword">var</span> jpegData = fs.readFileSync(<span class="hljs-string">'/sd/input.jpg'</span>);
+  <span class="hljs-keyword">var</span> buf = <span class="hljs-keyword">new</span> AlignedBuffer(jpegData, <span class="hljs-number">32</span>);
+  <span class="hljs-keyword">var</span> image = jpeg.decodeSync(buf, config);
+  <span class="hljs-comment">/* 成功... */</span>
+} <span class="hljs-keyword">catch</span> (err) {
+  <span class="hljs-built_in">console</span>.log(err);
+}
+</code></pre>
+</body></html>
\ No newline at end of file