落胆がらくた街

Dr.Rootはサポート終了製品です。

2PIでループする位相変数をUINTに正規化すると美味い

http://www.musicdsp.org/archive.php?classid=1
これの Fast SIN approximation for usage in e.g. additive synthesizers を試してみた。

float fastsin(UINT32 phase)
{
    const float frf3 = -1.0f / 6.0f;
    const float frf5 = 1.0f / 120.0f;
    const float frf7 = -1.0f / 5040.0f;
    const float frf9 = 1.0f / 362880.0f;
    const float f0pi5 = 1.570796327f;
    float x, x2, asin;
    UINT32 tmp = 0x3f800000 | ( phase >> 7 );
    if (phase & 0x40000000)
        tmp ^= 0x007fffff;
    x = ( *( (float*)&tmp ) - 1.0f ) * f0pi5;
    x2 = x * x;
    asin = ( ( ( ( frf9 * x2 + frf7 ) * x2 + frf5 ) * x2 + frf3 ) * x2 + 1.0f ) * x;
    return ( phase & 0x80000000 ) ? -asin : asin;
}

検証コード↓

int main() {
    timerInit();

    float delta_f = 2 * PI * 1000 / SRATE;
    float phase_f = 0;
    UINT32 delta_i = 1000.0 / SRATE * UINT32_MAX;
    UINT32 phase_i = 0;
    

    //特に工夫無く、位相phaseと角速度deltaをfloatにしてmath.hのsinfを呼ぶ
    double t = 0;
    float test = 0;

    for (size_t i = 0; i < SRATE; i++)
    {
        timerStart();

        test += sinf(phase_f);
        phase_f += delta_f;

        t += timerStop();

        if (phase_f >= 2 * PI)phase_f -= 2 * PI; //2PIで位相がループするのはとりあえず時間計測の外とする
    }

    cout << "sinf(float)::" << "total:" << t << "[ms]\n";

    //UINT32正規化版
    t = 0;
    float test2 = 0;

    for (size_t i = 0; i < SRATE; i++)
    {
        timerStart();

        test2 += fastsin(phase_i);
        phase_i += delta_i;

        t += timerStop();
    }

    cout << "sinf(UINT32)::" << "total:" << t << "[ms]\n";

    cout << "test:" << test << ", test2:" << test2 << endl; //何らかの形で変数を参照してやらないと最適化で省かれる

}

結果。

sinf(float)::total:3.06791[ms]
sinf(UINT32)::total:0.292572[ms]
test:0.0168861, test2:6.52373e-05

UINT32、速い(確信)。
ちなみに計測環境はWin8.1、cpu:intel 4690k、DRAM 16GBでコンパイル環境はVisual studio 2015のVisual C++、x64 Releaseビルドで最適化レベル最大。
sinの出力結果の総和が微妙に異なってるのは精度の問題なんだが、別に精度計測のソース書いたら1サンプル毎の精度は十分だったので割愛。


位相をUINT32に正規化するメリットを考えてみる。

  • 検証コードでは時間計測から省いたけど、真面目に2PIでループさせようとする場合1サンプル毎に位相が2PI超えたら戻す処理がいる。UINTならオーバーフローするので不要。
  • 位相を元にテーブルを引きたいみたいな時、位相変数の上何桁と下何桁を分けるみたいな処理が高速で出来る float->intキャストよりずっとはやい!
  • fastsinが速い
  • 位相変数そのものの計算もビット演算が使える分そこそこ速い。特に頻出の2n倍が高速なのは嬉しい

とかこんな感じかな。結構嬉しいと思うんだけど、逆にデメリットはどんなんあるんだろう。誰か教えてください。

デジタル信号処理チートシートと、BLITと殴り合ったメモ

デジタル信号処理でよく出てくる式とか変数とか関係をリストにしてみた
シンセとかプログラミングするのにこんがらがった時はどうぞ


  • int  R:サンプルレート。殆どの場合、44100か48000のどっちか。ほぼ定数とみなして良い。
  • int  F=R/2:ナイキストレート。やはり実質ほぼ定数で、22050または24000。
  • float  f:鳴らしたい周波数[Hz]。↓の f_{min}を用いて、 f_{min} \leq f \leq Fになる。
  • float  f_{min}:鳴らしたい周波数の下限。大抵10[Hz]とかそんなもん。
  • float  T=1/f:周期。単位は秒。
  • float  p:現在の位相。2πでループするんだから、 0 \leq p \leq 2\pi
  • float  {\omega}=2{\pi}f:fにおける角速度。つまりf[Hz]のサイン波は現実世界では sin({\omega})=sin(2{\pi}f)
  • float  d=2{\pi}f/R:1サンプル毎に進む位相差。つまり1サンプル処理する毎にp+=d; if(p>=2*PI) p-=2*PI;をするということ。 \omegaのデジタル世界版。fの条件から、  0 \leq d \leq \piになる。
  • int  H=(int)F/f=(int){\pi}/d:ある鳴らしたい周波数fにおいて、倍音が何個出せるか(F以下に収まる倍音の数)。整数倍音は全部持つ(ノコギリみたいに)と仮定。
  • float  P=R/f:周波数fの信号が1週するのにかかるサンプル数。ぴったり整数個でループするとは限らないので実数。
  • float  sin(2{\pi}\frac{f}{R}n):サンプルレートR、周波数fのサイン波のn番目の値。

