「ソフトウェアー・エンジニアリング」カテゴリーアーカイブ

ソフトウェアー関係の話題など・・

最近は、github にプッシュしてます~

RL78/G13にVS1063をつないで音楽ファイル再生

PWMでの簡易再生は、それなりに良い音だったが、やはり不満が残る。

昔から、音楽プレイヤーを自作してみたいと思っていたが、なかなか機会が無かった。
車やバイクで音楽聴いたり、持ち歩けるタイプなど。
※売ってるものは、不満があり、買う気にならない(以前に色々買ったけど、結局、
不便なので、使わなくなった)

RL78/G13は、そのようなガジェットに丁度良く、昔にRXマイコンで実験した
VS1063を接続して、音を鳴らしてみた。

「積みIC」とゆーのが自宅に沢山あるwww、買ったけど、まだ実験もしていないも
ので、VS1001やVS1011もあった。
VS1001は古くて、制御ラインが、余分に必要みたいなので、肥やしになる事が決
定・・、VS1011は、LQFP48はキープしてあったけど、変換基板が無い。
確か、VS1011のSOP版もあったハズとかなり探したが、結局見つからない・・
仕方なく、RXマイコンで実験したVS1063を外して、今度もモジュールにした。
IMG_0816s
※最近、変換基板の表側のピンにバイパスコンデンサを付ける小技を覚えたww
※SOP版の方が配線が少なく、実験しやすい、LQFP版は、電源など沢山結線しな
いと動かないので、使いたくなかったが、SOPが見つからないので仕方なくモジュー
ルに組んだ。

VS1053は、I/O電源3.3V、コア電源1.8V、アナログ電源3.3Vが必
要で、1.8Vは、3.3Vからレギュレーターで作っている。
アナログ電源は、とりあえず、デジタル電源と共有している。(フェライトビーズを入
れてある)
本来、クリスタルは12.288MHzを使うが、手元に12MHzしか無かったので、
とりあえず、これを使う、内部設定で、補正を行なう事が出来る。

モジュールにした事で、マイコンとは、10Pのフラットケーブルで接続する、SPI
のクロックが高めなので、できるだけ短くする。

そして、ようやく接続が出来て、実験コードを書いて動かしてみる・・・
動かない・・・
RXマイコンで鳴らした事があるので、そうそう間違う事も無いと思い、色々確認する
ものの、問題無い・・・
オシロスコープで信号を確認していると、制御信号が出ていない?
結局良く調べたら、RL78/G13では、P62、P63は、出力にした場合、オー
プンドレイン専用ポート
で、ある事が判明した。
仕方なく、他のポートに繋ぎなおしてみたら、普通に鳴った・・・
※最近、くだらない理由で、「はまる」事が多いなぁー

IMG_0819s

VS1063との接続:

    ・P73/SO01 (26) ---> VS1063:SI     (29)
    ・P74/SI01 (25) ---> VS1063:SO     (30)
    ・P75/SCK01(24) ---> VS1063:SCLK   (28)
    ・P52      (35) ---> VS1063:/xCS   (23)
    ・P53      (36) ---> VS1063:/xDCS  (13) 
    ・P54      (37) ---> VS1063:/DREQ  ( 8)
    ・/RESET   ( 6) ---> VS1063:/xRESET( 3)

-----
プログラムは、鳴らすだけの機能しか実装していない。
VS1063は、色々なフォーマットに対応しているが、タグ情報をスキップするとか、
色々な細かいケアをしないと実用的には使えないので、プログラムはこれから充実させる
として、ここらで、スタート・ボードの設計なども進めておかないと・・

プロジェクト・ソース・コード

RL78/G13でSDカードの速度比較

SDC_sample プロジェクトで、単純な空読みと書き込みで、どのくらいの
速度が出ているのか調べた。

メーカーや種類によってかなり違いがある。
※読み込むサイズは512バイト、これ以上大きい場合は、RL78の
RAMサイズから考えてあまり実用的では無いと思える。

WAVプレイヤーでは、読み込みで200キロバイト以下のカードでは、
16ビット、44.1KHz、ステレオファイルの再生は、ほぼ無理の
よう。
※300キロバイト近くないと十分とは言えない。
※1GB、8GBのカードは、十分使えた。

