2016年8月30日火曜日

LME49600のヘッドホンアンプ 基板設計

aitendoでほとんどLME49600専用みたいなピッチ変換基板が出たようだ。今回使っているのよりコンパクトだし放熱用のパターンもあるしデカップリング・コンデンサも載せられそう。前からあったのかな(^q^??

回路図


基板図

部品並べ

ソケット上の部品あり

470uFの電源コンデンサとターミナル・ブロックの位置などが多少ずれている。入出力のコネクタには以前買いだめて全然使っていなかった圧着コネクタを使ってみる予定。


焦らず騒がずぼちぼち作っていきます。

ベースマシンのシーケンサー シーケンス再生中にLCDを表示する(SPIの調査)

SPIクロックの指定


シーケンサーのSPI信号を測定してみたところ、LCD表示に使っているSPI2のSCLが500kHz程度だったので、st7567用のライブラリにSPIのクロックを設定するメンバ関数を追加した。(ライブラリのデフォルトではSPIクロックは1MHzの指定)

st7567LCD:
https://developer.mbed.org/users/ryood/code/st7567LCD/#0e21d2f2155a

SPI1はシーケンス送信、SPI2はLCD表示に使用していてともにSPI::frequency()でクロックを16MHzを設定するようにした。

SPI1

ch2:SPI1のSCK

オシロのカーソルで測定するとクロックは約10.5Mhz。

SPI2

ch1:SPI2のSCK

SPI1とは横軸の縮尺が違い、オシロのカーソルで測定するとクロックは約5.25Mhz。

プログラムで同じ16MHzを指定してもSPI1とSPI2で実際のクロック数が異なっている。

SPI信号のタイミング


SPIのクロックを上げて、簡単な文字列を表示するようにすると、シーケンス再生中にLCDに描画することができた。

mbad repository:
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer/ (revision 29)

SPI信号

ch1:SPI2(LCD) ch2:SPI1(Sequence)

拡大

さらに拡大

ch2:SPI1(Sequence)はRtosTimerを使って1msごとにSPIコマンドを発行している。ch1:SPI2(LCD)はmain関数のメイン・ループ内でLCDへのSPIコマンドを発行している。"rtos.h"をインクルードしているのでmain関数は最初のスレッドで動作し、優先順位の高いRtosTimerの割込み時間外でSPI信号を出力しているようだ。

シーケンス打ち込み用のグリッド画面のSPI信号



ch1:SPI2(LCD)

拡大

SPIコマンドの発行時間は約3.3ms。これを1ms以下にすればシーケンス再生中にシーケンス打ち込みのLCD表示ができるかな??st7565ライブラリの中身を見ると1バイトずつSPI信号を送っているの様なので、RtosTimerの割込みは効きそうなものだけど。

簡単な文字列表示も一旦画面をclearしているので(?)、同じ3.3msかかっているようだが。

シーケンス打ち込み用のハードウェアを作りながらもう少し調べる予定。

メモ:


SPIのCSのタイミング調整にwait_us()を使っているのでもう一度タイミングを見計らってちゃんとする。

ついでに消費電流をテスタで測ってみた。Nucleoは今回はUSBで給電しているので除外。プラス側が約120mA、マイナス側は約7mAとかなり差がある。電池電源にするとプラス側の電池の減りが速そうだ。

2016年8月29日月曜日

リズムマシンをアルミの制御盤に載せる構想。

思い付きで作ったベースマシンのPOTのコントロール・パネルが意外と使いやすいので、以前作ったリズムマシンも同じように傾斜したアルミ・パネルに載せることを考えてみた。


厚紙で作って穴の位置がおかしかったし、重さでたわんでいるが、傾斜が付いているとなかなか使いやすそうだ。

100mm×300mmのアルミ板を加工する予定。タカチのTSシリーズという斜めのケースなら曲げ加工しなくても使えそうだが、いかんせん値段が高いし、ちょうどいいサイズがない。

曲げ加工はまたトンカチでたたいて整形するかな(^q^;

2016年8月27日土曜日

LME49600を使ったヘッドホンアンプ 部品並べ

回路図

基板図

基板図の下側を並べてみた。


LME49600の1.7mmピッチを2.54mmピッチに変換するためにaitendoの1.6mmピッチ変換基板を使う予定。

メモ:


デカップリング用のコンデンサも積セラではなくフィルムコンにしてみた。

タンタルを使うので電源系にポリスイッチを入れてみた。ブレッドボードでの実験途中に何回かタンタルを逆接続してしまったが、めちゃくちゃ発熱した。ほんとにタンタルは危うい(^q^;;;

サイズを考えても、タンタルより特性のいい積セラの方が4.7uFぐらいのデカップリング・コンデンサとしては向いているいんじゃないだろうか。

アナログ回路は1点アースがいいらしいのだが、正直めんどくさくてやってられない。WIMAのコンデンサを使って並べてみたが試作なのでできるだけaitendoの安いコンデンサで組む予定。

2016年8月26日金曜日

ベースマシンのUI シーケンス打ち込み

シーケンス打ち込みができるようにファームウェアをプログラミングした。Reasonというソフト・シンセのMatrixというシーケンサーを参考にした。

Reasonは実在のハードウェアを模しているので多分元ネタになっているシーケンサーがあるんだと思う。ハード→ソフト→ハードというリスペクトの輪廻である。


BaseMachine_Sequencer:
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer/

mbed、mbed-rtosライブラリのアップデートのおかげでかなり混乱したが、以前のリビジョンに戻して、想定していた機能の実装はなんとかなった。

↓使っているmbed official libraryのrevision

mbed Rev 121
mbed-rtos Rev 117

メモ:


再生中にLCDを表示させたい。再生中もパラメータの更新は可能なので、シーケンスを走らせながら打ち込みしたくなる。再生中にLCDを表示させるとrtxのエラーが出る。RtosTimerがらみだと思う。地道に調査。

機能の拡張。モード変更ボタンを用意して、シーケンス打ち込みに使っているタクトスイッチやRotary Encoderを他の用途に使えるようにする。

パターン切り替えとパラメータの保存。16stepのパターンだけだとつまらないのでスイッチ等でパターンの切り替えが出来るようにしたい。また、SDカードか何かでパラメータを保存出来るようにしたい。

シーケンス打ち込み用のデバイスも使いやすいように筐体に収める。パラレルだと配線がぐちゃぐちゃするので将来的に専用のマイコンを入れてNucleoとシリアル接続出来るように考えておく。

BPMにenvelopeLengthを追従させる?

休符時にノイズが入る。NJM13700のDCAがすぐにはOFFにならないのか?これも要調査。

2016年8月23日火曜日

ベースマシンは旧バージョンのmbedで開発続行できそう

mbedのライブラリを
mbed:  リビジョン121
mbed-rtos: リビジョン117
に戻して音声系とUI系を結合したら、まあまあちゃんと動作した。


mbed repository:
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer/

メモ:


RTOSがらみの問題は別にして、シーケンス再生中にLCD表示させるのはなかなかつらい感じだ。
LCD表示(入力系も含める?)は別のマイコンで制御してSPIかI2Cで本体と通信したほうがいいかもしれない。

まあ、でもまずは一旦完成させたいのでシーケンス打ち込みのプログラミングをしてからもう少し考える。

aitendoの「プラボックス入り金属皮膜抵抗」のケースの使いみち

aitendoの「プラボックス入り金属皮膜抵抗」のケースは使わないのでためていたが、秋月のC基板等(72 x 47mm)を入れるのにぴったりのようだ。


抵抗は釣具のケースにまとめて収納している。


そろそろパンパン(^q^;;;

2016年8月21日日曜日

ATTiny85のUSIでI2C通信を試してみる。

ATTiny85はI2Cのハードウェアは実装されていないが、USI(Universal Serial Interface)が備わっているので半分ハードウェア制御でI2Cも使えるようだ。(AVRではTWIと称している)

Tiny85への書き込み


配線図


AVRライタには、SparkfunのAVR Pocket Programmerというのを使っている。Tiny85を使うのははじめてなのでとりあえずLチカしてみた。

Fuse Bit
hHuse DF
lFuse 62
eFuse FF
LED_Blink.cpp
#define F_CPU   10000000L

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB = 0x08;
    
    while(1)
    { 
        PORTB ^= 0x08;
        _delay_ms(100);
    }
}

I2C出力




I2Cはオープンドレインなので、1kΩのRでVCC(+5V)にPullUpしている。

ライブラリは「https://github.com/adafruit/TinyWireM」を使わせてもらった。Aruduino用のライブラリだが、

USI_TWI_Master.cpp
USI_TWI_Master.h

は素のAVR用なのでこれを使ってみた。

#define F_CPU   8000000UL

#include <avr/io.h>
#include "USI_TWI_Master.h"

const unsigned char I2C_Address = 0xAA; // 0b10101010
const unsigned char I2C_Write   = 0x01;

unsigned char twiMsg[] = { I2C_Address | I2C_Write, 0x55 };

int main(void)
{
    USI_TWI_Master_Initialise();
    
    while(1)
    {
        USI_TWI_Start_Read_Write(twiMsg, 2);
        USI_TWI_Master_Stop();
    }
}

スレーブのアドレスは適当に0xAA(7bit)にして、最下位はI2CのWriteの1なのでSDAは0b10101011になる。

出力波形


I2C信号らしきものは出力されてるようだ。オシロのカーソルで測定するとI2CのSCLは約400KHzだった。

SCLの9bit目はスレーブがSDAをLに引っ張らないといけないのでマスター側としての最初の動作はうまく行っていると思う。(たぶん)

メモ:


ATTiny85のADCは差動入力+Gain20倍に対応しているようなので(http://dad8893.blogspot.jp/2016/07/blog-post_22.html)I2C LCDを制御できるようにしてみたい。

2016年8月20日土曜日

ベースマシンの全体をつないでmbedでつまずく。

音声系とUI系を全部つないでいざUIのプログラミング!といきたかったが。


配線図

音声系

UI系

以前のRTOSTimerを使ったクラスをインポートして使うと、deprecatedが出てしまうので、この際シーケンサーのプログラムをレビューしながら書きなおしてみたがやはり動作がおかしい。

細かい条件は分からないが、"rtos.h"をインクルードしてAnalogInとSPIを同時に使うと

mbed assertation failed: _ptr == (T *)&_data, file: C:/Jenkins/workspace/mbed-2-build-library/.build/mbed/SingletonPtr.h, line 84

という実行時エラーが発生する。

音声系だけテストした

SpiSequenceSender_Test https://developer.mbed.org/users/ryood/code/SpiSequenceSender_Test/

はAnalogInを使っているが、再コンパイルしても動作する。このプログラムのmbed officialのライブラリのリビジョンは以下のとおり。

mbed:      Revision 121 | 25 May 2016
mbed-rtos: Revision 117 | 23 May 2016

ほとんど1日無駄にしてしまった(@@;

2016年8月18日木曜日

禿が憎たらしい。

ここまでmbedでむちゃくちゃするということはsoftbankの思惑としか思えない。

理解に苦しむ。

IoTって (IoT;;

mbed-rtosのThreadをdeprecated(非推奨)を避けて使ってみる。

Threadのコンストラクタは

Thread(mbed::Callback<void()> task,
  osPriority priority=osPriorityNormal,
  uint32_t stack_size=DEFAULT_STACK_SIZE,
  unsigned char *stack_pointer=NULL)

だとdeprecated(非推奨)のWarningが出るのでどうすればいいかやってみた。

ThreadのAPI DocumentやThread.hを見ると、

Thread(osPriority priority=osPriorityNormal,
  uint32_t stack_size=DEFAULT_STACK_SIZE,
  unsigned char *stack_pointer=NULL)

を使えばいいようだが、コンストラクタでThread本体の関数が指定できない。APIドキュメントを見ると、どうやら

template <typename T, typename M>
osStatus start(T *obj, M method)

で、本体の関数(task)を指定するらしい。Templateを使っていてちょっとわかりにくいが、objにClassから導出されたオブジェクトへのポインタ、methodにClassのメンバ関数へのポインタを指定すればいいらしい。Templateのこういう使い方は慣れていないので間違ってるかもしれない(@@;

APIドキュメントには載っていないが

osStatus start(mbed::Callback<void()> task);

という、Classのメンバ関数ではない素の関数もtaskに指定できるようだ。

テスト・プログラム

#include "mbed.h"

DigitalOut led1(LED1);

class Foo {
public:
    void print() {
        int cnt = 0;
        while (true) {
            printf("Foo::print(): %d\r\n", cnt);
            cnt++;
            Thread::wait(100);
        }
    }
};

void print()
{
    int cnt = 0;
    while (true) {
        printf("print(): %d\r\n", cnt);
        cnt++;
        Thread::wait(100);
    }
}

int main()
{
    printf("\r\n\n*** RTOS basic example ***\r\n");
    
    Foo foo;
    
    Thread thread1;
    Thread thread2;
    thread1.start(&print);
    thread2.start(&foo, &Foo::print);
    
    while (true) {
        led1 = !led1;
        Thread::wait(500);
    }
}

thread1が素のprint()、thread2がFooクラスのメンバ関数のprint()をThreadのtaskとして指定している。

実行結果

メモ:

プロジェクトに「mbed-rtos」をインポートしておけば、"rtos.h"をインクルードしないでもコンパイルできた。

mbed OS 5のExampleと思われる「mbed-os-example-blinky」というプロジェクトをオンライン・コンパイラでやってみたが、「mbed-os」というライブラリがインポートされていて、普通の「mbed」はインポートされていない。このライブラリでmbed OS 5とClassic mbedを分離しているのかな?

「mbed-os」はパブリッシュされていないようで、オンライン・コンパイラでは普通にインポートできないようだ。

RTOSはなんかややこしそうなで出来るだけ使わない方向でいきたいが、シーケンスのタイミング取りに使うTimer割り込みは、TickerだとISR内で重い処理ができないので(参考:「Nucleo F401RE(mbed)をMasterにしてPSoC4とSPI通信する。」)RtosTimerは使わざるを得ないかもしれない。大丈夫だろうか(@@;

2016年8月17日水曜日

ベースマシンのUI POT(AverageAnalogInクラスを利用)


POTを並べたコントロール・パネルもつなげてみた。入力にはAnalogInの読み取り値を移動平均する自作のAverageInクラス(「mbedのAnalogInでPotentiometerの読み取り値のふらつきを抑える。」)を使った。

配線図

BaseMachine_Sequencer(mbed):
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer_Test/

Github:
https://github.com/ryood/BaseMachine_Sequencer

これでつなぐ予定のユーザー・インターフェイス用のデバイスは全部つなげた(^q^/

メモ:

順番に機能を追加して行ったら、実行時に
mbed assertation failed: _ptr == (T *)&_data, file: C:/Jenkins/workspace/mbed-2-build-library/.build/mbed/SingletonPtr.h, line 84
というエラーが出るようになってしまった。

プロジェクト内でいろいろやったが、RTOSを使いつつAnalogInとst7567を同時使用するとこのエラーが出る。シンプルな状態にしてもこのエラーが出る。(プロジェクト内から不要なライブラリも削除)

#include "mbed.h"
#include "rtos.h"
#include "st7565LCD.h"

//ST7565(PinName mosi, PinName sclk, PinName cs, PinName rst, PinName a0);
ST7565 gLCD(PB_15, PB_13, PB_12, PB_2, PB_1);

AnalogIn Ain(A4);

int main()
{
    printf("\r\n*** st7567 & AnalogIn Test ***\r\n");
    gLCD.begin(0x10);    
    
    while (true) {
        char buff[32];
        sprintf(buff, "Ain: %6u", Ain.read_u16()); 
        gLCD.drawstring(0, 0, buff);
        gLCD.display();
        wait(0.1);
    }
}

プロジェクトを一から作りなおしたら動作した(@@;

2016年8月15日月曜日

ベースマシンのUI タクト・スイッチ(PinDetectクラスを利用)

先ほど、PinDetectクラスが動かないと書いたばかりだが、いろいろやっていたら動作した。原因は不明だが、配線の接触不良やPinDetectクラスの割り込みハンドラ内でprintfを呼び出したりしていたせいかもしれない。混乱していたのでよくわからない。InterruptInの内部PullUpが効かなのはまだ未確認なので、前回の記事はそのまままにしておきます。


ピンアサイン

配線図

ロータリーエンコーダーとSPI Graphic LCDで組んだ回路にタクトスイッチを追加した。現状のパラメータをTextでLCDに表示。

BaseMachine_Sequencer(mbed):
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer/

Github:
https://github.com/ryood/BaseMachine_Sequencer

メモ:

mbedのRTOSでThreadのコンストラクタがdeprecatedのWarningを吐く。新しいRTOSについてもう一回調べないとダメかも。(いらないところで混乱する)
Introducing mbed OS 5 https://developer.mbed.org/blog/entry/Introducing-mbed-OS-5/

POTによるアナログ入力を追加して動作確認

シーケンス打ち込みのプログラミング

Nucleo F401REでmbedのInterruptInが動作しない。

タクトスイッチのプログラミングをしようと思ったら、PinDetectクラスが動作しない。

OfficialのInteruptInクラスも動作しないようだ。



#include "mbed.h"

DigitalOut led1(LED1);
InterruptIn sw1(D2);

volatile bool isSw1Pushed = false;

void sw1Pushed()
{
    isSw1Pushed = true;
}

int main()
{
    printf("\n\n*** InterruptIn example ***\n");
    
    sw1.mode(PullUp);
    sw1.fall(&sw1Pushed);

    while (true) {
        led1 = !led1;
        printf("%d\r\n", isSw1Pushed);
        isSw1Pushed = false;
        wait(0.1);
    }
}

main()関数内の
sw1.fall(&sw1Pushed);
で割込みハンドラをsw1Pushed()に指定すると、プルアップされなくなる(←テスタで測定)

めんどくさいけど、割り込みではなくDigitalInでPollingするクラスを作ろうか(@@;

以前は動いていたので(参考:「NucleoF401REでQEIライブラリを使う。http://dad8893.blogspot.jp/2016/05/nucleof401reqei.html」)mbed OS 5になったのが原因かなぁ。

2016年8月13日土曜日

ベースマシンのUI LCDとロータリーエンコーダー

LCDはaitendoの「CH12864F-SPI」を使うことにした。今さっき、aitendoのWebページを見たら在庫切れやん(^q^;


この間Nucleo F401REのSPI2で実験したら半分ずれていたが、mbedのst7565ライブラリはjun imamuraさんのhttps://developer.mbed.org/users/imachooon/code/st7565LCD/ではなく、
Masato YAMANISHIさんがst7567用に改変されたhttps://developer.mbed.org/users/masato/code/st7565LCD/でないとダメだったかもしれない。

とりあえずst7565LCD.cppのpagemapという変数の要素の並びを変えてやればちゃんと表示された。

ピンアサイン(途中)

配線図

ファームウェア
BaseMachine_Sequencer(mbed)
https://developer.mbed.org/users/ryood/code/BaseMachine_Sequencer/

mbed OS 5になってRTOSの仕様がちょっと変わったのかも。ThreadのコンストラクタでWarningが出た。

Thread thUI(pollingUI, NULL, osPriorityNormal, DEFAULT_STACK_SIZE);

Warning: Function "rtos::Thread::Thread(void (*)(const void *), void *, osPriority, std::uint32_t, unsigned char *)" (declared at <a href="#" onmousedown="mbed_doc_goto('/BaseMachine_Sequencer/mbed-rtos/rtos/Thread.h', '140'); return false;">mbed-rtos/rtos/Thread.h:140</a>) was declared deprecated ("Thread-spawning constructors hide errors and may lead to complex program state when a thread is declared") in "main.cpp", Line: 101, Col: 18

LCDの表示はまとめてクラス化することにした。

単体テスト(途中)
SpiSequencerDisplay_Test
https://developer.mbed.org/users/ryood/code/SpiSequencerDisplay_Test/

メモ:

D0、D1をDigitalInなどで使うと、printf()でUART出力できなくなる。そのくせD0、D1にはそれらしい波形は出ていないようだ(@@;

参考:「ArduinoとNucleoでPCとのSerial(UART)通信の最高速度を調べてみる。

Nucleo64でもピン数がカツカツになってきた。一部使えないMorpho Headerのピンがあるのではまらないように再度メモ。

参考:「NucleoF401REのMorpho Headerは一部未接続(メモ)

2016年8月7日日曜日

Raspberry Pi 3でPCM5102Aを使ってみる。

オーディオ用のDACを使ったファンクションジェネレータ」でI2S DACのPCM5102Aを使ったが、Raspberry PiでもPCM5102Aがよく使われているようなので動かしてみた。

volumio(0.976)のWebブラウザの設定画面でのPlayback OptionsでI2S DACをonにして 「Hifiberry DAC」を選択。(Rapsberry PiのRebootが必要)


GPIOヘッダのI2S関係のピン・アウト


16bit/44kHzのデータを再生してBCK、DOUT、LRCKが出力されるかオシロで確認



ch1:BCK ch2:LRCK


ch2:BCK ch2:DOUT

回路図(DATA SHEETより)

接続図


ブレッドボードで回路を組んでRaspberry Piにつなぐ前に、以前テストしたプログラムをPSoC 5 LPに書き込んで動作確認した。

参考:PSoC 5LP Prototyping KitでPCM5102Aを使ってみる。

↑このプログラムはDMAの扱いが雑で、片チャンネルの出力が変だが、PCM5102A周りの回路が動作するかどうかは確認できる。

PCM5102Aで直接ヘッドホンを駆動するのはムリがあるが、音は出た。

あっさり動いてくれてうれしいような、寂しいような。

メモ:


PCM5102Aは電源電圧によって出力が歪む様なので(参考:「PCM5102の出力にLPFをかける」)実作するとすれば電源はがんばる。

Volumio+デバイス・ドライバでプログラミングしなくても音楽を再生できそうなので、このあたりをもう少し調べてみる。

まあでも、LME49600を使ったヘッドホンアンプを作るのが先かな。

電源(3.3V)とGNDをショートさせるとRebootがかかる。要注意。

Raspberry Pi 3にVolumioをインストールしてみる。

トランジスタ技術2015年9月号を参考にしてRaspberry Pi 3にネットワーク・オーディオ用のLinuxのVolumioをインストールしてみた。

Raspbery Pi 3 MODEL B
Volumio 0.976 Released: Thu Jul 28 12:38:53 CEST 2016


ネットワーク設定


Raspberian(NOOBS)と違ってローカルのGUIがない(たぶん)のでWifiの設定がめんどくさい。我が家ではネットワークはWi-fiで運用していて、親機が1F、作業場が2Fなので簡単には有線でLANに接続できない。

LinuxでWi-fiの設定はやったことがないし、DHCPサーバが立ち上がっているLANでないと自力でネットワークの設定もしないといけないので、押入れをひっかきまわして、無線LAN子機のWL54SEを探し出して有線LAN環境を作った。

一旦有線でつながれば、PCのWebブラウザからhttp://volumio.localにアクセスすればWi-fiの設定もできた。

あとはWi-fi経由で使っていけばいいが、他のディストリビューションも試してみたいので、しばらく有線LAN環境は残しておくつもり。

SSH


いちいちモニターやキーボードをつなぐのもめんどくさいので、SSHでアクセスしてみたがrootでは入れないようだ。Web上の記事だとrootでOKの様だが。

/etc/passwdを見るとvolumioというuserがあったので

ID: volumio
PW: volumio

でSSHで接続できた。sudoも使えるようだ。

久しぶりにLinuxを使ったのでわからないことばかり(@@;

2016年8月6日土曜日

夏コミ(C90)参加します。

8月14日(日) ”g”-03a「PNPNMS」です。

今回は師匠のtozさんと隣のブースで、おそらくDAISOで売ってるおもちゃのピアノを改造する本を合同で出す予定です。

Nucleo F401REのMorpho HeaderでaitendoのSPI Graphic LCDのCH12864F-SPIを使ってみる。

aitendoのFSTN液晶モジュール(SPI) [CH12864F-SPI]をNucleo F401RE(mbed)で動かす。」でNucleo F401REのAruduino互換ヘッダを使って動作させてみたが、NucleoのMorpho Headerでもやってみた。

Morphoというのはモルフォ蝶という蝶の一種らしい。Arduino Headerの横に蝶の様にハネを広げているということなのだろうか。画像を検索するとなかなか綺麗な蝶だ。

same as Arduino header


NucleoのMorpho Headerの2列のうち内側は基本的にArduino Headerとつながっている。ヘッダのオス/メスが違う。

配線図

ファームウェア
https://developer.mbed.org/users/ryood/code/CH12864F-SPI_Test/


Morpho Headerにつないでも表示できた。

SPI2


Nucleo F401REにはSPIのHWが3個あって、2番目を使ってみた。

配線図

ファームウェア
https://developer.mbed.org/users/ryood/code/CH12864F-SPI2_Test/


こちらは半分ずれて表示されてしまった。オシロで信号を確認するとSPIのSCK、MOSI、CS、LCDコントロール制御用のa0はそれっぽい波形が出ているので制御コマンドがらみかもしれない。

メモ:


SPI1では正常表示されてSPI2ではダメ。

表示バッファが2枚あって順番が逆とかかな。

作成中のベース・マシンでは音源系にSPIを使っているので、シーケンス打ち込み用のLCDはSPI2を使いたい。

2016年8月3日水曜日

RaspPi3(ARM Cortex-A53)とNucleo-F401RE(Cortex-M4)の浮動小数点演算比較

Raspberry PiはCortex Aなので、その実力を見るために以前やったサイン波テーブルの生成をやってみた。

gen_sine_table.c

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdint.h>

#define M_PI_f     (3.1415926f) /* pi float */
#define TABLE_LENGTH  (8192)

uint8_t waveTable_0[TABLE_LENGTH];

void genSineTable_double(uint8_t *table, int length)
{
    int i;

    int16_t v;
    int8_t* p8;
    for (i = 0; i < length / 2; i++) {
        v = (int16_t)(sin(2.0 * M_PI * i * 2 / length) * 32767);
        p8 = (int8_t *)&v;
        table[i*2] = *(p8+1);
        table[i*2+1] = *p8;
    }
}

void genSineTable_float(uint8_t *table, int length)
{
    int i;
    int16_t v;
    int8_t* p8;
    for (i = 0; i < length / 2; i++) {
        v = (int16_t)(sinf(2.0f * M_PI_f * i * 2 / length) * 32767);
        p8 = (int8_t *)&v;
        table[i*2] = *(p8+1);
        table[i*2+1] = *p8;
    }
}

int main()
{
    clock_t start;

    printf("CLOCKS_PER_SEC: %ld\n", CLOCKS_PER_SEC); 

    // 単精度浮動小数点演算 (with FPU)
    printf("start float: TABLE_SIZE:%d\r\n", TABLE_LENGTH);
    start = clock();
    genSineTable_float(waveTable_0, TABLE_LENGTH);
    printf("%d\r\n", clock() - start);

    // 倍精度浮動小数点演算
    printf("start double: TABLE_SIZE:%d\r\n", TABLE_LENGTH);
    start = clock();
    genSineTable_double(waveTable_0, TABLE_LENGTH);
    printf("%d\r\n", clock() - start);
}

pi@raspberrypi:~ $ gcc -o gen_sine_table -lm gen_sine_table.c

速度を上げる工夫は何もしていない。前回とほぼおなじプログラムをgccでコンパイルしただけ。バイトの入れ替えは__REV()関数を使ったほうが早そうだが、前回と同じく1byteずつ入れ替えた。

Linux上で動かしているので割り込みやらなんやらの影響(?)で実行するごとに値が変わる。適当に見繕って表にしてみた。


TABLE_LENGTH RasPi3 float (us) RasPi3 double (us) Nucleo float (us) RasPi3 float vs Nucleo float(us)
512 160 342 372 2.325
1024 273 454 743 2.721611722
2048 455 730 1486 3.265934066
4096 897 1378 2972 3.313266444
8192 1621 2691 5943 3.666255398


Nucleo F401は84MHz駆動で、RasPi3は1.2GHz駆動なのでもっと差がでても良さそうだが、いろいろなオーバーヘッドがあるのだろう。

8192バイトのサイン・テーブルをdouble型で生成しても3ms以下なので、ファンクションジェネレータとして使った場合、ロータリーエンコーダーをガチャガチャ回したタイミングで毎回波形テーブルを作ってもストレスは少なそうだ。専用機にしてしまうのはもったいないけど。

まじめにやるならスレッドの優先順位を上げたり、HWを使ったりとかいろいろ方法がありそう。

メモ:


Webを眺めていると、GPGPUで行列演算をされている方がいた。http://qiita.com/9_ties/items/15ab7fa198991a61a3a9

ARMのAとMはよく見るが、Rはあんまり見ない。どのへんで使われてるんだろう。

Raspberry Pi Zero($5 PC)なら安いし消費電力も小さいようなので、いろいろ使えるかな~。早く手軽に入手出来るようにならないかな。