あとBLITのメモ
 \displaystyle \begin{align}
Sinc_{M}(x)=\frac{sin(\pi x)}{Msin(\frac{\pi x}{M})}, \\
y(n)=\frac{M}{P}Sinc_M(\frac{M}{P}n) \\
=\frac{1}{P}\frac{sin(M\frac{\pi}{P}n)}{sin(\frac{\pi}{P}n)}
 \end{align}
ここでMはPを超えない最大の奇数(int)。
こいつを日本語訳すると、 「y(n)はナイキストレートまでの周波数で帯域制限したf[Hz]のインパルス列のn番目の値」。
Pは1周するのにかかるサンプル数なので上記チートシートの通りR/f。つまりサンプルレートを鳴らしたい周波数で割ったもの。
この帯域制限されたインパルス列から帯域制限されたSAWやSQUAREを作れる。
詳しくはg200kg氏のページ参照(必読)。

BLITのお話 | g200kg Music & Software


ところで、おもむろに  P=R/f \Rightarrow \frac{1}{P}=f/R をBLITの式に突っ込んでみよう。
 \displaystyle \begin{align}
y(n)=\frac{1}{P}\frac{sin(M\frac{\pi}{P}n)}{sin(\frac{\pi}{P}n)} \\
=\frac{1}{P}\frac{sin(M{\pi}\frac{f}{R}n)}{sin({\pi}\frac{f}{R}n)}
 \end{align}
sinの中身をよく見てみると、f[Hz]のサイン波が sin(2{\pi}\frac{f}{R}n)なんだから、 sin({\pi}\frac{f}{R}n)は鳴らしたい周波数の半分の速度のsinだ。つまりBLITとは「f/2[Hz]のサインでMf/2[Hz]のサインを割ったもの」と言える。ここから、

BLIT(p)=\frac{f}{R}\frac{sin(M\frac{p}{2})}{sin(\frac{p}{2})}
が得られる。
y(n)は「BLITのn番目の値」を引っ張ってくるわけだが、BLIT波形の1周が綺麗に整数個で収まるとは限らない(=Pが整数とは限らない)ので、BLIT(p)=「p[rad]におけるBLITの値」を算出できるようにしておいたほうが都合がいい場合もあると思う。


F[Hz]に帯域制限されたf[Hz]のインパルス列が、なんでこの式で得られるのか。
式の算出過程は理想インパルス列(デルタ関数級数)を理想LPF(時間領域でsinc関数)と畳み込んだものなんだが、得られた式は何がどういう意味を持っているのか。
早速Maximaさんにグラフを描いてもらった。 f:id:suzumodoki:20180121023528j:plain
極限の扱いが上手く出来ておらず、分母が0の時なにやら変な感じになってしまっているが、理想的には滑らかなsincの列なので脳内補完して図を眺める。
まずBLITの式を簡略化すると、振幅を決める \frac{1}{P}はこの際重要じゃないので無視して、意味があるのは \frac{sin(Mx)}{sin(x)}の部分。
ここで x = \pi\frac{f}{R}n だが一旦おいといて、結局こいつは角速度 MxのSinと xのSinの逆数との積だと言ってるわけだ。