256MBのSDカード(Panasonic)

SD Write test...
Write frame: 739
Write: 85134 Bytes/Sec
Write: 83 KBytes/Sec
SD Read test...
Read frame: 186
Read: 338250 Bytes/Sec
Read: 330 KBytes/Sec

1GBのSDカード(Transcend 60x)

SD Write test...
Write frame: 214
Write: 293993 Bytes/Sec
Write: 287 KBytes/Sec
SD Read test...
Read frame: 225
Read: 279620 Bytes/Sec
Read: 273 KBytes/Sec

2GBのSDカード(Transcend class ?)

SD Write test...
Write frame: 954
Write: 65948 Bytes/Sec
Write: 64 KBytes/Sec
SD Read test...
Read frame: 309
Read: 203606 Bytes/Sec
Read: 198 KBytes/Sec

8GBのSDカード(Transcend class 6)

SD Write test...
Write frame: 541
Write: 116293 Bytes/Sec
Write: 113 KBytes/Sec
SD Read test...
Read frame: 180
Read: 349525 Bytes/Sec
Read: 341 KBytes/Sec

32GBのSDカード(FlashAir)

SD Write test...
Write frame: 583
Write: 107915 Bytes/Sec
Write: 105 KBytes/Sec
SD Read test...
Read frame: 347
Read: 181309 Bytes/Sec
Read: 177 KBytes/Sec

32GBのSDカード(ノーブランド class 10)

SD Write test...
Write frame: 417
Write: 150874 Bytes/Sec
Write: 147 KBytes/Sec
SD Read test...
Read frame: 212
Read: 296766 Bytes/Sec
Read: 289 KBytes/Sec

IMG_0815s

RL78/G13でWAVファイルのPWM再生

SDカードとPWMが出来たら、定番のWAV再生を行わない理由は無い。

また、SDカードアクセスのパフォーマンスを測る指針ともなる。

以前にR8Cで、トライした時は、色々な問題にぶつかって、実用性が薄い事
から、あまり深く掘り下げなかった。
・R8Cでは、UARTとSPIが共有している為、どちらか片方しか、利用
する事が出来ず、不満が残る。
※SPIをハードで行い、UARTをソフト処理する事も考えられるが、受信
動作は困難と思われる。
・R8CのPWMでは、コンペアレジスターがバッファされていない為、書き
込んだタイミングと、前の値との組み合わせにより、グリッチが発生する、そ
の為、「プツプツ」とノイズが気になる。

結局、SPIをソフトで処理して、実装してみたが、11.025KHz、8
ビット、ステレオが限界だった・・
これは、かなり微妙な結果だと言うしかない、UARTを諦めて、SPIをハ
ードで扱う事も考えたが、プツプツと発生するノイズ、PWMの仕様上の問題
をナチュラルに解決する方法を思いつけなかったので、中途半端だったが諦め
た。

RL78では、その全てを改善できるであろう事が判っていた、8ビットの
PWM変調に起因する音質以外は、ほぼ満足なものとなると思われる。

早速実装して、音を出してみたら、思った通りの結果だった、PWMのレジス
タ書き換えに起因するノイズも聞こえない、(RL78では、バッファされて
いる)48KHz、16ビット、ステレオのファイルも、難なく再生出来た。
※16ビットの下位8ビットは捨てている。
※つまり、他の処理も考え合わせると、ゆうに200キロバイト毎秒以上の
読み込み速度が出ていると思われる。

※SDカードの速度は次のブログを参照

-----
PWM周期は、8ビットの分解能が必要なので、カウンタのクロックを
16MHzとして、256で割った、62.5KHzとした。
これで、一応48KHzのサンプリング・レートに対応できる。

多少難しい問題として、PWMのサンプルレート、62.5KHzと、ファイル
のサンプリングをどのようにマッチさせるか、この微妙な周期の違いを、簡潔に
解決する方法を考慮する必要がある。
62.5KHz毎に起動する割り込みで、波形値をバッファから取り出して、
PWMのコンペアレジスタに設定している。
バッファのポインター移動は、サンプリング周期/62.5KHzの分数で行い、
小数点以下の誤差が全く出ないように工夫した。
※簡単な整数計算だけで行なえるので、シンプル。

    device::TAU01::TDRL = buff_[pos_ + l_ofs_] + wofs_;
    device::TAU02::TDRL = buff_[pos_ + r_ofs_] + wofs_;
    inc_ += rate_;
    if(inc_ >= 6250) {
        inc_ -= 6250;
        pos_ += skip_;
        pos_ &= 1024 - 1;
    }

