GR-SAKURA
GR-KURUMI
GR-COTTON
GR-CITRUS
GR-PEACH
GR-KAEDE
GR-ADZUKI
GR-LYCHEE
GR-ROSE
GR-MANGO(*)
SNShield
Web Compiler
IDE for GR
TOPPERS関連
女子美コラボ
その他
※プロデューサミーティング中
作り方使い方資料
イベント関連
作品記事
体験記事
ライブラリ
ツール
その他・過去ファイル
がじぇるね岡宮です。
RL78/G13のボードとしてGR-KURUMI、GR-COTTON、GR-ADZUKIの3つがありますが、これらのライブラリをマージしようと思います。
★3/13を目途にご要望や修正点などを締め切り、その後検証して3月末にWebコンパイラに反映、順次IDE for GRへ適用したいと思います。
■概要
ライブラリについて、これまで多くのご意見やご提案があり、それぞれを独立してライブラリアップデートを図っていましたが、マージすることでメンテナンス性の向上と、見やすさ・分かりやすさを向上するために、ファイル構成変更をArduinoや既存のGR-SAKURAと同様にしたいと思います。
・マージについて
__RL78_G13__ をRL78/G13のGRボード共通マクロとして定義。コンパイルオプションで指定。ちなみにArduinoでは__AVR_ATmega1280__という感じ。
ボードごとにGRKURUMI, GRADZUKIなどコンパイルオプションを付加することで、切り分けを行う。(テスト版ではまだ付加しておらず、GR-ADZUKIで動作確認してます)
・ファイル構成変更
・GR-SAKURAと同様に以下の構成に変更
Arduino\cores\
\libraries (階層変更なし)
\rl78\ (portableフォルダを廃止してrl78直下に変更)
・主な変更
・RLduino78_mcu_depend.hや、RLduino78_basic.cpp、RLduino78_timer.cなど、独自にArduinoライブラリが形成されていたものを以下のファイルに移植。
ただし、関数の中身変更は改善事項を除いて基本的に実施しません。比較的RL78ライブラリは安定しているためです。(microsの検証ですごい苦労したのがトラウマです)
\Arduino.h (標準ライブラリに広くインクルードされるヘッダ)
\pins_arduino.h (ボードごとのピンに関するヘッダ)
\wiring_private.h (wiring**や、W**などのArduino基本ライブラリから参照されるヘッダ)
\wiring.c (millis()やdelay())
\wiring_digital.c (digital系)
\wiring_analog.c (analog系)
\wiring_pulse.c (pulse系)
\wiring_shift.c (shift系)
\WMath.cpp (算数)
\WInterrupts.c (外部割込み)
\Tone.cpp (Tone関係)
\utilities.cpp (GRで独自のもの。例えば省電力やattachIntervalTimerとか)
\rl78\specific_instructions.h (Fujitaさんが作ってくれた高速化やお役立ち)
■その他
・標準以外のArduinoのライブラリでよく使われるdigitalPinToPortなどを実装
・RTOS用の記述は削除(動作検証できておらず、あまり使用した事例もみないため。)
・attachMicroIntervalTimer、MsTimer2の時間ずれ不具合は反映しました(Fujitaさんありがとうございます!)
・makeでarによるアーカイブ化してから、リンクするとなぜか不要なものがリンクされてしまうため、適用保留としてます。
■テストファイル
・makefile
※make用ですが、ActivePerlを組み込んでC:\Program Files (x86)\KPITにGNURL78v14.03-ELFをコピーし、コマンドプロンプトでbuild実行してもOKです。ちなみに.batを実行してもOKで、これがWebコンパイラのビルド実体でもあります。
・e2studio用
インポートしてビルドできます。
■ご意見、要望などまとめ
-mcpu=g13 -mmul=noneを指定
以下で分ける
#if __RL78__ /* 全ボード全RL78共通 */ #if GRKURUMI /* GR-KURUMI 固有 */ #elif GRCOTTON /* GR-COTTON 固有 */ #elif GRADZUKI /* GR-ADZUKI 固有 */ #endif #if __RL78_G13__ /* RL78/G13 固有 */ #elif __RL78_G14__ /* RL78/G14 固有 */ #elif __RL78_G10__ /* RL78/G10 固有 */ #endif #endif
MsTimer2は標準ではないので、librariesフォルダに入れる
GR-KURUMI, COTTON, ADZUKI のライブラリ V2.00 の web コンパイラが生成する makefile でターゲットが clean の箇所が
clean: $(OBJS) $(MAKEFILE) rm -f $(OBJFILES) rm -f ./gr_build/$(TARGET).x rm -f $(TARGET).bin rm -f ./gr_build/$(TARGET).mot rm -f ./gr_build/$(TARGET).map
となっていますが `clean:' の後のソースが不要です。
ソースに $(OBJS) があるために make clean した後に再度 make clean をすると $(OBJS) にある .o を一旦生成した後に削除するという動作となってしまいます。
> -fnocprop-registersオプションの件ですが、SDからのWAV再生の方です。
web コンパイラにて GR-KURUMI_Sketch_V2.00.zip をテンプレートとして新規作成したプロジェクトに GR-KURUMI_WAVP(SD)_V1.13 の wav_lib/ 以下と gr_sketch.cpp を追加/交換してビルドを行ったところ、リンクの箇所で
./wav_lib/Fatfs/option/cc932.o: In function `ff_convert': /wav_lib/Fatfs/option/cc932.c:3759: undefined reference to `_rl78_abs__' E:/GCC for Renesas RL78 4.9.2.201701-GNURL78-ELF/rl78-elf/rl78-elf/bin/rl78-elf-ld.exe: Warning: RL78_SYM reloc with an unknown symbol /wav_lib/Fatfs/option/cc932.c:3763: undefined reference to `_rl78_abs__' E:/GCC for Renesas RL78 4.9.2.201701-GNURL78-ELF/rl78-elf/rl78-elf/bin/rl78-elf-ld.exe: Warning: RL78_SYM reloc with an unknown symbol /wav_lib/Fatfs/option/cc932.c:3763: undefined reference to `_rl78_abs__' E:/GCC for Renesas RL78 4.9.2.201701-GNURL78-ELF/rl78-elf/rl78-elf/bin/rl78-elf-ld.exe: Warning: RL78_SYM reloc with an unknown symbol /wav_lib/Fatfs/option/cc932.c:3763: undefined reference to `_rl78_abs__' E:/GCC for Renesas RL78 4.9.2.201701-GNURL78-ELF/rl78-elf/rl78-elf/bin/rl78-elf-ld.exe: Warning: RL78_SYM reloc with an unknown symbol make: *** [rom] Error 1
とエラーとなってしまいビルドが成功しませんでした。
確認したところ、wav_lib/Fatfs/option/cc932.c の ff_convert() の中の変数 p に sjis2uni と uni2sjis を代入している箇所
WCHAR ff_convert ( /* Converted code, 0 means conversion error */ WCHAR chr, /* Character code to be converted */ UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ ) { const __far WCHAR *p; WCHAR c; int i, n, li, hi; if (chr <= 0x80) { /* ASCII */ c = chr; } else { #if !_TINY_TABLE if (dir) { /* OEMCP to unicode */ p = sjis2uni; hi = sizeof sjis2uni / 4 - 1; } else { /* Unicode to OEMCP */ p = uni2sjis; hi = sizeof uni2sjis / 4 - 1; }
が
movw ax, #%lo16(_uni2sjis) movw [sp+4], ax movw ax, #%hi16(_uni2sjis) br !!.L11 .LVL1: .L7: .loc 1 3760 0 movw ax, #%lo16(_sjis2uni) .LVL2: movw [sp+4], ax movw ax, #%hi16(_sjis2uni) .L11: movw [sp+6], ax
というコードにコンパイルされ、アセンブルは通るものゝ、_uni2sjis と _sjis2uni というシンボルは同ファイルで定義されているにも関わらずリンクで参照に失敗するという現象のようです。
アセンブラかリンカの不具合と思われます。現在確認中です。
GR-KURUMI_Sketch_V2.00 のリンカスクリプトを変更し、WAVP(SD) の差分を追加して GCC for Renesas 4.9.2.201701-GNURL78 Windows Toolchain (ELF) にてビルドと動作の確認を行いました。`-fno-cprop-registers' はあってもなくとも動作に違いは見られませんでした。
> 現状のWebコンパイラに搭載されているV2.00では上記の記載が.ldになくリンクが通るのですよね。。
web コンパイラで組み込まれるライブラリでは
WCHAR ff_convert ( /* Converted code, 0 means conversion error */ WCHAR chr, /* Character code to be converted */ UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ ) { const __far WCHAR *p; WCHAR c; int i, n, li, hi; if (chr <= 0x80) { /* ASCII */ c = chr; } else { #if !_TINY_TABLE if (dir) { /* OEMCP to unicode */ p = sjis2uni; hi = sizeof sjis2uni / 4 - 1; } else { /* Unicode to OEMCP */ // p = uni2sjis; hi = sizeof uni2sjis / 4 - 1; } li = 0; for (n = 16; n; n--) { i = li + (hi - li) / 2; // if (chr == p[i * 2]) break; if (chr > p[i * 2]) li = i; else hi = i; } c = n ? p[i * 2 + 1] : 0;
エラーとなる箇所がコメントアウトされており根本解決していません。
web コンパイラでもコメントアウト部分を元に戻すとリンクでエラーとなることが確認できます。リンカスクリプトの修正は必要でしょう。
> -fnocprop-registerに関わるWAVPライブラリの個所を修正したいと思いますが、ビット操作を行っている部分と思ってよかったでしょうか?
`-fnocprop-register' は既にレジスタに格納されている値に対して無駄なメモリアクセスを省く最適化 `-fcprop-register' を打ち消す指示です。`-O' `-O2' `-O3' `-Os' 等の最適化指示では標準で `-fcprop-register' を含んでおり、コンパイラに問題がなければ `-fnocprop-register' は敢えて指示する必要はないものです。以前 RL78 版 GCC でレジスタ破壊を行うコードを吐いていた時期があり、その際には `-fnocprop-register' を指示することで破壊されたレジスタの内容を再度メモリから読み出すことで動作をさせていました。
コンパイラに問題がなければソースの修正は必要ありません。リンカスクリプトに PROVIDE (__rl78_abs__ = 0); を追加するという話とは問題が別です。
fujitaさん、オプションの解説ありがとうございました。
オプションの指定する/しないで、アセンブルリストでレジスタアクセス部分の差分を見てみましたが、例えば音の乱れに影響しそうなwav_audio.cのPWMのデューティーを変更する部分などには差分が見られず、どの部分が悪いのかが分かりませんでした。ちょっと時間がかかりそうなため、GCCサポートにクエリを登録し、その回答を待って修正を検討しようと思います。
https://gcc-renesas.com/ja/my-support-requests/tickettrackingsystem/ticketdetail/121
ですので恐れ入りますが、それまでは-fno-cprop-registersを追加する方向とさせていただきます。
> 例えば音の乱れに影響しそうなwav_audio.cのPWMのデューティーを変更する部分などには差分が見られず、どの部分が悪いのかが分かりませんでした。
web コンパイラで GR-KURUM_Sketch_V2.01.zip を初期テンプレートとして新規プロジェクトを作成し、gr_kurumi_wavplay_SD_library をインポートし、下記のスケッチを gr_sketch.cpp としてビルドした kurumi_sketch.bin と、web コンパイラから先のプロジェクトをダウンロードし、makefile 中の `-fno-cprop-registers' を削除してローカルでビルドし作成した kurumi_sketch.bin とを GR-KURUMI で動作させてみましたが動作上の違いは分かりませんでした。「音の乱れ」とはどのようなことを指していますか?
/* wavp_play.c - wavp library Copyright (c) 2015 Mitsuhiro Matsuura. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /*This template is based on GR-KURUMI Sketch Template Version: V1.13*/ #include <Arduino.h> #include <Wavp.h> #define LED_RED 22 #define LED_GREEN 23 #define LED_BLUE 24 #define LED_ON 0 #define LED_OFF 1 #define SW_PAUSE 7 #define SW_SKIP 8 #define SW_ON 0 #define SW_OFF 1 Wavp wavp(44100); static void cyclic_handler(unsigned long u32ms); void setup() { Serial.begin(9600); Serial.println("kurumi wav player from SD"); pinMode(LED_GREEN, OUTPUT); digitalWrite(LED_GREEN, LED_OFF); pinMode(LED_BLUE, OUTPUT); digitalWrite(LED_BLUE, LED_OFF); pinMode(SW_PAUSE, INPUT_PULLUP); pinMode(SW_SKIP, INPUT_PULLUP); // 周期処理を起動 attachIntervalTimerHandler(cyclic_handler); } #if 1 // ファイル名を決め打ちするサンプル void loop() { if(wavp.begin()) { // 再生 wavp.play("1.wav"); wavp.play("2.wav"); wavp.play("3.wav"); wavp.play("4.wav"); wavp.play("5.wav"); wavp.play("6.wav"); wavp.play("7.wav"); wavp.play("8.wav"); wavp.play("9.wav"); wavp.play("11.wav"); wavp.play("12.wav"); wavp.play("13.wav"); wavp.play("14.wav"); wavp.play("15.wav"); wavp.play("16.wav"); wavp.play("17.wav"); } else { Serial.println("no card!"); digitalWrite(LED_GREEN, LED_ON); delay(1000); digitalWrite(LED_GREEN, LED_OFF); delay(1000); } } #else // カードの.wavファイルを見つけた順に再生するサンプル FRESULT scan_files(char* path) { FRESULT res; FILINFO fno; DIR dir; int i; char *fn; /* 非Unicode構成を想定 */ static char lfn[_MAX_LFN + 1]; fno.lfname = lfn; fno.lfsize = sizeof lfn; // ディレクトリを開く res = f_opendir(&dir, path); if(res == FR_OK) { i = strlen(path); for(;;) { // ディレクトリ項目を1個読み出す res = f_readdir(&dir, &fno); if(res != FR_OK || fno.fname[0] == 0) { // エラーまたは項目無しのときは抜ける break; } if(fno.fname[0] == '.') { // ドットエントリは無視 continue; } fn = *fno.lfname ? fno.lfname : fno.fname; if(fno.fattrib & AM_DIR) { // ディレクトリ sprintf(&path[i], "\\%s", fn); res = scan_files(path); path[i] = '\0'; } else { // ファイル // パス名とファイル名を結合 char path_and_name[256]; sprintf(path_and_name, "%s\\%s", path, fn); // 文字コードをUTF-8に変換 // ファイル名に多バイト文字が無い場合は不要 // シリアル出力がシフトJISの場合は不要 char buf[256]; sjis_to_utf8(buf, path_and_name); Serial.println(buf); if((NULL != strstr(fn, "wav")) || (NULL != strstr(fn, "WAV"))) { // 再生(ファイル名の多バイト文字はシフトJIS) Serial.write(wavp.play(path_and_name)); } } } f_closedir(&dir); } return res; } void loop() { char path[1024] = ""; if(wavp.begin()) { // .wavファイルを探して再生 scan_files(path); } else { Serial.println("no card!"); digitalWrite(LED_GREEN, LED_ON); delay(1000); digitalWrite(LED_GREEN, LED_OFF); delay(1000); } } #endif // 一時停止,スキップ機能のサンプル static void sw_timerproc(void) { static int s_pause = 0, t_pause = 0; switch(s_pause) { case 0: if(SW_ON == digitalRead(SW_PAUSE)) { if(++t_pause > 100) { wavp.pause(1); s_pause = 1; } } else { digitalWrite(LED_BLUE, LED_ON); t_pause = 0; } break; case 1: if(SW_OFF == digitalRead(SW_PAUSE)) { s_pause = 2; } t_pause = 0; break; case 2: if(SW_ON == digitalRead(SW_PAUSE)) { if(++t_pause > 100) { wavp.pause(0); s_pause = 3; } } else { digitalWrite(LED_BLUE, LED_OFF); t_pause = 0; } break; default: if(SW_OFF == digitalRead(SW_PAUSE)) { s_pause = 0; } t_pause = 0; break; } static int s_skip = 0, t_skip = 0; switch(s_skip) { case 0: if(SW_ON == digitalRead(SW_SKIP)) { if(++t_skip > 100) { wavp.skip(); s_skip = 1; } } else { t_skip = 0; } break; default: if(SW_OFF == digitalRead(SW_SKIP)) { s_skip = 0; } t_skip = 0; break; } } static void cyclic_handler(unsigned long u32ms) { sw_timerproc(); // FatFs 周期処理 disk_timerproc(); }
web コンパイラにて GR-ADZUKI_Sketch_V2.01.zip をテンプレートとして新規プロジェクトを作成し、gr_adzuki_wavplay_SD Library を追加して、gr_sketch.cpp の内容を
/* wavp_play.c - wavp library Copyright (c) 2015 Mitsuhiro Matsuura. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /*This template is based on GR-KURUMI Sketch Template Version: V1.13*/ #include #include #define LED_RED 22 #define LED_GREEN 23 #define LED_BLUE 24 #define LED_ON 0 #define LED_OFF 1 #define SW_PAUSE 7 #define SW_SKIP 8 #define SW_ON 0 #define SW_OFF 1 Wavp wavp(44100); static void cyclic_handler(unsigned long u32ms); void setup() { Serial.begin(9600); Serial.println("kurumi wav player from SD"); pinMode(LED_GREEN, OUTPUT); digitalWrite(LED_GREEN, LED_OFF); pinMode(LED_BLUE, OUTPUT); digitalWrite(LED_BLUE, LED_OFF); pinMode(SW_PAUSE, INPUT_PULLUP); pinMode(SW_SKIP, INPUT_PULLUP); // 周期処理を起動 attachIntervalTimerHandler(cyclic_handler); } #if 1 // ファイル名を決め打ちするサンプル void loop() { if(wavp.begin()) { // 再生 wavp.play("1.wav"); wavp.play("2.wav"); wavp.play("3.wav"); wavp.play("4.wav"); wavp.play("5.wav"); wavp.play("6.wav"); wavp.play("7.wav"); wavp.play("8.wav"); wavp.play("9.wav"); wavp.play("11.wav"); wavp.play("12.wav"); wavp.play("13.wav"); wavp.play("14.wav"); wavp.play("15.wav"); wavp.play("16.wav"); wavp.play("17.wav"); } else { Serial.println("no card!"); digitalWrite(LED_GREEN, LED_ON); delay(1000); digitalWrite(LED_GREEN, LED_OFF); delay(1000); } } #else // カードの.wavファイルを見つけた順に再生するサンプル FRESULT scan_files(char* path) { FRESULT res; FILINFO fno; DIR dir; int i; char *fn; /* 非Unicode構成を想定 */ static char lfn[_MAX_LFN + 1]; fno.lfname = lfn; fno.lfsize = sizeof lfn; // ディレクトリを開く res = f_opendir(&dir, path); if(res == FR_OK) { i = strlen(path); for(;;) { // ディレクトリ項目を1個読み出す res = f_readdir(&dir, &fno); if(res != FR_OK || fno.fname[0] == 0) { // エラーまたは項目無しのときは抜ける break; } if(fno.fname[0] == '.') { // ドットエントリは無視 continue; } fn = *fno.lfname ? fno.lfname : fno.fname; if(fno.fattrib & AM_DIR) { // ディレクトリ sprintf(&path[i], "\\%s", fn); res = scan_files(path); path[i] = '\0'; } else { // ファイル // パス名とファイル名を結合 char path_and_name[256]; sprintf(path_and_name, "%s\\%s", path, fn); // 文字コードをUTF-8に変換 // ファイル名に多バイト文字が無い場合は不要 // シリアル出力がシフトJISの場合は不要 char buf[256]; sjis_to_utf8(buf, path_and_name); Serial.println(buf); if((NULL != strstr(fn, "wav")) || (NULL != strstr(fn, "WAV"))) { // 再生(ファイル名の多バイト文字はシフトJIS) Serial.write(wavp.play(path_and_name)); } } } f_closedir(&dir); } return res; } void loop() { char path[1024] = ""; if(wavp.begin()) { // .wavファイルを探して再生 scan_files(path); } else { Serial.println("no card!"); digitalWrite(LED_GREEN, LED_ON); delay(1000); digitalWrite(LED_GREEN, LED_OFF); delay(1000); } } #endif // 一時停止,スキップ機能のサンプル static void sw_timerproc(void) { static int s_pause = 0, t_pause = 0; switch(s_pause) { case 0: if(SW_ON == digitalRead(SW_PAUSE)) { if(++t_pause > 100) { wavp.pause(1); s_pause = 1; } } else { digitalWrite(LED_BLUE, LED_ON); t_pause = 0; } break; case 1: if(SW_OFF == digitalRead(SW_PAUSE)) { s_pause = 2; } t_pause = 0; break; case 2: if(SW_ON == digitalRead(SW_PAUSE)) { if(++t_pause > 100) { wavp.pause(0); s_pause = 3; } } else { digitalWrite(LED_BLUE, LED_OFF); t_pause = 0; } break; default: if(SW_OFF == digitalRead(SW_PAUSE)) { s_pause = 0; } t_pause = 0; break; } static int s_skip = 0, t_skip = 0; switch(s_skip) { case 0: if(SW_ON == digitalRead(SW_SKIP)) { if(++t_skip > 100) { wavp.skip(); s_skip = 1; } } else { t_skip = 0; } break; default: if(SW_OFF == digitalRead(SW_SKIP)) { s_skip = 0; } t_skip = 0; break; } } static void cyclic_handler(unsigned long u32ms) { sw_timerproc(); // FatFs 周期処理 disk_timerproc(); }
としてビルドして作成した adzuki_sketch.bin と、web コンパイラから上記のプロジェクトを PC にダウンロードし、makefile 中の `-fno-cprop-registers' を削除してローカルでビルドした adzuki_sketch.bin を、GR-ADZUKI は持っていないので代わりに GR-KURUMI に書き込んで確認してみましたが動画のような現象は見られませんでした。
基板の違いは置いておくとして、とりあえずあと違いとして .wav ファイルと gr_sketch.cpp の内容が不明なので動画のテストで使用されたそれを公開して下さい。それで再度確認を行います。