まず \frac{1}{sin(x)}はこんな感じ。 f:id:suzumodoki:20180121025414j:plain
赤線が1/sin(x)なんだが、ソフトに書かせると無限の部分を真面目に描いちゃうので、あえて手書きで概略図にしている。
で、こいつにsin(Mx)をかけると… f:id:suzumodoki:20180121030914j:plain
こんな感じ。イマイチ分かりにくいが、大雑把にまとめると

  • 1/sin(x)が発散するタイミングで、 \lim_{x \to \infty} \frac{sin(Ax)}{x}=AよりMになる(インパルスがぴこっと立つ)
  • よって1/sin(x)は「インパルス列そのものの周波数」に対して影響を及ぼしている。
  • よく見るとx=0,π,2πで1/sin(x)が∞になるので、インパルスが立つのはsin(x)の倍の周期。BLITがf/2のsinで割っているのはこういう理由。
  • 分子のsin(Mx)は帯域制限する周波数に対するパラメータ。事実上Mが帯域制限周波数になる*1
  • もしMが奇数だと、インパルスが立つ瞬間の1/sin(x)とsin(Mx)は同じ符号になるので、必ずインパルスはプラス側に立つ。
  • 逆にMが偶数だと、インパルスがプラスとマイナス交互に立つ。これを「バイポーラBLIT」と言う。
  • 矩形波作りたくてバイポーラBLITをやると周波数が半分になる、というのはこの理屈から1/sin(x)だけ倍の周波数にすれば解決する。多分。

といったところ。


現実的な問題と備忘録。
 Sinc_M(0)=1より BLIT(0)=M/Pであるべきだ。黙ってsin/sinをプログラミングすると、sinはともかく割り算が出るので一々0除算じゃないかチェックしなきゃならず辛い。
この間「sinをテーブル引きにすると速い」というネタを自分の環境で試したら速いどころか100倍以上遅くてゲンナリだったんだけど、Sincとか1/sinみたいなのをテーブル化するんならやぶさかでない気もする。というわけで今後は本格的にどんな実装が速いのかとか、数学よりもっとC++とかx64で効率的なやり方を考えようと思います。どっとはらい(あ、あと位相変数は2πをUINT32に正規化するとオーバーフローのお陰で周期性チェックいらなくて便利じゃねっての思ったのでこれも今度試します)

*1:うまいことやればPを整数に決め打ちしても任意のMで帯域制限できそうなんだけど勉強不足で未検証

もうちょっと真面目にパナ改を作った

まえがき

suzublog.hatenablog.com
↑およそ一年前に作ったやつ
こいつは回路の実験という側面が強かったし、単純に出来がよろしくなかったので、「余り物で安く作る」というコンセプトはそのままにもうちょいマトモな代物を組み上げた。
ろくに回路を知らなかった去年よりもう少し知恵も付けたので、多少はマシになった筈だ。採用した回路はいつもの通り
1713 :ファンタム式パナ改マイクの単純化 省電流バージョン|ShinさんのPA工作室
からパクらせていただく。ただし、マジで金が無くて秋月で買い物する送料すら捻出できない貧乏ぶりなので、「コンデンサは容赦なく積層セラミックを使う」という致命的な欠点が。

でざいん

本体及びハウジングだが、これも余り物の流用で、まずXLRはサウンドハウスで一番安かったこれ。
CLASSIC PRO ( クラシックプロ ) >CXL2B | サウンドハウス

マイク本体を収めるのは、ぶち折れたオシロスコープのプローブを流用。
オシロスコープ・プローブ(60MHz): 測定器・計測器関連 秋月電子通商 電子部品 ネット通販
これをバラすとどうなるかはこちらの記事が参考になる…というかまんまだ。
オシロスコープのプローブの修理 ( 修理とリフォーム ) - 金田式アンプ・ファンのささやき - Yahoo!ブログ

さらにそれらを収めるハウジング的な何かとして、余ってたモノプラグのガワを流用。なんでも良いんだけど、これが一番サイズがぴったりだった。
https://www.soundhouse.co.jp/products/detail/item/25715/

f:id:suzumodoki:20171214150549j:plain
右から、「BNCコネクタをバラバラにしたもの」「プローブの持ち手のゴム?の部分」「モノプラグのガワ」「ガワだけ使われていらない子になったモノプラグの本体」。

電子的な部分について。
マイク石はお決まりのこれ↓。拘る人はオリジナルのWM-61Aに拘るらしいが、とりあえず安くて手に入りやすいのでこっちに飛びつく。
エレクトレットコンデンサーマイクロホン(ECM) WM−61A相当品: パーツ一般 秋月電子通商 電子部品 ネット通販

また基盤は、元ネタの「コネクタの中に回路を全て入れる」というアイデアを拝借。必然的に小さい部品が有利なので、J-fetはこれ↓を使う。2つのJ-fetが1チップに収められており、しかもソース同士が内部でくっついている(元の回路図と同じ状態になっている)ので大変好都合だ。
Nch J−FET 2SK2145−BL (2個入): 半導体 秋月電子通商 電子部品 ネット通販