分数計算で、分子が、分母(6250)を超えたら、テーブルのポインターを進
める、また、分子から、6250を引く。
・6250は、62.5KHzの1/10で、「rate_」は、波形ファイルのサン
プリング周波数を1/10にしてある。
※つまり、48KHzなら4800、44.1KHzなら4410、
22.05KHzなら2205となる。
・1/10にするのは、計算レンジを16ビット以内に納まるようにする為の工夫。
・「skip_」は、8ビットモノラルなら「1」、8ビットステレオなら「2」、
16ビットモノラルは「2」、16ビットステレオなら「4」にする。
・8ビットファイルの場合、無音は「0x80」だが、16ビットファイルでは、
無音は「0x0000」となるので「wofs_」で調整する。
・WAVファイルは、リトルエンディアンなので、「l_ofs_、r_ofs_」で、掴む
位置を微調整する。
・バッファサイズは、SDカードの読み込みでは、512バイトの倍数が効率が
良いようなので、ピンポンバッファにする為、倍の1Kバイトとした。

-----
PWM出力は、適当なローパスフィルターを通す事で、アナログ出力を得られる。
今回は、2Kオームと、0.01uFのネットワークとした。
少し贅沢ではあるけども、フルスイング・オペアンプを使って、バッファーを組ん
でみたが、オペアンプを使わず、大きめのカップリングコンデンサを入れただけの
回路でも、問題無いだろう。
※RL78がリセット状態や、停止中は、出力に直流が乗るので注意。
IMG_0814s

・ターミナルからのコマンドで WAV ファイルを再生する。
・「dir」ディレクトリーリスト
・「play file-name」再生
・「play *」カード内の WAV 形式ファイルを全て再生
・再生中、「<」曲の先頭に戻る、「>」次の曲
・再生中「SPACE」を押す毎に、一時停止、再開
rl78_wav_play

※この写真は、オペアンプを使っていないRCフィルター
IMG_0813s

RL78/G13 WAV file player サンプル

参考回路とKiCADのプロジェクト:
WAV_Player KiCAD Project

WAV_Player_Sample

RL78/G13でPWM出力を出してみる

インターバル・タイマーの次は、PWM出力。

少し悩んだのは、少し構成が複雑になるので、どのようなAPIにするのが良いのか
・・・

RL78では、PWMを使う場合、マスターと、スレーブの2つのチャネルを組み合
わせる必要がある点が、少し厄介な為で、結局、PWMの設定関数は、テンプレート
関数とした、テンプレートの引数は、マスターチャネルのTAUを使う。

typedef device::tau_io<device::TAU00> master;
master master_;
device::tau_io pwm1_;
device::tau_io pwm2_;

bool init_pwm_()
{
    uint8_t intr_level = 0;
    if(!master_.start_interval(100000, intr_level)) {
        return false;
    }
    if(!pwm1_.start_pwm<master::tau_type>(0, intr_level)) {
        return false;
		}
    if(!pwm2_.start_pwm<master::tau_type>(0, intr_level)) {
        return false;
    }
    return true;
}

このサンプルでは、TAU01、TAU02をそれぞれPWM出力としている。
PWMの周期は、TAU0を使い、サンプルでは、100KHzとしている。
「TAU01」は、TO01(P16)40番ピン
「TAU02」は、TO02(P17)39番ピン

    auto val = master_.get_value();  // マスターチャネルのカウント最大値
    pwm1_.set_value(val / 4);  // PWM Duty 25%
    pwm2_.set_value(val * 3 / 4);  // PWM Duty 75%

サンプルでは、それぞれ、25%と75%のディーティーとしている。

IMG_0812s

PWMサンプル

RL78/G13でインターバル・タイマーを使ってみる

ようやく、ここまで来た感がある。

タイマーの機能は、複雑なので、機能を理解して、クラスを作るのが難しく、楽しい。

まず、面倒な、データ・レジスタのマッピング・・
これは、SAU(シリアルアレイもそうだったけど)ではまったんだけど、SDR
(シリアル・データ・レジスタ)でも実アドレスが、不規則に並んでいる・・
SAUは8チャネルが2ユニットあるのだけど、SDRだけ、不規則な実アドレスと
なっている。(何でこうなるのか理由は不明だが、仕様なので仕方無い・・)

タイマ・アレイはほぼ同じ構成であるので、テンプレートでクラスを作り、テンプレ
ートパラメーターとして、アドレスのオフセットを加える構成にしてある、しかし、
それだと、不規則なアドレスの変化に対応出来ない為、SDRだけ、別途アドレスを
与えるようにして対応した。

// UOFS: ユニット・オフセット
// CHOFS: チャネル・オフセット
// DRADR: SDRアドレス
template <uint32_t UOFS, uint32_t CHOFS, uint32_t DRADR>
struct tau_t {
.
.
.
};
typedef tau_t<0x00, 0x00, 0xFFF18> TAU00;
typedef tau_t<0x00, 0x02, 0xFFF1A> TAU01;
typedef tau_t<0x00, 0x04, 0xFFF64> TAU02;
typedef tau_t<0x00, 0x06, 0xFFF66> TAU03;
typedef tau_t<0x00, 0x08, 0xFFF68> TAU04;
typedef tau_t<0x00, 0x0A, 0xFFF6A> TAU05;
typedef tau_t<0x00, 0x0C, 0xFFF6C> TAU06;
typedef tau_t<0x00, 0x0E, 0xFFF6E> TAU07;

C++ で作ると、このような、変化に柔軟に対応できて、便利だ、そしてわかり易い。

RL78/G13 tau.hpp

-----
日本製マイコンのタイマー系は、やはり良く考えられて作られている。

まずは、基本のインターバル・タイマーを使って、矩形波を出力する。
インターバルタイマーの矩形波は、タイミングでトグルするので、設定の半分の周期
となる。

※サンプルでは、TO01端子(ポート1のビット6)40番ピンから、5KHz、
デューティー50%の信号を出力する。

TAUを使ったインターバルタイマー出力

今後、機能追加の過程で、仕様は変わるものと思う。

RL78/G13にSDカードを繋いでみる

液晶表示で、少し手間取ったけど、ようやく本命のSDカードアクセス。
でも、これは、ChaN さんのソフトウェアーに、おんぶにだっこで、自分の実装する
部分は少ない上に、非常に良く出来たソフトウェアーなので、移植も楽だし、トラブ
ルも少ない。
FatFs 汎用FATファイルシステム モジュール
※今回は、「ff12a」を使った。
RL78/G13は、リソースもそこそこ沢山あるので、最小構成版を使う必要は無
い(pfatfs)ものの、RO領域が限られるので、UTF-8を使う事が出来ない。
この対応は、少し考えたい。
※外部 EEPROM などに、コードページの変換テーブルなどを置く事が考えられる。
※又は、通常のコード領域に配置して、32ビットポインターでアクセスするなど。

以前R8Cで実験した時は、基板にSDカードソケットを直付けしたのだけど、それ
だと、他に流用出来なくなるので、今回は、モジュールにしてみた。
IMG_0809s
IMG_0810s
ヒロセ製のSDソケットは、品質が高く(創りが良い)、これ以外は使いたくないく
らいの出来の良さ。
一応、全ての端子を出してある、又、埃等が入らないように、テープを張ってある。
電源オン、オフのP-ChanelFET、電源LEDなども含めておいた。
電源をオンにした時、かなり大きな電流が流れる、その時の急激な電圧降下を和らげる
目的でフェライトビーズ(470オーム、1000mA)を入れてある。

また、カードのチップセレクト端子や、データアウト端子は、電源OFF時に、「H」
にしていると、そこから、電流が内部に還流するので、電源OFF時は、「0」にする
必要がある。

ChaN さんのプロジェクトを自分のシステムに移植する方法は、簡単で、サンプルにある
「generic」サンプルの「sdmm.c」を参考にする事だと思う、このソースは、クロック信
号、シリアル/パラレル変換を全てソフトで行っているもので、わかり易く、必要最低限
のコードを追加すればよい。
また、全体の機能設定を「ffconf.h」で行ない、「ff.c」をプロジェクトに加える。