そして基盤は面実装モノをうまい具合に乗せられるこれ↓を採用。こいつは穴がちっこすぎて面実装以外の部品がマトモに乗らないのだが、
64ホールユニバーサル基板(1.16mm): パーツ一般 秋月電子通商 電子部品 ネット通販

こいつの端子部分を引っこ抜くとうまい具合に変換ピンとして流用出来る。↓
シングルピンソケット (低メス) 1×20 (20P): パーツ一般 秋月電子通商 電子部品 ネット通販
f:id:suzumodoki:20171214150536j:plain

ケーブルを受ける側の基盤は同じサイズでDIPピッチの物があるのでこれと繋げばOKだ。
16ホールユニバーサル基板(2.54mm): パーツ一般 秋月電子通商 電子部品 ネット通販


抵抗はebayで中国人が何故か送料無料で送ってくれた大量の面実装抵抗を使う。精度?知らんな!w

かいろ

「超簡略版」との事だが、ファンタム電源を使う以上はいくら簡略化されていても構わない。どうせゲインはオーディオインターフェースでどうとでも出来るからだ。
抵抗4つ、コンデンサ2つ、面実装のJ-fet実質1つを基板上にせっせこ組み上げるだけで出来上がる。今回はあれこれ余り物を使った以上ちょっとヘンな部分があるので回路は本家様にまかせてここではさらっと各部品について触れる。

まず、各J-fetのゲートからGNDに落としている1MΩの抵抗。こいつは十分大きければ何でも良い。今回は在庫事情から750kΩを採用したが、そんなに精度もいらんだろう。
次に、マイクのマイナス、即ちマイク内蔵FETのソースからGNDに落ちている2.2kΩ。こいつはマイク石のデータシートに指定されている数値なので、余り弄るべきじゃないだろう。精度がいるかは謎だが。
で、J-fetのソースからGNDに落としている1.5kΩ、これもなるべくこの通りにした方がいい。まぁ今回は1kΩにしちゃったんだけど。元の回路は2sk-2880というJ-fetを使ってるんだが、今回使ったJ-fetはもうちょっとソース電流がデカいので、それに合わせて少し下げてみた。ここの抵抗がどんな影響を及ぼすかは検証の余地あり。

2つの0.22uFコンデンサ。これは耐圧50V以上が必須で、かつなるべくオーディオ向きのフィルムコンなんかを使うべきだ。在庫無いから安物の積セラ挿したけど(号泣)
ただ、0.22uFという数字は検証の余地があると思う。こいつを絞ると低域がカットされる筈だが、完成品を使ってみた所どうも低域がちと強すぎる感じがあった。好みで上下させていいと思う。

かこう

兎にも角にも苦労するのは加工作業だ。もしこれから初めてこのECM改造をやるのであれば、安いものなので多めに買って練習すると良いと思う。
f:id:suzumodoki:20171214150542j:plain
画像左が無加工の状態。青字で注釈を入れたが、ようはこの黒い点がスルーホールで、内部のマイクの端子にくっついているわけだ。初期状態ではマイクのガワ(GND)とくっついているのが困るので、うまい具合に切り離さなきゃならない。まず予め乗っているハンダが邪魔なので吸い取る。次にスルーホールを潰さないよう気をつけながら、基盤の金属部分、赤点線の所をカッターでせっせこ切って電気的に切断する。マイクのガワはまずハンダが乗らないので、基盤部分をマイク-とGNDに分けなければならないわけだ。マイクは熱に強い部品ではないので、コテを押し当てる時間は長くても3秒程度、それを超えたら一旦冷やす…という感じでやると失敗しにくいと思う。

出来上がったマイクの各端子に配線するのも一苦労だろうが、これはなるべく細い線を使えば(そしてコツさえ掴めば)難しくない。お勧めは物故割れたイヤホンの線だ。こいつは極めて細い上に秋葉原まで出なくても安く簡単に入手出来るというメリットがある。金の話しかしてねぇな…?
メッキ皮膜がなされているので普通に剥がそうとすると大変だが、「ハンダゴテの熱でメッキを溶かして剥がす」というテク(?)を身につければ楽勝だ。まず乗らない事を承知の上ではんだを線材のさきっぽに当ててコテで溶かす。そのまま線材にコテを当て続けると、はんだを通じて熱が伝わり、メッキが黒く焦げて焼け落ちる。黒くなった部分をコテ先で擦るとうまい具合にメッキが剥がれてハンダが乗ってくれるというわけだ。
f:id:suzumodoki:20171214150527j:plain
画像は作業途中の2線繋いだ所。