IMG_0811s

SDカード・サンプル
このサンプルでは、起動すると、SDカードのルートディレクトリーをリストする。
このサンプルでは、カードをソケットに入れると、マウントを行い、抜くとアンマウント
を行なう。
又、コンソールから、「dir」コマンドを入力する事で、ディレクトリーのリストが行える。

シリアル通信では、SAU0(SO00、SI00、SCK00)を使っている。
それ以外の制御と、カード検出などは以下のポートを利用している。

    typedef device::PORT<device::port_no::P0,  device::bitpos::B0> card_select;	///< カード選択信号
    typedef device::PORT<device::port_no::P0,  device::bitpos::B1> card_power;	///< カード電源制御
    typedef device::PORT<device::port_no::P14, device::bitpos::B6> card_detect;	///< カード検出

※「main.cpp」参照

参考回路と KiCAD のプロジェクトなど:
KiCAD プロジェクト

SDC_sample

RL78/G13でSPI通信、モノクロLCDを表示

I2Cが、何とか動作するようになったので、次はSPI通信。
RL78/G13は、SAU(シリアル・アレイ・ユニット)で、SPI準拠の通信も
扱える(CSIと呼ぶらしい)、これなら、SDカードアクセスを行なっても、アクセ
ス速度が足りないとかは無さそうだし、DMA転送も使えるはず。
※以前にR8CでSPI通信を行なった時は、ソフトウェアーのみで実装した、その時
は、SDカードのアクセスでは、11.05KHzの波形ファイルの再生が限界だった。
一応R8CにもシリアルユニットをSPI通信で使うモードが用意されてはいるものの、
そうすると、シリアル通信が出来なくなってしまう。

RL78/G13では、シリアル・アレイは6チャネルもあり、潤沢に使える。

ただ、CSIを実装していて気がついたが、最高速度は16MHzである上に、それは、
CSI0だけで、他は8MHzが上限のようだ・・
これは、かなり痛い・・
現在UARTには、チャネル0、1を宛てているので、これを、別に宛てて、最高速度
が出せるチャネルは、CSI用にする必要があるようだ・・

それでは、早速、CSI用のマネージャーを作成開始。
UARTと違うのは、UARTでは、基本、送信と受信は全二重(別チャネル)で動く
ので、SAUは2チャンネル必要だけど、CSIでは、1チャネルで、出力、入力を兼
ねる点。

簡単なテストプログラムを作成して、出力をオシロスコープで確認してみたもの、パル
スが出力されない・・・

随分時間をかけて、調べた結果、SAUのデータレジスターの実アドレスだけが、イレ
ギュラーな飛び方をしている事を発見、それを修正したら、SO10から、パルスが出
るようになった。

FFF10H, FFF11H(SDR00), FFF12H, FFF13H(SDR01)
FFF44H, FFF45H(SDR02), FFF46H, FFF47H(SDR03)
FFF48H, FFF49H(SDR10), FFF4AH, FFF4BH(SDR11)
FFF14H, FFF15H(SDR12), FFF16H, FFF17H(SDR13)

※「SO10」は、「SDR02」を使う。

まず、SDカードの前に、もっとも簡単なLCDを繋いでみた。
大型STN液晶モジュール(128x64/SPI) [LCD12864B11-2P]
RAMが潤沢にあるので、128X64のグラフィックスも余裕で扱える~
ビットマップのLCDを高速に、そして柔軟に扱うには、どうしてもフレームバッファ
が不可欠で、表示サイズと同等のメモリーが必要となる。
この場合、1Kバイトの領域が必要。
通常、アプリケーションは、フレームバッファを全クリアして、オブジェクトをメモリ
ー上に描画する、そして、最後の描画が終わったら、全ての内容を、LCDに送る。
こうする事で、柔軟な描画が出来る。
これが、俗に言う「フレームバッファ方式」と呼ぶもので、他の考え方として、書き換
えが起こったら、その領域だけを選択的に書き換える方法があるが、液晶モジュールと
のコマンドのやりとりが複雑になり、書き換える領域が大きいほど、描画時間が多くか
かってしまう、また、書き換えるタイミングも個別に管理しなくてはならない。
フレームバッファ方式の場合、1秒に60回ほどの書き換えが望ましいが、STNの液
晶は、応答が速く無いので、秒間15枚も書き換えれば、十分かもしれない。
この方式は、昔からゲーム機で広く使われている方式。