なお、この配線作業も慣れない内は失敗がつきものだと思う。そんなこと無い?自分だけ?
そんな時、「とりあえずマイクが生きてるかどうか確かめる回路」をブレッドボードかなんかに作ってテストすると便利だ。
f:id:suzumodoki:20171214160047j:plain
ようは本家本元、3線加工する前の回路でマイクテストして、ちゃんと音声が取れればとりあえず配線は成功、という事で。当たり前だけどこの回路はファンタムじゃないので注意。単三電池一個あればテストできるので便利。

くみたて

f:id:suzumodoki:20171214155051j:plain
コンデンサに小さい積セラを使っていることを除いても、面実装部品を遠慮なく使えば余裕を持ってコネクタに収まる事がわかる。
ちなみに手前のケーブル及びコンデンサ部分の基盤と、XLRピンに繋いだ面実装基盤部分は分離できるように作ったので、もし色気づいてお高いコンデンサを買い足しても簡単に改造出来る仕組みだ。今度部品を買いに行く機会があったらやってみよう。

f:id:suzumodoki:20171214155043j:plain
出来上がり。大分端折ったが、どんな部品が手元にあるかで作り方は千差万別だと思う。兎にも角にも、「6ミリ径のマイクがきれいに収まってケーブルを通せる部品」があればなんだって良いのだ。それこそ100均で売ってるチャッカマンの先端の筒部分だって良い。回路部分に関しては、本家のJ-fetや高精度抵抗への拘りも理解できるものの、コストに釣り合わないとか、そもそもS/N比が良ければあとは加工次第でどうにでもなるとか、アマチュアにはアマチュアの事情があるので、個人個人で部品を選べばいいと思う。自分は面実装を容赦なく使用し、確実にコネクタに入れられる方針を採用した(でもコンデンサは自分でも酷いと思う)。もっと一般的な事を言うなら、
・J-fetはNchのものであれば何でも良い。音は好みによる所が大きいので、出してみないとわからない。
・抵抗は高精度であることが売りになる部分(1.5kと2.2k)とそうでもない部分(1MΩ)がある。前者は拘る価値があるかもしれないが、音質にどこまで影響するかは謎。精度より温度特性を意識したほうが良いかも?
コンデンサは拘る価値が大いにある。ただし、容量に関しては検討の余地がある。0.047uF~1uFあたりを色々試してみたい所存。ただし2つのコンデンサが同容量なのは絶対。

おためし

といったところ。肝心の録音に関しては、「A/Iのゲインが最低でも十分過ぎるくらいの音量でびっくり」という結果に。これはこれで不便かもしれないので要検証。
Twitterには録音した音源を挙げたのだが、ネタに走ってクッソ汚い六尺コピペ朗読音声しか挙げなかったので、こっちに挙げるのは後日マトモな奴を正式に録るということで…

一月以上経った今、ふと思い出してようやく録音のテスト音声を上げる事にした。
録音はsteinberg CL-1。廉価なA/Iなので、ここが音質に影響を与えてる説はあるかもしれない…。

とりあえずテキトーにエレキギターを弾いてみた。ソフト的な処理はゲインだけで、ノイズキャンセルの類は皆無。
個人的には十分な音質だと思うんだが、どうもマイクと距離や角度があると急激に音が取れなくなるらしく、例えばウェブカメラのマイクのような部屋全体を録るには向いてない。
楽器や声を録るには良いだろう。

全くのおまけとして、同じギターを同じA/Iにライン録音で録ってみた。

…こ、こいつぁひでぇや!
A/Iがダメなのか、ギター(バッカステレキャス 元値15k ほぼタダで貰った)がダメなのか、いや両方か。
しかし一番ヒドいのは自分のギターの腕前そのものだった。先輩こいつ1年以上やってて未だにF弾けないらしいっすよ?

Split-Radix型大浦FFTの一部をC#に移植した

qiita.com

Qiitaクソ便利だしもうプログラム関連の記事はあっちで書くわ 何がはてなじゃw

~~~

Qiitaでは一切関係ない話題だから書かなかったけど、大浦FFTもFFTWも基本的には「いかに高精度で、次に速く」を原則として作られてる。ので、例えばDTMで使うVSTプラグインみたいな、「まぁ概ねスペクトルの概形が見られればOK」っていうシチュエーション、すなわち「いかに速く軽く、次に高精度で」を原則とした場合まだイジれそうな気がする。

具体的には、FFTはサンプルをN個突っ込んで、サンプルレートの半分を更にNで割った分だけ周波数分解能が得られるわけだが、パラメトリックイコライザなんかでとりあえずローをばっさり切るべーみたいな時に果たして何千という分解能はいるのかという感じ。だから「8192個のサンプルを突っ込むんだけど、求める係数は1つ飛ばし」とかでもいいんじゃね的な。

なんでこんなこと考えてるのかというと、CubaseからStudio Oneに移行したら、Cubaseにあったデフォルト付属のパライコがなくなっちゃったのだ。あのチャンネルストリップに最初から刺さってるやつ。
んでスタ1には一応ProEQって結構高性能なEQが付属しとるんだけど、もっともっと手軽に使えるEQの需要ってあるんじゃないかと思った所。
例えばミックス処理なんかで、大抵のトラックにはローカットを食らわせつつ特定の周波数帯をピークEQでどついたり削ったりするってのがよくある話だと思うんだけど、それやるのにそんな高級なEQいちいち挿したくない。んで探すと意外とフリーでシンプルなパライコ無いんだよな。なんかどれもコレも性能重視というか。性能は雑魚くていいから馬鹿みたいに軽い奴誰か教えてください。

~~~

もいっこ思ったんだけど、FFTというかオーディオのバッファリングでよく使われるのがリングバッファだ。リング状の配列にぐるぐるデータを突っ込んでいく。で、FFTをかけるときは、例えばサイズ8のリングバッファを4つずつFFTかけるみたいな時、最初はa0からa3をFFT、次はa1からa4、次はa2~a5…みたいにちょっとずつずらしながらFFTをかけたい…なんていうのが思いつく。ところが大浦FFTはin-place演算なので、FFTをかけたら元のデータは無くなってしまう。ましてやこの「ずらしながら法」の場合、ハミング窓も一緒になってずれていくので、こうなると一々FFTをかけたい部分だけリングバッファからコピーしないといけない計算になる。こりゃー無駄だ。

っていうのを何とかしたかったんだけど、素のFFTアルゴリズムを自前で書いてリングバッファと窓関数を対応させたやつよりも、一々バッファをコピーしてから大浦FFTかけるほうが速度出たからもう寝るわw

Vscode+PlatformIOでIntelliSenseが変なもん参照する時の覚書

前置き

f:id:suzumodoki:20171125212155j:plain
画像はVS codeにPlatform IOという拡張をぶち込んで
Mbed lpc1114fn28向けのプロジェクトを立ち上げた時の一コマ。
一見1114向けのヘッダが見事に読み込めているように見えるし、ビルドもちゃんと通るのでとっても快適。

f:id:suzumodoki:20171125221448j:plain
ところが、実はこんな明らかにヘッダファイルを読めているにも関わらず、IntelliSenseが1114のピンネームマクロ「dp14」を候補に出してくれない。
コンパイル・ビルドが通る以上ビルドツール向けのパスの設定はちゃんと出来ているので、問題はプロジェクトフォルダのc_cpp_properties.jsonという事になる*1
で、c_cpp_properties.jsonがどうなってるかというと…

イヤーッ!
f:id:suzumodoki:20171125212815j:plain
グワーッ!

これは「configurations」属性の直下の「includepath」属性なので、コンパイラに渡すインクルードパスと同じだ。
ここの設定は正しいのだが、何故かIntelliSenseはこのインクルードパスを参照してくれず、果には「mbed.hなんて無いよ」とか言い出す。
で、下の方を見てくと、「browse」というタグがあり、やはりその下にはpath属性があって似たような記述がずらっと並ぶ。
browse属性は何をしているかというと「fazzyモード(厳格ではない、多少のエラーは気にせずコード解析するモード)」で候補を出すときのインクルードパスだ。
最初にVs codeでプロジェクトを起こした時、インクルードパスを何も設定してないせいで#includeプリプロセッサに緑の線が引かれるが、あれは「参照が解決できないのでファジーモードで候補出すよ」という記号だ。だから緑の線が無くなるまできっちりインクルードパスを書いてやったのだが何故か逆に何も読んでくれなくなった(原因不明。誰か教えてください)。

コンパイラに渡すインクルードパスと違い、「browseのpath属性」にIntelliSenseが検索をかける時はサブフォルダまで舐め回すように探すので、
このずらーっと並んだ書き方は恐らく無駄でしか無い。
例えば1114が参照するのは「targets/TARGET_NXP/TARGET_LPC11XX_11CXX」以下なんかにあるファイルだが、
ドタマに「C:/Users/admin/.platformio/packages/framework-mbed/.」が書かれている以上、その下にある全く関係無い他のデバイス用の同名のヘッダも全部読む。
そして名前の衝突が起こった場合、本来ならばIntelliSenseは複数の候補があると言ってくるのだが、「複数の候補が存在するa.hからやはり複数の候補が存在するb.hをインクルード」というシチュエーションの時、どうやらb.hで名前がぶつかっている候補をIntelliSenseは見つけてくれない。