能書きはこのくらいで~

-----
先日、Aitendoで購入したLCDは、コントローラーは、「ST7565R」と
あるので、ネットを探して、「ST7565」のドライバーを入手した。
以前にR8Cでも「ST7567」の液晶を扱ったので、その時に書いたドライバーは
あるが、別のソースを精査して、もう一度ドライバーを見直してみた。
※少し、動作が怪しい部分があった為もある。

ソフトを実装して、動かしてみたが、ウンともスンとも動かない・・
SCI関係のバグなのかもと思い、クロックとデータの関係など、色々確認してみたが、
問題無い、悩んだ末、組み立てる前から、基板のコネクターが気になっていたので、良
く調べてみると・・・
何と、ケーブルを差し込む上下が逆になっている・・・
ホームページの写真ではストレートに接続しているが、これでは、機能しない、180
度返さないと接触しない。
IMG_0807s
IMG_0808s

とりあえず、動作はしたのだが、非常に後味が悪い・・・
※メールで交換、返品を申し出たのだが、どうなるやら・・

RL78/G13でI2Cを使ってみる

最近アマゾンで、Arduino向けデバイスが格安で入手できる、中華製で、品質は
それなりではあるけれども、値段が恐ろしく安い。(送料も大抵無料)
評価欄で、低評価をしてる人がいて笑ってしまうのだが、こんだけ安くて、何が不満な
のだろうか?
部品を正規ルートで買って組み立てたら10倍以上の値段になるだろうか・・
「当り」、「はずれ」は当然として、不満なら正規品を買えば良いだけの事と思うのだ
が・・
※スイッチサイエンスや、ストロベリーリナックスで、同じような「製品」は入手でき
る、その場合のコストを考えてほしいと思う。

-----
さて、シリアル入出力は、割り込みにも対応できて、機能的にはとりあえず十分なので
何か外にデバイスを接続したくなる。
RL78/G13には、SAU(シリアル・アレイ・ユニット)を簡易I2Cとして使
う機能があるが、他に、IICA(I2Cアレイ)が1チャネルあり、I2Cの仕様を
全て満足する事が出来るので、当然ながら、こちらを使う事になる。

ハードウェアーマニュアルを読んでも、イマイチ使い方がピンとこなかったが、以前に
R8Cで、I2Cをソフトウェアーだけで実現した経験があったので、それが役立った、
出来上がってみると、R8Cで実装した構成とほぼ同じようになった。
新規のデバイスを使うのは、困難が伴う、I2Cは動作が複雑なのでなおさらだ。
ハードウェアー・マニュアルの不備などに悩まされ、ルネサスさんのサンプルコードも
参考にして、ようやく動作した。
まだ、ポーリング動作なので、遅いI2Cは、割り込みにする必要があるのだけど。
※R8CのソフトウェアーI2Cもフル機能がある。

構成が複雑化してくると、バイナリーが肥大化してきた、これを解消する為、このプロ
ジェクトから、最適化オプション「-O2」を「-Os」とした。
これは、「-O2」から、バイナリサイズが大きくなる可能性のある最適化オプションを取
り除いたもので、サイズはかなり縮小する。
※おおよそ1/4になった。

使ったデバイスは、DS3231で、RTCだ、このモジュールは中華製で、危険なほど
安い!(確か220円とかだった)
このRTCは、OSCの発振周波数が非常に正確なのが特徴で、普通にチップだけ買って
も500円はするが、このモジュールは、バッテリーバックアップ、それにEEPROM
まで付いている。

IMG_0804s

DS3231サンプル・プロジェクト

RL78/G13のスタートアップルーチン修正

const 領域の問題が解決したと思って、コンパイラに含む問題は解決されたと
思っていたのだが、何だか、動作が怪しい・・・

少し調べると、クラスの初期化リストが正しく動いていないように感じた。