f:id:suzumodoki:20171125214129j:plain
PlatformIOはMbedプラットフォームを選択した時点で対応しているライブラリを全てダウンロードして手元に置く。
その為、たとえ存在を知らないような、BEETLEとかいうわけのわからんボードのAPIも手元にある。これは2017/11/25時点でMbedプロジェクトフォルダのアタマに置かれている(framework-mbed\targets\TARGET_ARM_SSG以下。)
で、ビルドツールは設定されたマクロに従い、図の右下の1114用ライブラリをきっちり読み込んでくれるのだが、ファジーモードのIntelliSenseはそんなマクロ知ったこっちゃないので、まずDevice.hで競合する(図中とりあえず①)。この時はまだ「競合してるよ」的なウィンドウを出してくれるのだが、ここから更に読み込んでいるヘッダに関しては「競合が解決されない以上は仮に一番上のヘッダを読んでおく」事になっているらしい。つまり、「TARGET_ARM_SSG\TARGET_BEETLE\PinName.h」をPinName.hの代表として読むわけだ(図中とりあえず②。図ではobjects.hが一例)。
かくして1114の為のPinName.hは読み飛ばされ、候補にdp14というマクロは出なくなる。纏めると、
「厳密な解析モードだと何故か何も表示してくれない。ファジーモードだと何もかも読み込み衝突を起こす」。


解決策

ようはbrowseタグのpath属性でサブフォルダを読まないようにすればいい。
vscode-cpptools/c_cpp_properties.json.md at master · Microsoft/vscode-cpptools · GitHub
リファレンス曰く、「パスの末尾が/*か\*ならそれ以降読まない」との事。なので、このずらっと並んだ部分を選択して、置換コマンドで
「",」を「/*",」に置換してやる。これだけ長ったらしく前置きをした挙句やることがこれだけって…。
f:id:suzumodoki:20171125223000j:plain

なお、今回はMbedの話だが、多分どのプラットフォームを選んでも似たり寄ったりじゃないかと思うので、状況は違えど現象が同じなら同じやり方でなんとかなると思います。
いやわかんないけど。めっちゃ対症療法だし。

*1:インクルードパスなどを設定する、プロジェクトフォルダ毎の設定ファイル

例大祭14戦利品

今回買った中で特に良かったもの。自分向け。太字は今年初めて買ったサークル。
敬称略。


・べにしゃけ/poprication 初恋に捧ぐ
レイマリ。いつも通り文句なしの傑作。もう殿堂入りみたいなもんだし割愛。

いな/Inadahime 床伏の君。
レイマリ。文章力がないので上手く書けないがとても良かった。次回レミフラ描くらしいのでそっちにも期待。

・よぬりめ 雨音が結ぶ
レイマリ。ここも殿堂入りみたいなもんだし割愛。ところでよぬりめさん体調の方はもう大丈夫なんだろうか。

電派絵師団/しろし 科学世紀小噺
SF色強め。個人的にはかなりアタリ。秘封。

あみだ屑 秘封倶楽部モノ
漫画を描く技術が頭一つ飛び抜けてる。構成や描き込みの技術が魅せる。

・romi/あじさい通り 蓮子が落ち着かない話。
前から好きなサークルなので割愛でもいいんだけど今回はいつもより甘めかもしれん。蓮メリ。
秘封ってシリアスな話多いんだけどここのはダダ甘でいいね。

にくにくみっく ふきのとうは甘く
サニーとスターのR18。作者は間違いなく筋金入りのロリコンだと思う。幼児体型へのこだわりが尋常ではない。

・杏飴/こいんとす おかしが食べたいっ
まぁここも毎年買ってるし有名だし殿堂入りっすね。割愛。


全体として豊作だったけど古明地姉妹がちと不作だった。ここ数年言ってるけどサークルスペースが変わらないままキャラやジャンルが増えたので好きジャンルの本の絶対数が下がっている。そろそろ新ジャンルを開拓しないと…

LPC11u35 DIP化基板を試す

ついき
LPC11U35 DIP化基板で遊ぶ | 落胆がらくた工務店
新ブログの方でわかりやすく書き直した。なんで今さら書き直したかって?プルアップ抵抗の記述がすっぽ抜けてて自分で1日悩んだからだよ。ファック!

0.2017年秋も終わり頃の追記
LPC11U35マイコンボードキット (LPC11U35 QuickStart Board互換): マイコン関連 秋月電子通商-電子部品・ネット通販
今気づいたんだけど今年の6月(つまりこの記事の本文を書いたひと月後くらい)にこんなんが出てた。
マイコン、回路、周辺回路、その他諸々でお値段850円也。
これを買えば手間暇回路をあれこれする必要は全く無い

つまりこの記事の存在価値もまったくない。

一応残しますが、資料として真新しい要素は無いし、お安くMbedでUSBdeviceが叩きてぇようって人は黙ってこれ買えば良いと思います。
あ、それと、一応850円基盤の方は11U35の足が一部オミットされてるので、「11U35の足を全部くまなく使う予定があるんじゃ」という人にはいいかも。いるのか?

結論。もう一月早く出してくれ。

          • 追記ここまで------

秋月でこんなのが売ってた。
LPC11U35 DIP化モジュール: マイコン関連 秋月電子通商-電子部品・ネット通販
LPC11u35を単体で試せるとのこと。お値段500円也。
11u35はUSBを搭載したマイコンで、プログラムの書き込みもMbedでお馴染みのマスストレージとして認識されるアレが出来る。
ただしその為にはちょっと回路を組まなきゃならないよ、ということで参考になったサイトなんかを纏めておく。
(ようはトラ技ARMライタを自前でやっちゃおうという話)

1.いるもの
マイコン単体だけではどうにもならんので必要な資材を挙げる。
・12Mhzクリスタル
・クリスタル用コンデンサ20pf 2個
・USBコネクタ
・3.3V出力のレギュレータ
・レギュレータ用コンデンサ
ISPモード用のスイッチ(必須ではない)
といった具合。最初1114みたいに内部の発振器が使えると思い込んでて延々悩んでたけど外部にクリスタルが要る模様。

2.回路
実は同じようなことを自前で既にやってらっしゃる方がいる。
mbedクラウド対応CPUボード
ここにある「回路図」がまんまやりたいことなので、参考にさせていただく。
ただし、USBDeviceとしてのみ使う場合は外部電源の存在を気にしなくて良いので、PIO0_6 USB_CONNECTあたりの端子は不要になる。
秋月の商品画像とマイコンのデータシートを加工して(勝手にやった。万が一怒られたら消す)ピンアサインっぽいのを作った。
f:id:suzumodoki:20160917204419j:plain
これを見ながら組んでいく。
注意点としては、
・左右にVDDが一つずつあるが、別に内部で繋がってたりはしない。どちらも3.3Vに繋ぐ必要がある。
・データ線に直列で入ってる33Ω抵抗とかは無くても動く。勿論一応あった方が良いに越したことはない。
・VBUSには文字通りUSBからの5Vをブチ込んでやる。抵抗は入れても入れなくても良い。
・何か知らんけどリセットが効いてるんだか効いてないんだか。USBを指し直さないとリセットが効かない?


f:id:suzumodoki:20160917204224j:plain
組み上げたところ。ブレボでやったら結構ごちゃっとしたからもしかしたら基板組み上げちゃった方がいいかもしれない。
USBを繋いで、マスストレージデバイスCRP Disabled」が表示されたら成功だ。本来ISPピンをLOWにしながらリセットした場合だけこのモードに入れるが、初期出荷時はデフォルトでここに入るらしい。
11u35については以下のページが詳しい。
家庭用コンピュータ環境の模索:(トラ技ARMライタ基板:2014年2月)TG-LPC11U35-501 活用


3.あそびかた
恐らくMbedを使ったUSBDevice対応マイコンとしては現時点で最安の選択肢になる(次点でNucleoか?性能はダントツだがサイズがね…)。
USBDevice - USB device stack | Mbed
こいつを一発コンパイラにブチ込んで、試しにUSBSerialを書き込んでやろう。書き込んでからリセットをかければ、Mbed virtual serial portがインストールされ…ない。
どうもドライバが要るらしい。
直リン:https://developer.mbed.org/media/uploads/samux/serial.zip
デバイスドライバの不明なCDCドライバを更新する→上記infを読みこませるとやればドライバが入…らない。セキュリティ証明書が無いらしい。ファック!
セキュリティ証明を無効にして再度ドライバをインストールしてようやく成功。TeraTermからデバイスが見え、500円マイコンからPrintfが出来た。


ちょろっと電子部品がいるので、500円で済むとは言えないのだが、それでもあれこれあわせて7,800円で組み上がる。
それでもNucleoの半額くらいなので、USBDeviceを作りたい人にはいい選択肢なんじゃなかろうか。特に私のような貧乏人には良い商品だと思った。ありがたや秋月。