xxxx.lst を見ながら、xxxx.mot ファイルのバイナリーを色々調査すると、明
らかに呼ばれていない関数がある事が判った。

00004c96 <__GLOBAL__sub_I__Z5wait_v>:

このアドレス「0x00004c96」は、どうやら、「.ctor」に積まれているようだ。

今まで、スタティックに定義したクラスのコンストラクターは、

extern void rl78_run_preinit_array(void);
extern void rl78_run_init_array(void);
extern void rl78_run_fini_array(void);

の3つを走らせれば良いのだと思っていたが、どうやら、「ctor」に積まれた
アドレスもコールしておく必要があるようだ・・

そこで、リンカースクリプトに「ctor」、「dtor」リストのシンボルを追加して、
「start.s」に関数を呼ぶエントリーを追加、「init.c」から呼ぶようにしてみ
た。
※どの順番で呼ぶのか不明なので、ctor を最初に呼ぶようにした。
※ctor、dtor のエントリーアドレスを得る方法が判らないので、シンボル追加。
この「無理やり」な解決方法が合っているか不明ではあるけど・・・

とりあえず、初期化が正しく行われ、正常に動作しているようだ。

まだまだ、スタートアップの方法に問題を含んでいるのかもしれない・・・

ここは、時間が出来たら、もう少し厳密な調査をしたい。

RL78/G13でインターバルタイマーを使ってみる。

RL78も、UARTが動作し始めた事で、佳境に入った感が出て来た。

とりあえず、現在使ってみた感想を述べてみる~
・バイナリーは、R8Cより少なくなる感じではあるけど、基本内部は8ビット構成な
ので、16ビットや32ビットを扱うと、肥大化は免れない。
・ミラー領域のおかげで、64K領域を超えた場合も、ある程度普通に扱う事が出来る。
・32MHzで動作するので、速度面でもかなり有利に感じる。
・RL78/G13は、コアは「S-2」なので、掛け算や割り算命令は無いものの、
外部に「乗除積和算器」があり、コンパイラオプション「-mmul=g13」で、コンパイラ
はこのリソースを使う為、それなりの速度で動作する。
※但し、割り込みルーチン内で使う場合には注意を要すると思われる。
・トータルメモリーのサイズから考えると、コストパフォーマンスに優れている。
・消費電力が非常に小さい。

いつもは、LED点滅の後くらいに、インターバルタイマーを実装するけど、RL78
のインターバルタイマーは、1ユニットで、12ビットレンジ、低速で、シンプルすぎ
るので、イマイチ意欲が沸かなかったが、必要な機能ではあるので、粛々と実装した、
動いた。

ただ、残念なのは、カウンターの値を読み出す事が出来ないので、正確なタイマーを実
装したい場合などに使えない。

単に設定したインターバルを待つだけのものでしか無い。

-----

ついでなので、ソフトディレイも実装した。
RL78/G13では、32MHz動作なので、より細かい単位も可能だけど、とりあえ
ず良く使うだろう、1uS(1マイクロ秒)単位の関数にした、これは、R8Cと同じ仕
様。
最初、アセンブラは、覚えなくても良いとか言ってたけど、結局、なんだかんだで、覚え
る必要が出てきて、ソフトウェアーマニュアルを読む事になった・・・

void micro_second(uint16_t us)
{    
    while(us > 0) {
        --us;
    }
}

上のようなコードは、最適化(-O2)して、以下のように展開される

(2) decw    0xffef0
(1) movw    ax, 0xffef0
(1) cmpw    ax, #0
(1) skz
(3) br      !!4922 <.L629>

最適化されても、ワークメモリーが使われているが、マシンサイクルから考えると、なる
ほど、ペナルティーは意外と少ない。
RL78のような、アーキュムレーターが基本のCPUでは、レジスターだけに割り振る
コードを出すのは難しいのかもしれない・・
※()内がマシンサイクル

この結果を考慮して、全体で32クロックになるように「nop」命令を置く。

・次のコードで実験してみた。

    while(1) {
        utils::delay::micro_second(10);
        P4.B3 = !P4.B3();
    }

10uS毎にポートを変化させてみた。
IMG_0802s
大体合ってる~

インターバルタイマーソースコード