2020年4月30日木曜日

戒厳令日記(23日)

どうやら戒厳令日記は60日目まで続きそうです.
このような忌まわしい特集は早く手じまいするべきだと思います.


【戒厳令日記(23日目)】
昨夜2時      就寝

10:00     起床、M先生へ電話予約

11:00     M先生の医院へ.いつものクスリをもらう.
M先生の医院では、疫病疑いの患者は午後の診察として時間分けしている.頑張ってね.

12:00     久しぶりの外出なので吉野家を食べる、本屋へ行く.
本屋でムーとダイヤモンドを買う.ダイヤモンドは相続特集なので買った.伊勢原の家を相続したくないのだ.

13:00     ついにその時が来た、来てしまった.精神病院入院中のアルツ毒父が退院する季節なのだそうだ.わたしがダイヤモンドの相続特集を買った1時間後に退院の電話がかかって来るというシンクロニシティが不気味である.油断ならないぞ.

14:00~     STM32


本日会話した人:  おくさん、M先生、受付の人、薬局の人、吉野家の人、本屋の人

本日の最長外出距離:   500m

本日のキャッシュアウト:   M先生¥1500   薬¥1800  吉野家¥400    雑誌¥1500

かしこ

STM32でDCCを作る方向で (7) SPIの具合はどうかな?

STM32 DCCの開発を行っている.    INDEXページへ

PCからのaudio streamがSTM32内部FIFOへブタ積みされるのはわたしには高難易度だけどやればできるのだろう.

どうやったらできるのかがいまいち謎なのは、意外にも、FIFOに積まれたaudio streamを円満にCPU外部へ出力できるのか、なのだ.もちろんFPGAみたくロジックを全部自分で設計するのなら無問題である.しかしここでは、STM32のDMAでどうやって外部出力するんだい?という点が課題となる.

ちなみに、DMAのdestinationとしてGPIOを指定することは出来ないようだ.
DMA出来るのは、SPIやI2CのようなSTM32に内蔵されたperipheralだけである.
ゆえに、SPIやI2Cへaudio stream dataを不具合なく出力できるかどうかを実機で確認しなくてはならない.(I2Cは最初から捨てている)

今回は、STM32内蔵SPI1を使ってみて、その挙動をチェックしてみる.
targetはSTM32F207.SPIのSCKは最高設定の30MHzである.TX only masterである.
STM32CubeMXでSPI1を組み込む方法については割愛する.

main.cのwhile()にSPIを動かすcodeを追加する.txbuf1[]="123"とする.
このcodeは、CPUが介在してSPIへせっせとデータを運ぶ形式である.
  while (1)  {
while (HAL_SPI_GetState(&hspi1)!=HAL_SPI_STATE_READY){}
HAL_SPI_Transmit(&hspi1, txbuf1, sizeof(txbuf1), 0xFFFF);
HAL_Delay(500);
  }
↓SPIバスのMISO(上)とSCK(下)を観測したらこうなった.
なんで送信が間歇的になっているんだ? CPUがせっせと働いている遅延時間なのだろう.こりゃ使えない.それともう一つ気になるのは、送信バイト数は3bytesなのに、4byte目に00Hが勝手に挿入されているんだが... この00H挿入は偶数bytes合わせのためかと思ったがそうではなく、4bytes送信には5byte目に00Hが挿入されるのを確認した.

次に、DMAで同じことをやってみると、、、、
  while (1)  {
while (HAL_SPI_GetState(&hspi1)!=HAL_SPI_STATE_READY){}
HAL_SPI_Transmit_DMA(&hspi1, txbuf1, sizeof(txbuf1));
HAL_Delay(500);
  }
↓DMAは高速なので間歇じゃなくなった.全部一気に送信している.でも、末尾の00H送信は変わらず.こりゃ使えない.

結論: SPIはなんか嫌だなぁ.これじゃぁ後段のFPGAの処理がめんどくさくなってまう.

別のIFを試してみることにする.

解決追記 コメ欄にあるとおり、末尾の00Hはstringの末尾の00Hをsizeof()がカウントしているからでした.コメントさんに感謝.これならSPIでOKじゃね?

かしこ

2020年4月29日水曜日

戒厳令日記(22日目)ZOOMの背景

ボチッ、シャー、、、「しまったビデだ」   ←自粛してるとこうゆうことが起こる

奥さんは毎日ZOOMをやっている.わたしには誰からもZOOMのお声がかからない.communicationはTEXT onlyだ.わたしがZOOMをやる場合は右のキール・ローレンツ・ヒラサカ議長のTEXT ONLYをアバターとして使うこととしよう.ちゃんとボカシ入れて作ったんよ.

ところで在宅勤務の皆さんはZOOMの背景に家の様子が映ってしまうのが恥ずかしいらしい.その気持ちはわかる.


もしもわたしがZOOMをやったらこんなものが映ることになる.
↓まずは正面はこんなかんじ.(画質は落としてありんす)
↓背景はこんなかんじ.(画質は落としてありんす)
 ↓映ってしまって恥ずかしいのはこれかな? エロ漫画とドメカノが背景に映り込んでしまう恐怖.(画質は落としてありんす)

【戒厳令日記(22日目)】

昨夜21時      夕食、豚肉とキムチともやしと豆苗の炒め、焼売、ほや、ご飯

昨夜1時      就寝

11:00        起床

12:00        昼食、カレーライス

                ずーっとひっきー、アニメ、STM32

20:00      夕食、ブリ照り焼き、鶏肉煮物、山芋、わかめサラダ、ご飯


本日会話した人:   おくさん

本日の外出距離:   0m

本日のキャッシュアウト:    ¥0

かしこ

STM32でDCCを作る方向で (6) 仕様調査中

【バスについて】
ソニーにいた頃、LSI設計チームの人々がAHBだのAPBだのバスアービタだのとごちょごちょとやっていたけれど、system回路設計者じゃなくて信号処理回路者だったわたしにはAHBなんかご縁が無かった.

STM32をいじるとなると、ARM CPUなのでどうしてもAHBやAPBが絡んでくる.疎いんだよねぇ、そっち方面については.

AXIというバス規格も名前ぐらいは知っていた.XILINXによるローカルなバス規格なのかと思っていたのだけどそうじゃなく、AXIもARMのバス規格なんだね.知らないのよ、そっち方面については.

まぁ使えりゃなんでもいいや...

【sample code】
STM32 DCCの開発に役立つsample codeがあると便利だ.
探してみたら、USB audio class 2.0のsampleがあることがわかった.
うまうまとDLしてみて、う~んと唸ってしまった.
targetが、STM32446E-EVAL と 32F769IDISCOVERY なのである.STM32F769はあまりにもHighEnd過ぎて最初から相手にする気が無い.STM32F466ならアリかもしれない.

本当はお値段が安いSTM32F205をtargetにしたいんだけどな.F466は少しお値段が高い.中華通販で、F205は最安¥257、F466は最安¥500 ぐらい.両者にはCPUがCoretex-M3とM4の違いがある.

リンク先のsampleには、F4xx系CPUとF7xx系CPU専用のUSB libraryが入っているのだけれど、それらはF2xx系CPUには対応していない.
かすかな希望を抱きつつ、F2xx系とF4xx系のUSB registerをdatasheetで比較してみる.ベース設計は同じはずなので似てはいるが、半分同じ、半分違うといった具合.F4xx系libraryをF2xxに流用するのはあきらめるしかなさそうだ.

targetをSTM32F446に変更しようかと悩む.

【出力、DMA】
PCM streamをSTM32から外部へ出力する必要がある.いちいちCPUで出力する気はないのでDMAを使う.

最も簡単な経路は、USB FIFO → DMA → 8bitのGPIO なのだが、GPIOはDMAのdestinationに出来ないんだ.がっかり.

何か別のperipheralで外部出力しなくちゃいけない.候補はI2S,I2C,SPI,SAI などがある.これらならDMAのdestinationにできる.

I2Sを使えばいいじゃんと思うだろうが、STM32のI2Sには問題がある.32bit192kHzまでしか対応しないのだ.32bit384kHzじゃないと嫌なのでI2Sはダメ.

I2Cは1Mbpsぐらいしか出ないので問題外.32bit384kだと25Mbpsぐらい必要.

QUAD-SPIはclock最大90MHzという数値がdatasheetにある.これは速いので使えそう.でもaddressを出力されるとかえってめんどくさいので嫌かも.

SAIはSerial Audio Interfaceの略である.外部クロックも使えるみたいだ.問題は外部から25MHzのclockをぶっここめるのかどうかであるが、それはダメっぽい.

帯に短し襷に長しである.
32bit384kHzを円満に出力できるかどうかを実機で確かめる必要がありそうだ.

かしこ


業務スーパーの冷凍イワシでアンチョビを作れるか?

戒厳令の今、暇な人々はパンを焼いているそうです.皆がパンを焼いているのならわたしはアンチョビ作りだ!と思ったのです.

しかしイワシの調達がほとんど無理.かたくちイワシを使うらしいのですが、築地までもとい豊洲まで買いに行くのはかったるい.

幸いなことに業務スーパーには、北欧の海で獲れた冷凍イワシ500gが売られています.¥200ぐらいと安いです.かたくちイワシではないと思うのですが、これでアンチョビを作ってみることにしました.2パック、1kg買いました.
↓魚体が小さいのでさばくのに手こずります.最初はナイフで3枚おろししてたのですが、途中から手開きに変えました.首を切る→腹びれを切る→手開き→背びれを取る という作業です.
↓さばいたもの(左)は700gぐらいあります.頭と骨とはらわた(右)は今回は捨てました.
↓軽く洗って、キッチンペーパーで水気を取ります.
↓塩とともにタッパーに並べます.
↓塩で埋めます.イワシが700gに対して、塩を350g投入しまして、ちょいと塩が多かったかも.大丈夫かな?

とりあえず今日の作業はここまでです.タッパーを冷蔵庫に入れて2か月ぐらい放置プレイです.

オリーブオイル漬け工程に移行するのは2か月後です.

業務スーパーのイワシで成功しますかどうか? 続報を待たれよ.

→その2へ (6月8日)

かしこ

2020年4月28日火曜日

戒厳令日記(21日目)今日も外出

戒厳令は延長または一部緩和で継続の予想が強まっているみたいで残念です.先ほど、郵便屋さんがアベノマスクを届けてくれました.噂通り小さくて隙間スカスカで効果少なそう.鼻の脇がスカスカなんですがねー.

さて、アニメの話題を.

アニメ「グレイプニル」面白いね.
今期のアニメでは最も今風の作風をキープした王道路線かつクオリティも上々.だがそれだけではなくて、毎回ラストシーンで「おおっ、来週どうなるんだ?」と思わせるところで終わる.首もげにはアセったぞ.優秀でよかよか.原作の絵柄とアニメのキャラは随分違うようだ.

「グレイプニル」が今期注目度1位、「波よ聞いてくれ」が2位、「球詠」は規格外注目作品ということでよろしくお願いしたい.

ところで今期アニメに占める講談社の比率が多いのにお気づきだろうか?
グレイプニル、波よ聞いてくれ、かくしごとギャルと恐竜無限の住人、これらは講談社の雑誌原作に由来する.古くは「謎の彼女X」も講談社だった.最近では「ドメスティックな彼女」も講談社.侮れない作品が多い講談社だ.でも今期の講談社の多さはすげぇよ.KADOKAWAとか集英社とか置いてきぼりじゃん.講談社って古い体質っぽくてアニメ化だのメディアミックスだのには疎い会社だなぁと思っているわたしだが、TVアニメ企画の優秀さには目を見張るものがある.
冴えない彼女の育てかた」はKADOKAWAだったが、もっともっと頑張って欲しいな.


【戒厳令日記(21日目)】

昨夜4時     就寝

12:00     起床、朝食兼昼食はカレーライス

13:00     家庭の事情で隣県までクルマで走る

14:00     目的地で用事を済ませる

15:00     隣県の業務スーパーで大量買い
池尻大橋の業務スーパーは混雑しているのでもう行く気無くした.
中目黒ライフも混んでるのでもう行く気無くした.

16:30    帰宅、隣県菌をシャワーで洗浄

現在20:00     STM32のUSBがさっぱりわからん!


本日会話した人:   奥さん、目的地で2名

本日の最長外出距離:   50kmぐらい

本日のキャッシュアウト:    食料¥10,000ぐらい買いだめ

今日は夕寝しなかったので早寝できそう.心技体が健全になれますように.

かしこ

戒厳令日記(20日目) 焼け太りの野望

本日は機密度AAA+の業務のため真相を伏せてお届けする戒厳令日記である。

国の持続化給付金という緊急制度が立ち上がるので案内ページを読んでみた。去年の帳簿と今年の帳簿の差額を貰えるが、いずれか1ヶ月分だけ。なんだよそれ。3ヶ月分を要求する!
我が家の謎のカフェもお金を貰えるのか? 営業開始がほぼ今年なので去年の実績が無くダメなようだ.焼け太りの野望は潰えた。疫病のせいでロケットスタートが阻害されているのは事実なのだがなぁ。


【戒厳令日記(20日目)】
昨夜2時      就寝

11:00     起床

12:00     朝食兼昼食

17:00〜     XXXX

24:00     帰宅、菌をシャワーで洗浄する

本日会話した人:   奥さん、XXXX

本日の最長外出距離:     10km?

本日のキャッシュアウト:     ¥XXXX

かしこ

2020年4月27日月曜日

STM32でDCCを作る方向で (5) NUCLEO-F207ZGのUSB HighSpeed modeがdisableである事の回避方法

今回はメチャメチャ重箱の隅の話題である.誰得にもほどがあろうというくらい重箱の隅だ.

2日ぐらい悩んでいた.

INDEXページへ

【やりたいこと】
NUCLEO-F207ZG をtargetとしてDCCを開発したい.
DCCにはUSB HighSpeed mode(480Mbps)が必要である.
しかし、NUCLEO-F207に載っているCPU STM32F207ZGにはHSのPhyが内蔵されていないので、HSのPhyを外付けせにゃいかん.

【問題】
いつも通りSTM32CubeMXでcodeの雛形を生成させる.
その際のtargetは2つ考えられる.
1)NUCLEO-F207ZG をtargetにする方法.これは便利である.なぜならNUCLEO基板の周辺回路のsettingを自動でやってくれるからだ.STLINKの対応も自動でやってくれる.
2)CPU STM32F207ZG単品の剥き出し状態をtargetにする方法.これはやりたくない.せっかくNUCLEO基板を使うのだからスクラッチでperipheralの設定なんかしたくない.

というわけで、targetをNUCLEOにするのは必須ともいえる状況.

しかーし、問題があるのだ.NUCLEO targetを振り出しにすると、このようにUSB HS modeを選択する画面がdisableなのである.HSに設定できないのである.これが問題.(CPU剥き出しなら無問題よ)

赤い部分は「External Phy」「internal FS Phy」と書かれている.意味が通じにくいと思われるのだが、External Phyとは「外付けHS用Phyを使うかどうか」の意味であり、これがdisable固定になっているので結果としてHSが使えない.またinternal FS Phyとは、「CPU内蔵FullSpeed Phyは在るけれどどうする?」の意味であり、これがdisable固定になっていて結果としてUSB IF自体が使えなくなっている.まったくつかえねー

【回避策】
xxx.icoファイルを直接編集などして回避策が徐々にわかってきた.
わかってしまえば回避策は単純なものだった.

まず理解すべき点は、USB HS modeにするべく外部Phy enableにした時点で、固定的に割り当てられるpinがある.これが固定割り当てpinの一覧.外部PhyとのIFは8bit data+制御線なのでこれだけのpinを占有するのである.
ところが、NUCLEO基板では、これらのうち赤丸をつけた2pinが別の用途に割り当てられている.その2pinの別割り当てのせいで、USB HS modeがdisableにされてしまっていたのである.PB0はLED(LD1)のピン、PB13はEthernetのピンに割り当てられている.ゆえに、その2pinを開放してやればいい、これが回避策だ.
←PB0=LED(LD1)に割り当て
←PB13=Ethernetに割り当て
なお、これらの別割り当てpinをクリアする方法は、例えばPB13についてはEthernetをdisableにすれば一蓮托生で割り当てクリアされると思うのが普通であろう.だがそれだとクリアされないっぽいので注意が必要だ.このように明示的にpinを「reset state」にブチこまなくちゃいけないというのがわたしの経験から知り得た法則だっ.

STM32CubeMXで開放してやるだけでなく、hardware的に配線切断せにゃいかんのは言うまでもない.回路図ではどうなっているのか?
PB0=LD1については、何故かLEDなんかに接続されていない.謎だ.MXの軽いbugか?
PB13については、JP7で切断できるようになっている模様.

【結果】
はーい、HSを選択できるようになりました.

めでたしめでたし.オレの貴重な約2日を返してくれ.

かしこ

2020年4月26日日曜日

戒厳令日記(19日目)

昨日の戒厳令日記のコメ欄に寄せられた情報に「7日移動平均線を表示するとご新規さん減少傾向がくっきり」というのがある.減ってるじゃん.ついては5月6日の戒厳令解除をよろしくお願いしたい.専門家さんは反対なさるでしょうけど.官邸は専門家さんの言いなりでしょうけど.
http://kabumatome.doorblog.jp/archives/65961758.html

もうひとつ、昨日のコメ欄から転記しておく.昭和10年代、日本が戦争と敗戦へ転がってゆく様と現状が似ていると思う.わたしが専門家や官邸や自粛厨を批判し続ける理由はこの類似から発している.財務省も追加したいが巧い喩えを思いつかん.
         現在               →       昭和10年代
  医学系専門家会議      → 旧陸軍=予算厨
  医学系専門家会議      → 旧海軍=予算厨
  官邸                         → 軍の言いなり、政治判断無し、大本営発表、国民騙し
  マスコミ                   → 自粛煽り、非国民煽り、鬼畜米英煽り
  飲食店                      → 徴兵され、ガダルカナル島で補給無しで餓死
  国民                         → 欲しがりません勝つまではと自粛厨、非国民ガーと発狂
  小池都知事                → 近衛文麿、人気取り政策に邁進
  強制なし補償なし       → 戦力の逐次投入
これぞ日本国の伝統に裏打ちされたフルパワーだっ! あんたバカァ? 集団ヒステリー?


【戒厳令日記(19日目)】
今日は戒厳令開始以来最弱の一日であった.生活パターンが、午前中寝る、夕方寝る、昼食のみ に収斂しつつある.引き籠り貧乏老人の生活ってこんななんだろうなぁ.

昨夜2時      就寝

11:30      起きたらこんなお時間

12:00      麻婆豆腐、揚げ物、ごはん

~16:00     アニメ、STM32

16:00       睡魔に襲われる

19:00      目覚める


本日会話した人:  おくさん

本日の外出距離:    0m

本日のキャッシュアウト:   ¥0

かしこ

Aliexpressに注文中の品々をご紹介

いち早く疫病から立ち直ったとご主張なさる中華様.次はバッタの被害をいち早く克服なされよ.

今回はAliexpressについて.

旧正月の時期はAliexpressへの注文を避けるようにしている.莫大な注文が殺到して行方不明になりそうだからだ.飽くまでもわたしの主観なので実際に旧正月に配送ミスが多発するのかどうかは知らない.

疫病を克服したと主張なさるこの頃、Aliexpressへの注文数が増えているわたしだ.

今回は注文中の品々を紹介しよう.お値段は送料込み価格.

↓PCM5102が載ったDAC基板.¥320
↓STM32F205      USBを使えるCPU     2ヶで¥550ぐらい
↓USB3300      USBのPhy      7ヶで¥500ぐらい
↓USB3300基板        ¥741
↓EZ-USB基板       ¥381
↓キーボードの隙間まで掃除するスライム      ¥151     ←これ使えるの?
↓Arduino Nano       2ヶ¥430
↓100V-200V昇圧トランス     ¥283
真面目な品々ばかりでしょ?

スライムがちゃんと使えるのかどうか興味深い.キーボードの裏側に引っかかって取り出せなくなるのではないだろうか?

これらのうちどれだけが届くであろうか?

かしこ

2020年4月25日土曜日

STM32でDCCを作る方向で (5) NUCLEO-F207ZG 到着

待ちわびた、というほどでもないけれど、USBが載ったNUCLEO-F207ZGがマルツ通販で届いた.

これまで使ってきたNUCLEO-F401REにはUSBが無かったのでDCC開発のためには使い物にならなかった.

↓2つを並べてみる.左のがUSBつきのもの.一言、デカイ.ST-LINK部分を除くとCPU本体部分はほぼ2倍サイズだ.

このデカイ奴でDCC開発に着手できると思ったら甘い!
前回書いたように、デカイ基板のCPUのPhyがFullSpeed(12Mbps)対応のみであってHighSpeed(480MHz)には非対応だからだ.外付けでHS用Phyを取り付けなくちゃいけないのである.

↓Aliexpressに注文したPhyはこのようなものである.¥800ぐらい.早く来ないかなぁ.
↓IC単品で調達することもできるので、IC単品も注文してある.自作プリント基板も注文してある.

プリント基板は来週に来るだろうが、AliexpressのPhyは30~50日待つ必要アリー.
そんなに待てんぞ.

かしこ


戒厳令日記(18日目) バイオハザード

土曜だというのに在宅勤務中の皆様こんばんは.お仕事捗ってますかー?
本日の平坂調査隊は、イタ飯屋というバイオハザードへの潜入探査を敢行しました!

本日の自粛厨: 外に客が見えたので営業しているっぽい小さな喫茶店へ行った.店の入り口で、takeoutあるいはバルコニーのみの営業になっていますと説明を受ける.バルコニーでお願いしますと言う.次にマスクはお持ちですか?と訊かれる.その時わたしはマスクをしていなかったのでイイエ、と答えるとご入店できませんという.アホくさいので露骨に嫌な顔をして店を後にした.店員が追いかけてきてマスクをご提供できますと言うが無視して去った.
アホくさいとはどういうことかというと、、、店の入り口でtakeだのバルコニーだのと喋るのに要した時間は数分.それに比べて、バルコニーへ出る距離はたったの数m.そんなの5秒で通過できるって.今でもマスクって潤沢に流通しているわけじゃないでしょ? 小さな店内のたかが数mの通過だけに入手難のマスクを配布したり受け取ったりするのって愚かじゃん.
もちろん従業員規則としてならマスク常用は妥当と思われる.だが小さな店内を数m横切るだけの客相手に適用するのはただのマスターベーションとしか評しようが無い.それだけではない、マスクを外さずにコーヒーを飲めとでも言うのか? 少しは考えろ自粛厨.あの喫茶店にはもう行かないだろう.

多くの自粛厨もこれを読むはずだ.今日のヒラサカがどうしてマスクをしなかったのかを説明しておこう.電車移動や食品スーパーを訪れる日はマスク+携帯アルコールで厳重警戒なわたしだ.しかし今日はイタ飯屋というバイオハザードで1~2時間を過ごす.その間はマスクなんかするわけがない.店内で感染しちまったら素直に死のうという達観である.食の醍醐味は常に危険と背中合わせなのだよ.イタ飯屋は満席だった.あははー


【戒厳令日記(18日目)】

昨夜21:00     レトルトカレー焼き肉あいがけ

~04:00     プリント基板設計をしてて夜更かし

11:00      しまったこんな時刻だ、で起床

~13:00      書留の再配達を待ち続ける (腹減ったよぅ)

13:30      奥さんのお誕生日なのでイタ飯屋というバイオハザードへ.マトモな飯食ったの1ヶ月ぶりかと感涙にむせぶわたくしたち.

15:00     冒頭でdisった自粛厨な喫茶店

16:00     帰宅、中目黒菌をシャワーで洗浄する、睡魔に襲われる

19:00     目覚める


本日会話した人: 奥さん、バイオハザードのホールさん、自粛厨な喫茶店の人

本日の最長外出距離: 500m

本日のキャッシュアウト: バイオハザードランチ¥7140

かしこ

2020年4月24日金曜日

戒厳令日記(17日目)

もう17日目か、、、皆さんこんばんは.「自粛中から国民を守る党」のヒラサカです.

自粛のストレスは人により様々であろう.わたしにとって引き籠り生活は自分の生活様式そのものなので引き籠っていても何も不自由を感じずに生活できる.ジョギングとかしないし.人と会話しなくても平気だし.回路を作りアニメを観ていられれば満足だ.

ただしストレスは2つあるかな.
1)TVが非国民煽りに熱心で吐きそう
例えば昨日のTVにおける非国民糾弾大会はジョギングだった.今日は非国民にならないための食品スーパー活用方法指南だった.お前らバカもいい加減にしろ.
2)yahoo newsの自粛厨がうざい
yahoo記事をスクロールダウンすると自粛厨が自粛厨のモラル視点でグダグダグダグダ臭い事書いてるのよ.最近悟った.朝日新聞の読者投稿の方がまだマシだって.

なるべく見ないようにしてるんだけど、目に入っちゃうんだよ.タスケテー、ストレスー

ところでNY州(1950万人)で抗体保持者=完全体が14%も居たそうでおめでとうございます.273万人が完全体となった.病死は12,000人ぐらいいるかな.死亡率=0.44%になった感じ.東京の完全体比率はどのくらいかしらね.


【戒厳令日記(17日目)】

昨夜4時     回路設計で夜更かし、就寝

11:00       起きたらこんな時刻だったといういつものパターン

12:00       冷凍ハンバーグ、冷凍鮭、生卵、ごはん

13:00       業務スーパー、ライフへ(池尻大橋店)
ここ数日間は買い置き品、冷凍品、レトルトで食いつないできたが、食料がだいぶ少なくなってきたので数日ぶりに買い出しへ.
業務スーパーは店内をぐるっと廻るようにレジ待ちの行列で買う気なくした.
ライフの混雑はフツーだった.ババアが、積まれたキュウリを一本一本ベタベタと触って曲がりの少ないキュウリを選別していた.ババアがベタベタ触ったキュウリなんか買いたくないし食いたくないわ、きもい.(嫌いなので食わんけど)

~17:00     プリント基板4枚をJLCPCBに発注

17:30     睡魔が襲ってきたのでベッドへ行ったら、奥さんも寝ていた

19:30     目覚める


本日会話した人      奥さん

本日の最長外出距離       2km?  池尻大橋まで

本日のキャッシュアウト        ライフで¥3000ぐらい
                                            JLCPCBに$33.5

かしこ

2020年4月23日木曜日

戒厳令日記(16日目)

ほとんど読まないけれど、タイトルだけさらっと見るyahoo news.

「経済を殺してでもやるほど自粛は尊いのか?」という真っ当な記事が今週あたりから出始めた事を喜ばしく思う.5月6日に戒厳令解除できそうにない予感と、その先に襲い掛かる大倒産への恐怖を織り込んで、「病死も大倒産も防がなければ」と心配する賢明な人々が少しづつ増え始めている兆候だろう.

その考え方に従うならば「飲食店に行くな、だが休業補償はしない」と言った3月末の小池会見は無茶苦茶だ、となる.だからわたしはあの時から小池しね、と言い続けている.ホリエモンがいつもの炎上商法Twitterで「小池都知事は自粛厨の言いなり」とつぶやいているのには笑った.こいつも自粛厨いうてる.あははー

一方で自粛厨は益々勢いを増している.それもそのはず、大本営が自粛厨煽りをしているのだから、自粛厨は国家公認で暴走できる.せいぜい我を忘れて今を愉しみたまえ.そう遠くないうちに自粛自粛いうてる君達自身が大本営によって経済的に殺されるであろう.

「経済なんかいくら殺しても構わない」と暴走する多勢の自粛厨と、「病死も経済死も防がなければ」と焦る者の比率はどこかで逆転するだろうけど、それは1ヶ月先とかではないな.
いまの大本営のやり方だと、ワクチン接種が完了するまで自粛厨優位は続く.それは2年先か? 経済死ぬで.
『罹ってもアビガンでだいたい死なずに済みます.今月の集団免疫率は5%増えて25%になりました』、、、大本営がそっちへ方針転換する時が、自粛厨が下火に向かう時だ.

陰謀論的にいうと、我々は疫病に乗じたサヨクによる敗戦革命工作を喰らっていると疑った方がいい.小池都知事には、お前は近衛文麿の生まれ変わりかといいたいぞ.「自粛厨の言いなり」で人気が高まるところも近衛文麿みたいだ.

刮目して状況を見よ.


【戒厳令日記(16日目)】
昨夜21時~       プリント基板アートワーク

昨夜2時AM       就寝

11:00      毎度の起きたらこんな時間だった状態

12:00     カーナピーナへカレーを買いに行く.祐天寺のKFCでオリジナルチキン3Pを買う.カーナピーナはtakeout営業のみであるが、takeoutのお客でそれなりに混んでいた.

13:30     プリント基板アートワーク.STM32 DCCの準備である.
とりあえず2品作った.今夜中にもう一品作りたいとこ.

21:00     夕飯    カレー、ハンバーグ、納豆、ごはん


本日会話した人    奥さん、カナピーのマスターと奥さん、KFCの店員

本日の最長外出距離      2kmぐらい、バイクにて

本日のキャッシュアウト      カナピカレーLLサイズ¥1440、KFC3P¥750

かしこ

STM32でDCCを作る方向で (4) HSはPhyが外付けになります

告知です.
コミケ99にて当社のDDC/DACを頒布いたします.
  日付   2021年12月31日(金) 東地区 テ-40b  東5ホール
  サークル名    bangflat
コミケにお越しの際はお立ち寄りいただけますとありがたいです.
商品紹介ページを作りました.

ーーーー
STM32のIDEは使いやすくていい感じかもしれない.pripheralの知識をロクすっぽ知らなくても、レジスタ表と首っ引きでcodingしなくても、なんとなく動かせてしまうようになっている.組み込みマイコンのprogrammingでそれはとても有難い.

なのであるが、STM32 CPU本体と、開発ボードであるところのNUCLEOには「あっそうなんですか、そうですかそうですか、とほほのほ」と愚痴の一つや二つも言いたくなるようなところがあるんだ.

それはDCCに必須のUSBに関する失望である.

USBには低速~高速まである
  USB1.0    1.5Mbps
  USB1.0    12Mbps    のろくてだめ
  USB2.0    480Mbps     DCCに適する
  USB3.0    3Gbpsぐらい     そんなには不要
なのでUSB2.0の性能をSTM32に求める.

STM32のラインナップを読んで、480Mbpsを出せるSTM32を探すと、STM32F2xx、STM32F7xx、STM32H7xx といったところ.F7xxとH7xxは高機能でパッケージも最低でも256pinとかでお値段もそれなりに高価である.自動的にF2xxを使おうということになる.(訂正:STM32F4xxにも480Mbpsがある)
それで、STM32F207が載ったNUCLEOをtargetにして、STM32CubeMXでUSBのprogrammingを始めようとしたのさ.

ところが、STM32CubeMXがどういうわけか、USB 480Mbps(HS)をセレクトできないのである.選択肢が12Mbps(FS)に固定されているのだ.なんでだろ? (480MbpsをHigh Speed(HS)、12MbpsをFull Speed(FS)とUSB規格では呼ぶ)

おかしいなぁと思いつつ、単独のSTM32F207をtargetにしてSYM32CubeMXを動かすと、HSの選択肢が出てくる.

これの原因がわかった.
 ・NUCLEOでHSはプリント基板的に非対応なのでHSを選択不能
 ・CPU 単品でなら、HSへの対応が可能
ということなのだが、これには悲しい事情がある.
STM32はHighEnd CPUに至るまで全てにおいて、
HSで動かしたければPhyは外付けなんだよ
おいおいおい、STMさん落胆させてくれるじゃないか....

EZ-USBなんかあんなチープなICなのにPhyは内蔵されてるよ.
♪またひとつ、EZ-USBが偉く思えてきた~♪
(ちなみに、CypressはInfineonに身売りしました)

ここでPhyとは何かを解説する.わたしは「ファイ」と読むけどあってるのかな?
バスを流れる信号は通常のdigital信号ではなく、高周波アナログ差動伝送信号である.そのdigi-ana変換をする専用ICをPhyと呼ぶのだ.小さなICだ.

USB HS PhyぐらいSTM32なら内蔵していると思ってたんだけどな.

だって、競合製品のNXPのLPC5500にはPhyが内蔵されているんだよ.
♪またひとつ、NXPが偉く思えてきた~♪

仕方がないのでPhyにはMicro Chip社のUSB3300を使うつもりだけど、部品が増えるのってめんどくさいんだよね.データを8本も配線しなくちゃいけないしさ.

結論は、、、NUCLEOでSTM32F207のHSを選択できない理由はPhyがNUCLEOには搭載されていないため、target=NUCLEOにした時点でHSが選択できなくなっているのであった.

かしこ


2020年4月22日水曜日

戒厳令日記(15日目)

皆さんこんばんは、「自粛厨から国民を守る党」の平坂久門です.
「自粛厨をぶっこわーす」

↑えへへ、いつかやると思ってたでしょ?


【戒厳令日記(15日目)】

昨夜2時      就寝

12:30      起きたらこんな時間だった

13:00      ノムネンのお弁当を買いにいく、鶏唐揚げ弁当

14:00      エヴァンゲリオンの序・破・Qのyoutube公開版を観る
やっぱ「破」の後半20分はとても面白い.
それに比較すると「Q」は面白いとは言い難い.旧エバの心理学と旧約聖書からの引用という軸から外れたいのはわかるが、新しい軸を設定するのには成功していない.だからやりたい事がわからないし、派手な映像だけの作品に思えてしまう.

20:00     夕食    エビチリ、塩サバ、サラダ、お味噌汁、ごはん


本日会話した人     奥さん、ノムネンの店員

本日の最長外出距離     100m

本日のキャッシュアウト     お弁当¥680、電子パーツ¥1700(Aliexpress)

かしこ

2020年4月21日火曜日

戒厳令日記(14日目)

「明日の自粛厨を創る会」に誘われたんだけど、下記のように全然自粛してないので丁重にお断りしました.

【戒厳令日記(14日目)】
今日は忙しかったのだけど記憶が薄れているのはどういうわけだ...

昨夜24時     就寝

07:00     起床、朝食  チキンライス、シュークリーム

08:00     出動

09:00     現場着

19:00     現場から退出

20:00     帰宅、現場菌をシャワーで洗浄する

20:30     夕飯  鶏唐揚げ、フライドポテト、ごはん

21:00     故障して廃棄したオーブンレンジの代替機をインストする

22:00     こうしてブログを書いている


本日会話した人     奥さん、現場のWさん、お店のIさん、お店のお客さん

本日のキャッシュアウト      電車賃 数100円

本日の最長外出距離      10kmぐらい

かしこ

2020年4月20日月曜日

戒厳令日記(13日目)

社団法人 全日本自粛厨推進協議会総裁 は昨日付で辞任いたしました.

雨、全くやる気を失わせる.しかし老骨に鞭打って現場へ出頭となったわたしは朝からコメダ珈琲再びである.
珈琲を愉しみつつ遠い日を偲ぶ.7週に渡り新宿バルドへ通い続けた「冴えない彼女の育て方」は2019年10月〜12月であった.映画館という施設がまだ在った日々は遥か遠くになりにけり.シン・エヴァンゲリオンの劇場公開はいつになるやら不明になりにけり.

【戒厳令日記(13日目)】
昨夜23時    目黒区長選挙開票速報を見守る
想定外の高投票率でレッドチーム区長誕生かとハラハラドキドキした.投票率を押し上げたのは若者だという観測があり、票数から推測するとその多くは維新のたぶち医師へ行ったと見るわたしだ.自民党のコロナ対応の拙劣さに若者達はかなりお怒りの様だ.批判票が立憲へ行かずに第三勢力へ向かったとは、若者達はなかなかいいセンスをお持ちの様だ.

昨夜24時    就寝

07:00     起床、現場へ向かう、朝食は吉野家

08:00     コメダ珈琲

09:00     作業開始

19:00     作業終了

20:00     帰宅、現場菌をシャワーで洗浄する

20:30     夕食   ピーマン肉詰め、サラダ、お味噌汁、ごはん

夕食を摂りつつ「球詠」第3話を観る.Aパート最初の唐突な斜めカットを巻き戻してじーっと見るが特別な意味はなかった.相変わらずの規格外な作りに一体どうなっているのだ?とうならされる.野球を断念して軽音楽部に転向する展開を期待していたのだがそうはならなさそうで、全国大会を目指す展開へ.いっそ大回転魔球を取り入れてみてはいかがだろうか?

本日会話した人    奥さん、現場の2名、不動産屋さん1名、吉野家の店員さん、コンビニの店員さん

本日の最長外出距離     10km?

本日のキャッシュアウト      電車賃、コメダ珈琲、お茶      ¥1000ぐらい
                                    NUCLEO基板 ¥3200
                                    オーブンレンジ   ¥10.8万 (故障したため)

かしこ

2020年4月19日日曜日

本日、目黒区長選挙、結果を予想してみるなり

本日、2020.4.19は目黒区長選挙です.

これを書いているのは、4月19日 AM2時です.

選挙結果を予想してみます.
  青木     自公推薦          27000票
  山本     立憲共産推薦    20000票
  たぶち  維新                   5000票

  投票率21.7%

いくつかの前提・予想を込めています.

1)過去数回の結果から、青木は3万票、野党は2万票 である.

2)投票率は意外に下がらなくて20%を切るようなことにはならない.期日前投票が盛況だったため、考えを変えました.

3)青木は票を減らしはするものの、維新候補が出馬した時点で青木批判票が山本とたぶちに分散し、結果的に青木の勝利は確実になった.それでも山本は上玉候補なだけに善戦する.

4)青木信任票:青木否認票 = 27000:25000  と考えると接戦と見られる.

#維新の支持基盤ってなんだんだろう? 完全浮動票狙いってことはないと思うんだけど、どうなんだろう?

ーーーーー
結果は以下に追記します.当たりますように.

21:10    なんと、最終的投票率が33.3%にもなっている.爆上げ!
目黒民、いったいどうしたんだ? 何が起きたんだ? 若者の投票率爆上げらしい.

わたしは立憲共産推薦の区長なんか嫌なので山本落選を願うが、青木も5期目に立候補するかね?お前は権力亡者か?と思うのでそんなに青木を有難がってはいない.でも立憲なんかが当選するのはゴメンなので青木に投票しといた.

21:43    最初の速報来た!   候補者3人とも2500票で並んでいる.

22:08    まだ3人とも並んでいる.8500票.この段階では、維新にマトモに票が入っているのに驚くわたしだ.

22:36     山本21,000/たぶち18,000/青木21,000   開票率 78.41パーセント
これは、、、78%開票でまだ勝負がつかない.山本区長誕生の可能性がまだある.
この状況は、現職青木にとっては負けに等しいと思う.もしもたぶちが立候補してなかったとしたら、山本がぶっちぎりで勝利だったじゃん.

23:00の速報で最終結果が出るだろう.
未開票は16,500ぐらいなはずなので、青木がいつもどおり30,000票獲れれば勝ちだが、もしも27,000しか取れなかったら負けそう.

23:17     青木当選!     青木30,178/山本26,908/たぶち18,588
しかし、自公の集票マシンというものは正確に3万票を叩き出すもんだねぇ.
青木はたぶちに救われたな.
そして、山本の上玉候補っぷりには頭が下がる.
たぶちは善戦した.

4年後にはもう青木が当選する力は残ってないと思うので、山本区長が誕生してしまうかもしれないな.

かしこ

戒厳令日記(12日目)

悪夢で目覚めた.

都立大学マンガ研究会の面子で麻雀打っている.
わたしはリーチをかけたのだ、25待ちで.
34555・・・・・・六六
ところが対面が切った2を見逃してしまう.その後2が連続して切られて内心寒々としてたところで、あれっ六も待ちじゃんと気づいたのだが、六は自分がツモ切りしていた.もはやカラ聴、、、そこで目覚めた.地獄のような夢だった.

麻雀夢の原因は、昼間に麻雀ライブを見てたのが原因と思われる.声優の小山剛志がプロに混じって打ってた.


【戒厳令日記(12日目)】

昨夜20:00     焼塩サバ+お味噌汁+ごはん で夕食

昨夜04:00     就寝

11:00     悪夢で目覚める

12:00     目黒区選挙投票率をチェック、なんと投票率がいつもより高い

13:00     ツナサンド+玉子サンド を朝食兼昼食にする

14:00     明日の現場で仕様変更があり、¥150ほどのプラスチック部品を買うためだけに国道一号方面へ走る羽目になった.

16:00     帰宅.シャワーで馬込菌を洗浄する.(千鳥菌ではない)

17:00     目黒区長選挙をチェック、なんと投票数が前回の1.5倍だよ.みんな暇!


本日会話した人       奥さん、ホームセンターのレジの人

本日の最長外出記録       5km

本日のキャッシュアウト       ¥286

かしこ

さくらトラベルさん、ありがとう (キャンセル料)

小池都知事が飲食店死ね会見をしたのと、4月1日から戒厳令だというデマが飛び交ったのは、両方とも3月30日か31日でしたかね?

小池の会見を見て、あぁこれは政府が押される形で戒厳令になるな、もう止まらないなと、思った.

実際の戒厳令は4月8日からだったかな? 一日ぐらい不正確かもだがさておく.

その後、戒厳令が全国に拡大されたのが4月16日.あちゃーっ、5月6日に戒厳令を解く目途が立たないと政府は考えてるな、と思った.経済への悪影響は計り知れない.

-----
石田純一がコロナに罹って、沖縄旅行中から具合が悪かったらしい.感染したのは東京であろう.実はわたしも、4月21日から沖縄に行く予定だったのだ.予約したのは3月頭だった.

だがしかし、小池会見やら戒厳令デマを見て3月31日に沖縄旅行をキャンセルした.

キャンセル料金はどうだったか?
沖縄のホテルのキャンセル料は3weeks前だったこともあったためか無料だった.

ところが、さくらトラベルを通じて予約したスカイマークの飛行機切符のキャンセル代は、お客様都合キャンセルということで、片道一名¥6500だった.切符が¥1万なのでキャンセル料が65%ということになった.随分と高額だと思った.しかも3weeks前キャンセルなのにね.
それでも戒厳令は鉄板だと考えたヒラサカは、キャンセルしてくださいとさくらトラベルに申告した.

以上が3月31日の状況だった.

その後、4月6日頃のことだったと思う.スカイマークからわたしに直接電話が入った.お客様がご予約された便は欠航しますので、払い戻ししますので、さくらトラベルさんに返金を依頼してくださいという連絡だった.

あぁそうなの??? 意外な展開.

キャンセル手続きで多忙のさくらトラベルさんは、ヒラサカからのキャンセル依頼を3月31日に受けたものの、4月6日の時点でスカイマークに連絡してなかったようなのだ.
なので、スカイマークは、航空会社都合によるキャンセルをしますとヒラサカに告げてきた.だとすると、さくらトラベル提示のキャンセル料¥6500x往復x2名=¥26,000が大幅に減額されると期待される.

なので、ダメもとで、さくらトラベルに以下のメールを打ってみたんだ.

お世話になっております.解約手数料の減額についての問い合わせです.

本日、スカイマーク航空から電話をいただきました.要件は3つでした.
1)航空会社都合の欠航になります.(お客様都合の解約ではない)
2)往復2便が欠航になり、返金いたします.
3)旅行会社から払い戻しを受けてください.(旅行会社への手数料がかかります)

つきましては、さくらトラベルさんへお願いがございます.

さくらトラベルさんからご提示いただいた解約手数料は、「お客様都合解約の金額」でした.¥6500x4=¥26000

ところがこの度、状況が覆りまして、、、さくらトラベルさん~スカイマークへの解約宣言の日程ズレのためと思われますが、「航空会社都合による欠航」に切り替わった様子です.恐らく、解約手数料は¥26000よりも少なくなるのでしょう.

ついては、さくらトラベルさんへの解約手数料を差し引いていただき、変更後の残金の返却を希望しますので、ご案内の方よろしくお願い申し上げます.

コロナで多忙を極めていらっしゃるかと思いますが、がんばってください!

それでは!

まぁなんつうか、一応は聞いてみましょうということで、期待はしてなかったけど....

そうしたら、数日後にさくらトラベルから返信があり、全額返金の手続きを致しますとのことであった.ええっ、多少の手数料を引いてくださいっていいんですよ.全額返金まで求めてませんから.

いま旅行会社はキャンセル手続きという後ろ向きの業務で大変だと思うのですが、誠意あるご対応に感謝します.   >   さくらトラベル殿

#聞かなかったどうなってたのかな? お金は誰の懐に落ちたのかwww

かしこ

2020年4月18日土曜日

EZ-USB FX2LP を動かしてみる (45) DCCの設計資料(ど長文)

撤退したEZ-USB DCCの設計資料を公開しておく.   (INDEXページはこちら

言っとくが修復不能な欠陥があってマトモには動かない.音は出るけど、数秒ごとにFIFOアンダーフローが生じてプツッとノイズが混じる. →想定原因はこちらを参照

動作確認?が済んでいる条件は、、、
・windows10
・デバドラはusbaudio2.sys
・USB audio class 2.0
・32bit 384kHz ステレオ    (他モードでは音出ししてない)
・DCCであるから、USB→I2S の変換回路である
・DACはPCM5102のI2S接続で音出ししている

それでは以下はど長文のレポートである.

なにせ途中で投げ出した設計なので、コメントがインチキだったりするのであまり信用しないでくれよな.

なお、いかなる間違いにもわたしは何の責任も負わないので素直に死んでくれ.

ーーーーーー
【全体写真】
①EZ-USB
②8bit audio data → I2S 変換 FPGA
③DAC PCM5102
④USB setup request表示器 Arduino

①と②の関係.
EZ-USBに積まれた音声データは、FPGAに読みだしてもらう必要がある.FPGAがmaster clockを発生させるからだ.音声データは8bitで伝送する.
ゆえにEZ-USBがhostから指示されたbit情報やサンプリング周波数情報をFPGAへ渡してやる必要がある.そのための配線がごちゃっとある.

②と③の関係.
FPGAが音声データをI2Sに変換してDACへ音声データを供給する.

①と④の関係.
hostからのsetup requestをモニタするためにarduinoを設けてある.EZ-USBはI2Cでsetupdataを出力する.それを受けたArduinoはsetupdataを解析してCOM portへ文字出力する.

ソースコードは3つの部分から成る.
①EZ-USB firmware      開発環境はKeil uVision4
②XILINX Spartan6       開発環境はISE13    verilog
④Arduino nano            開発環境はArduinoIDE

以下では、①②④のsource codeを解説する.


【①EZ-USB firmware】
source fileの構成はこのようになっている.こちらのフォルダにヒラサカが追記したファイルを入れておく.赤線のファイルについて以下で触れる.

【USB descriptor      dscr.a51】
まずはdevice descriptorから.
VID/PIDはゼロにしてある.そんなので動くの?と思われるかもしれないが、動いている.動く理由は、windowsのUAC2.0 driverにはVID/PIDに紐づけされた部分が無いらしいのだ.その代わり、UAC2.0 classでぇす、というUSB deviceからの申告に素直に対応するみたいよ.
;    --------- Device Descriptor ------------
;bLength                  : 0x12 (18 bytes)
;bDescriptorType          : 0x01 (Device Descriptor)
;bcdUSB                   : 0x200 (USB Version 2.00)
;bDeviceClass             : 0xEF (Miscellaneous)
;bDeviceSubClass          : 0x02
;bDeviceProtocol          : 0x01 (IAD - Interface Association Descriptor)
;bMaxPacketSize0          : 0x40 (64 bytes)
;idVendor                 : 0x0000
;idProduct                : 0x0000
;bcdDevice                : 0x0208
;iManufacturer            : 0x01 (String Descriptor 1)
; Language 0x0409         : "bangflat"
;iProduct                 : 0x02 (String Descriptor 2)
; Language 0x0409         : "EZ-USB DCC"
;iSerialNumber            : 0x00 (No String Descriptor)
;bNumConfigurations       : 0x01 (1 Configuration)
DeviceDscr:

次はDevice Qualifier Descriptorである.
特に言うべきことはない.
;----------------- Device Qualifier Descriptor -----------------
;bLength                  : 0x0A (10 bytes)
;bDescriptorType          : 0x06 (Device_qualifier Descriptor)
;bcdUSB                   : 0x200 (USB Version 2.00)
;bDeviceClass             : 0xEF (Miscellaneous)
;bDeviceSubClass          : 0x02
;bDeviceProtocol          : 0x01 (IAD - Interface Association Descriptor)
;bMaxPacketSize0          : 0x40 (64 Bytes)
;bNumConfigurations       : 0x01 (1 other-speed configuration)
;bReserved                : 0x00
DeviceQualDscr:

Configuration Descriptorについてはいくつか指摘しておきたい.
265bytesという巨大数値があるが、これはHOST PCがdecriptorの下の方まで一気読みを要求してくるのに対応している.
2 interfacesという文字がある.2つのinterfaceがありますと言っているのだが、1つはAudio control IFで、もう一つはAudio streaming IFだ.Audio controlはサンプリング周波数やvolumeなどの機能.Audio streamingはPCM dataを流す機能.
HighSpeedConfigDscr: という文字がある.後ろの方にはFullSpeedConfigDscr:というのがあって、HighSpeedは480Mbpsモードの意味である.FullSpeedは12Mbpsの意味である.480/12Mbpsそれぞれに独立したdescriptorが存在する.なお、32bit384kHzPCMを再生するには12Mbpsではまるで足りない.なので専ら使うのは480Mbpsである.
;    ------------------ Configuration Descriptor -------------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x02 (Configuration Descriptor)
;wTotalLength             : 0x0109 (265 bytes)
;bNumInterfaces           : 0x02 (2 Interfaces)
;bConfigurationValue      : 0x01 (Configuration 1)
;iConfiguration           : 0x00 (No String Descriptor)
;bmAttributes             : 0xC0
; D7: Reserved, set 1     : 0x01
; D6: Self Powered        : 0x01 (yes)
; D5: Remote Wakeup       : 0x00 (no)
; D4..0: Reserved, set 0  : 0x00
;MaxPower                 : 0x32 (100 mA)
HighSpeedConfigDscr:   

IADのことはよく知らない.
;        ------------------- IAD Descriptor --------------------
;bLength                  : 0x08 (8 bytes)
;bDescriptorType          : 0x0B
;bFirstInterface          : 0x00
;bInterfaceCount          : 0x02
;bFunctionClass           : 0x01 (Audio)
;bFunctionSubClass        : 0x00 (undefined)
;bFunctionProtocol        : 0x20 (AF 2.0)
;iFunction                : 0x00 (No String Descriptor)

ここからはAudio control IFである.
幾つかの機能moduleから成り、それぞれにID番号がつけられ、ID番号で結線を追えるようになっている.
記述されているのはこんなことである.
input terminalはID1であり、clockはID18から供給される.
control feature unitはID13であり、ID1から入力される.
output terminalはID7であり、ID13から入力され、clockはID18から供給される.

volume等の音質制御機能を全部殺してある.
しかしここで重要なのは、サンプリング周波数の設定である.ID18のAudio Control Clock Source UnitへめがけてHOST PCがサンプリング周波数を投げて寄こすのだ.
それ以外の機能は何も使っていない.
;        ---------------- Interface Descriptor -----------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x04 (Interface Descriptor)
;bInterfaceNumber         : 0x00
;bAlternateSetting        : 0x00
;bNumEndpoints            : 0x01 (1 Endpoint)
;bInterfaceClass          : 0x01 (Audio)
;bInterfaceSubClass       : 0x01 (Audio Control)
;bInterfaceProtocol       : 0x20 (Device Protocol Version 2.0)
;iInterface               : 0x00 (No String Descriptor)

中略

;        ----- Audio Control Input Terminal Descriptor 2.0 -----
;bLength                  : 0x11 (17 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x02 (Input Terminal 2.0)
;bTerminalID              : 0x01
;wTerminalType            : 0x0101 (USB streaming)
;bAssocTerminal           : 0x00
;bCSourceID               : 0x12 (18)
;bNrChannels              : 0x00 (0 Channels)
;bmChannelConfig          : 0x00000000 (-)
;iChannelNames            : 0x00 (No String Descriptor)
;bmControls               : 0x0040
; D1..0  : Copy Protect   : 0x00 (not present)
; D3..2  : Connector      : 0x00 (not present)
; D5..4  : Overload       : 0x00 (not present)
; D7..6  : Cluster        : 0x01 (read only)
; D9..8  : Underflow      : 0x00 (not present)
; D11..10: Overflow       : 0x00 (not present)
; D15..12: Reserved       : 0x00
;iTerminal                : 0x00 (No String Descriptor)

;        ----- Audio Control Output Terminal Descriptor 2.0 ----
;bLength                  : 0x0C (12 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x03 (Output Terminal 2.0)
;bTerminalID              : 0x07
;wTerminalType            : 0x0301 (Speaker)
;bAssocTerminal           : 0x00 (0)
;bSourceID                : 0x0D (13)
;bCSourceID               : 0x12 (18)
;iTerminal                : 0x00 (No String Descriptor)

;        ------ Audio Control Feature Unit Descriptor 2.0 ------
;bLength                  : 0x12 (18 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x06 (Feature Unit 2.0)
;bUnitID                  : 0x0D (13)
;bSourceID                : 0x01 (1)
;bmaControls[0]           : 0x00, 0x00, 0x00, 0x00  ←全部殺し
;iFeature                 : 0x00 (No String Descriptor)

;        --- Audio Control Clock Source Unit Descriptor 2.0 ----
;bLength                  : 0x08 (8 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x0A (Clock Source 2.0)
;bClockID                 : 0x12
;bmAttributes             : 0x03
; D1..0: Clock Type       : 0x03
; D2   : Sync to SOF      : 0x00
; D7..3: Reserved         : 0x00
;bmControls               : 0x07
; D1..0: Clock Frequency  : 0x03 (host programmable)
; D3..2: Clock Validity   : 0x01 (read only)
; D7..4: Reserved         : 0x00
;bAssocTerminal           : 0x00
;iClockSource             : 0x00 (No String Descriptor)

;        ----------------- Endpoint Descriptor -----------------
;bLength                  : 0x07 (7 bytes)
;bDescriptorType          : 0x05 (Endpoint Descriptor)
;bEndpointAddress         : 0x86 (Direction=IN EndpointID=6)
;bmAttributes             : 0x03 (TransferType=Interrupt)
;wMaxPacketSize           : 0x0006
; Bits 15..13             : 0x00 (reserved, must be zero)
; Bits 12..11             : 0x00 (0 additional transactions per microframe -> allows 1..1024 bytes per packet)
; Bits 10..0              : 0x06 (6 bytes per packet)
;bInterval                : 0x04 (4 ms)

ここは短く終わってしまう.interface1のalternate0である.
alternate0がどのように活用されているかというと、hardwareをsleepにするスイッチのように使われる.後述するalternate1,2,3になったら再生ONの意味である.
;        ---------------- Interface Descriptor -----------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x04 (Interface Descriptor)
;bInterfaceNumber         : 0x01
;bAlternateSetting        : 0x00
;bNumEndpoints            : 0x00 (Default Control Pipe only)
;bInterfaceClass          : 0x01 (Audio)
;bInterfaceSubClass       : 0x02 (Audio Streaming)
;bInterfaceProtocol       : 0x20 (Device Protocol Version 2.0)
;iInterface               : 0x04 (String Descriptor 4)
; Language 0x0409         : "Speaker"

以下はinterface1のalternate0である.16bitモードのPCM streamだ.
EPを2つ持っている.EP4 OUTと、EP2 INだ.
EP4 OUTはもちろんPCM streamだ.
EP2 INは何かというと、転送レート調節機能のためのfeedbackである.
EZ-USBを放棄した原因がこのfeedbackだった.EP4 OUTとEP4 INのように同じ番号じゃないとfeedbackは動かないというのがUSB規格書に書いてある.EZ-USBで同番号IN/OUTは実装できない.そのせいでfeedbackが正しく動作せず、転送レート調節機能が動作せず、FIFO emptyが生じていると考えている.

2chでFront LとFront Rであると書かれている.

16bit 4bytesと書かれているのに戸惑いがあるだろう.無駄であるが、32bit枠で16bit伝送してくれ、という要求だ.下位16bitはゼロ埋めで.理由は、I2S DACがそういう仕様だからなのだ.

400 bytes per packetという文字がある.これはEZ-USBのFIFOサイズ512bytesを超えない範囲でという意味で400にしてある.なので500でもいいんだろう.

末尾のEP82がfeedbackであり、4 bytes per packetという文字がある.これはfeedback valueが4bytesという意味である.
;        ---------------- Interface Descriptor -----------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x04 (Interface Descriptor)
;bInterfaceNumber         : 0x01
;bAlternateSetting        : 0x01
;bNumEndpoints            : 0x02 (2 Endpoints)
;bInterfaceClass          : 0x01 (Audio)
;bInterfaceSubClass       : 0x02 (Audio Streaming)
;bInterfaceProtocol       : 0x20 (Device Protocol Version 2.0)
;iInterface               : 0x00 (No String Descriptor)

;        ------ Audio Streaming Interface Descriptor 2.0 -------
;bLength                  : 0x10 (16 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x01 (AS General)
;bTerminalLink            : 0x01 (1)
;bmControls               : 0x05
; D1..0: Active Alt Settng: 0x01 (read only)
; D3..2: Valid Alt Settng : 0x01 (read only)
; D7..4: Reserved         : 0x00
;bFormatType              : 0x01 (FORMAT_TYPE_I)
;bmFormats                : 0x00000001 (PCM)
;bNrChannels              : 0x02 (2 channels)
;bmChannelConfig          : 0x00000003 (FL, FR)
;iChannelNames            : 0x00 (No String Descriptor)

;        ----- Audio Streaming Format Type Descriptor 2.0 ------
;bLength                  : 0x06 (6 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x02 (Format Type)
;bFormatType              : 0x01 (FORMAT_TYPE_I)
;bSubslotSize             : 0x04 (4 bytes)
;bBitResolution           : 0x10 (16 bits)

;        ----------------- Endpoint Descriptor -----------------
;bLength                  : 0x07 (7 bytes)
;bDescriptorType          : 0x05 (Endpoint Descriptor)
;bEndpointAddress         : 0x04 (Direction=OUT EndpointID=4)
;bmAttributes             : 0x05 (TransferType=Isochronous  SyncType=Asynchronous  EndpointType=Data)
;wMaxPacketSize           : 0x0190
; Bits 15..13             : 0x00 (reserved, must be zero)
; Bits 12..11             : 0x00 (0 additional transactions per microframe -> allows 1..1024 bytes per packet)
; Bits 10..0              : 0x190 (400 bytes per packet)
;bInterval                : 0x01 (1 ms)

;        ----------- Audio Data Endpoint Descriptor ------------
;bLength                  : 0x08 (8 bytes)
;bDescriptorType          : 0x25 (Audio Endpoint Descriptor)
;bDescriptorSubtype       : 0x01 (General)
;bmAttributes             : 0x00
;bLockDelayUnits          : 0x00
;wLockDelay               : 0x0000

;        ----------------- Endpoint Descriptor -----------------
;bLength                  : 0x07 (7 bytes)
;bDescriptorType          : 0x05 (Endpoint Descriptor)
;bEndpointAddress         : 0x82 (Direction=IN EndpointID=2)
;bmAttributes             : 0x11 (TransferType=Isochronous  SyncType=None  EndpointType=Feedback)
;wMaxPacketSize           : 0x0004
; Bits 15..13             : 0x00 (reserved, must be zero)
; Bits 12..11             : 0x00 (0 additional transactions per microframe -> allows 1..1024 bytes per packet)
; Bits 10..0              : 0x04 (4 bytes per packet)
;bInterval                : 0x04 (4 ms)

以下はinterface1のalternate2である.24bitモードだ.
16bitモードとほとんど同じである.
24bit 4bytesと指定してあるので、24bit+8bitのゼロがPCM dataとして伝送される.
;        ---------------- Interface Descriptor -----------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x04 (Interface Descriptor)
;bInterfaceNumber         : 0x01
;bAlternateSetting        : 0x02
;bNumEndpoints            : 0x02 (2 Endpoints)
;bInterfaceClass          : 0x01 (Audio)
;bInterfaceSubClass       : 0x02 (Audio Streaming)
;bInterfaceProtocol       : 0x20 (Device Protocol Version 2.0)
;iInterface               : 0x00 (No String Descriptor)

中略

;        ----- Audio Streaming Format Type Descriptor 2.0 ------
;bLength                  : 0x06 (6 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x02 (Format Type)
;bFormatType              : 0x01 (FORMAT_TYPE_I)
;bSubslotSize             : 0x04 (4 bytes)
;bBitResolution           : 0x18 (24 bits)

以下略

以下はinterface1のalternate3である.32bitモードだ.
16bitモードとほとんど同じである.
32bit 4bytesと指定してある.
;        ---------------- Interface Descriptor -----------------
;bLength                  : 0x09 (9 bytes)
;bDescriptorType          : 0x04 (Interface Descriptor)
;bInterfaceNumber         : 0x01
;bAlternateSetting        : 0x03
;bNumEndpoints            : 0x02 (2 Endpoints)
;bInterfaceClass          : 0x01 (Audio)
;bInterfaceSubClass       : 0x02 (Audio Streaming)
;bInterfaceProtocol       : 0x20 (Device Protocol Version 2.0)
;iInterface               : 0x00 (No String Descriptor)

中略

;        ----- Audio Streaming Format Type Descriptor 2.0 ------
;bLength                  : 0x06 (6 bytes)
;bDescriptorType          : 0x24 (Audio Interface Descriptor)
;bDescriptorSubtype       : 0x02 (Format Type)
;bFormatType              : 0x01 (FORMAT_TYPE_I)
;bSubslotSize             : 0x04 (4 bytes)
;bBitResolution           : 0x20 (32 bits)

以下略

HighSpeedのdescriptorはここまででおしまい.
HighSpeedConfigDscrEnd:  



FullSpeedのdescriptorがここから始まる.
FullSpeedについてはほとんどメンテナンスしてないし動作確認もしてないので説明を省く.
FullSpeedConfigDscr:
  中略
FullSpeedConfigDscrEnd:   


以下のstring descriptorはword境界に配置されないと動かない.現状はコメントアウトしてあるが、word境界をkeepするために適宜コメントを外すこともある.
// db 00H    ;; needed for word arign
// db 00H    ;; needed for word arign

string descriptorは説明を省く.
StringDscr:
    中略
StringDscrEnd:

サンプリング周波数の一覧である.Audio controlのclock source unitへのリクエストで、対応しているサンプリング周波数の一覧を要求されるのでここに記してある.
最初の2bytesは、8種類のサンプリング周波数があるという意味.
それ以降はリトルエンディアンの32bit整数である.最初の3つは数値はこうだ.
 44H, 0acH, 00H, 00H,    →0x0000ac44 = 44100Hz     MAX
 44H, 0acH, 00H, 00H,    →0x0000ac44 = 44100Hz     MIN
 00H, 000H, 00H, 00H,    →0x00000000 = 0Hz         RES
44.1kHzを示しているのはわかるが、MAX/MIN/RESとは何なのか?
MAX~MINの間をRES分解能で設定できますという意味なのだが、RESOLUTIONがゼロなので44.1kHz決め打ちになっているのである.
それ以降のサンプリング周波数はこうだ.全部合わせて8種類である.
 0x0000bb80   48kHz
 0x00015888   88.2kHz
 0x00017700   96kHz
 0x0002b110   176.4kHz
 0x0002ee00   192kHz
 0x00056220   352.8kHz
 0x0005dc00   384kHz
FsRangeDscr:
db 08H,00H,44H,acH,00H,00H,44H,acH,00H,00H,00H,00H,00H,00H,80H,bbH
db 00H,00H,80H,bbH,00H,00H,00H,00H,00H,00H,88H,58H,01H,00H,88H,58H
db 01H,00H,00H,00H,00H,00H,00H,77H,01H,00H,00H,77H,01H,00H,00H,00H
db 00H,00H,10H,b1H,02H,00H,10H,b1H,02H,00H,00H,00H,00H,00H,00H,eeH
db 02H,00H,00H,eeH,02H,00H,00H,00H,00H,00H,20H,62H,05H,00H,20H,62H
db 05H,00H,00H,00H,00H,00H,00H,dcH,05H,00H,00H,dcH,05H,00H,00H,00H
db 00H,00H
FsRangeDscrEnd:


【fw.c】
main()があるファイル.キモのところだけを抜粋.

void main(void) {
    // Initialize user device
    TD_Init();      EPの初期化

FPGAに渡すべき情報がある.16/24/32bitの切り替えと、サンプリング周波数の切り替えなどだ.PD[7:0]を使う.
OED = 0x7F; // PD7 input
IOD = 0;

LEDインジケータとしてPAを使う.
    // SOF timer flash LED IO
OEA |= 0x80; // PA7 output
OEA |= 0x08; // PA3 output
OEA |= 0x40; // PA6 output  0100_0000
PA3=1;
PA6=1;

何をやっているのかは知らない.初期化.
    EZUSB_InitI2C();  // Initialize EZ-USB I2C controller

USB系割り込みをオンにする.
USBIE |= bmSUDAV | bmSOF | bmSUTOK | bmSUSP | bmURES | bmHSGRANT;

feedbackのためSOF周期をFPGAでカウントする.FPGAはカウント完了割り込みしてくる.EZ-USBの割り込みポートはINT0.INT0のピンはPA0.negative edgeで割り込み.
// INT0, SOF measurement interrupt
   PORTACFG |= 0x01; // PA0 for INT0
  SYNCDELAY;
   TCON |= 0x01; // INT0 negative Edge triggered
  SYNCDELAY;
   EX0 = 1; // enable INT0
  SYNCDELAY;

FIFO emptyで自分自身のINT1に割り込みする.ピンはPA1.FIFO empyの個数をカウントする実験のため.
// INT1, FIFO empty interrupt
   PORTACFG |= 0x02; // PA1 for INT1
  SYNCDELAY;
   TCON |= 0x04; // INT1 negative Edge triggered
  SYNCDELAY;
   EX1 = 0; // disable INT1  あとでONにする
  SYNCDELAY;

EndPoint割り込みは全部OFF.
// EPx INTERRUPT
// EPIE[7:0]={EP8, EP6, EP4, EP2, EP1OUT, EP1IN, EP0OUT, EP0IN}
  EPIE = 0x00;
  SYNCDELAY;

EZUSB_xxxx()はCypressが作ったルーチンなので中でなにをやってるのか知らない.
    EZUSB_IRQ_ENABLE(); // Enable USB interrupt (INT2)
    EZUSB_ENABLE_RSMIRQ(); // Wake-up interrupt

最終的なinterrupt ON
    EA = 1; // Enable 8051 interrupts

main()のwhile loopここから.
   while(TRUE) 
   {
      TD_Poll();       ポーリング処理はこのルーチンで行う

SUDというのはSetUpDataのことで、setup data割り込みでGotSUD=1にされる.setup dataがhostから届いたらSetupCommand()がコールされるようになっている.
      if(GotSUD)  // GotSUD is set by ISR_Sudav()
      {
         SetupCommand();          // Implement setup command
         GotSUD = FALSE;          // Clear SETUP flag
      }

main()はここまで.


main()から飛んでくるsetup data処理ルーチン.
Cypressのsample codeをベースにしている.ただしそれは標準USBリクエストには対応しているものの、UAC2.0のリクエストには全く対応していないのでヒラサカが追記した.
Windowsのデバドラがどのようなリクエストを発行するのかをUSB protocol analyzerなどで調査して、必要な処理を追加した.
void SetupCommand(void)
{

setup dataはSETUPDAT[0]~[7]の8bytesである.この8bytesをUSB規格書から探すとどの様な処理が要求されているのかを理解することができる.
ここでは、SETUPDAT={2,1,0,0,0x86,0}となっている.意味はEP86をリセットしろだ.
// Clear feature endpoint 86
if(SETUPDAT[0]==2 && SETUPDAT[1]==1 && SETUPDAT[2]==0 && SETUPDAT[3]==0 && SETUPDAT[4]==0x86 && SETUPDAT[5]==0) {
  // RESET FIFO
  FIFORESET = 0x80;
  SYNCDELAY;
  FIFORESET = 0x86; // reset EP6
  SYNCDELAY;
  FIFORESET = 0x00;
  SYNCDELAY;
  INPKTEND = 0x86;  // ARM FIFO
  SYNCDELAY;
  INPKTEND = 0x86;
  SYNCDELAY;
}

SETUPDAT={0x21,1,0,1,0,0x12,4} これはサンプリング周波数をXXXにセットしろというリクエストである.0x12がdescriptorに記されたclock source IDを指定している.末尾の4はサンプリング周波数が4bytesの32bitの整数であるという意味になっている.4bytesはSETUPDAT[0-7]に含まれない.別に届くので明示的に読まなければならない.
// Set smpl freq
else if(SETUPDAT[0]==0x21 && SETUPDAT[1]==0x01 && SETUPDAT[2]==0 && SETUPDAT[3]==1 && SETUPDAT[4]==0 && SETUPDAT[5]==0x12 && SETUPDAT[6]==4) {
4bytesを読む.
EP0BCH = 0;
SYNCDELAY; 
EP0BCL = 0; // Clear bytecount to allow new data recieve
SYNCDELAY; 
while(EP0CS & bmEPBUSY);
4bytesを読み終わった.
32bit整数に変換してサンプリング周波数を得る.
FS = EP0BUF[0] + EP0BUF[1]*256 + EP0BUF[2]*65536 + EP0BUF[3]*16777216;
PD[4:3]にサンプリング周波数を出力する.PD[4:3]はFPGAへ配線されている.FPGAはclock分周比を切り替える.44.1kHz系はまだ実装してない.
if     (FS==48000)  { PD4=0; PD3=0; }
else if(FS==96000)  { PD4=0; PD3=1; }
else if(FS==192000) { PD4=1; PD3=0; }
else if(FS==384000) { PD4=1; PD3=1; }
サンプリング周波数が変更されたのに伴い、念のためPCM streamを扱うEP4をクリアしておく.
FIFORESET = 0x80; // activate NAK-ALL
SYNCDELAY;
EP4FIFOCFG = 0x00; //switching to manual mode
SYNCDELAY;
FIFORESET = 0x84; // Reset FIFO 4
SYNCDELAY;
OUTPKTEND = 0X84; //OUTPKTEND done twice as EP4 is double buffered by default
SYNCDELAY;
OUTPKTEND = 0X84;
SYNCDELAY;
EP4FIFOCFG = 0x10; //switching to auto mode
SYNCDELAY;
FIFORESET = 0x00; //Release NAKALL
SYNCDELAY;
}

SETUPDAT={0x21,0x0a,0,0,2,0} これはHIDをidle状態にしとけの意味である.でもdescriptorからHIDを削除しちゃったので、今ではこのリクエストは来なくなっている.それで中身は何も無い.
// Set HID IDLE
else if(SETUPDAT[0]==0x21 && SETUPDAT[1]==0x0A && SETUPDAT[2]==0 && SETUPDAT[3]==0 && SETUPDAT[4]==2 && SETUPDAT[5]==0) {}

SETUPDAT={0x80,0,0,0,0,0,2,0} get statusの意味である.何のステータスだよと思うのだが、つつがなく過ごしていますの意味をこめてゼロを返しとく.末尾の{2,0}はリトルエンディアン16bitで2を表す.返信は2bytesでという意味である.
ここで返信のやり方がわかるだろう.すなわち、EP0BUFに返信データを積む.そして返信バイト数EP0BCH/EP0BCLにセットする.あとはEZ-USBのhardwareにお任せでよい.
// GET STATUS
else if(SETUPDAT[0]==0x80 && SETUPDAT[1]==0 && SETUPDAT[2]==0 && SETUPDAT[3]==0 && SETUPDAT[4]==0 && SETUPDAT[5]==0 && SETUPDAT[6]==2 && SETUPDAT[7]==0) {
EP0BUF[0] = 0;    返信するゼロの1byte目
EP0BUF[1] = 0;    返信するゼロの2byte目
SYNCDELAY; 
EP0BCH = SETUPDAT[7];    返信バイト数上位=0
SYNCDELAY; 
EP0BCL = SETUPDAT[6];    返信バイト数下位=2
SYNCDELAY;
}

SETUPDAT={0xa1,1,0,2,0,7,6} descriptorに記載されたoutput terminal ID=7へのリクエストである.質問は、出力端子に機器が接続されているか? である.そんな質問してきて誰得なんだろうと思うのだが、このリクエストは何度も飛んでくるんだ.不思議だなぁ.末尾の6は6bytesの返信を要求されている.返信内容は、下記に示されるように2chでFrontL,FrontRだよである.
// Get TE_CONNECTOR_CONTROL of output terminal in the interface0  --> UAC2.0 5.2.5.4.2
else if(SETUPDAT[0]==0xA1 && SETUPDAT[1]==1 && SETUPDAT[2]==0 && SETUPDAT[3]==2 && SETUPDAT[4]==0 && SETUPDAT[5]==7 && SETUPDAT[6]==6) {
EP0BUF[0] = 2;  // channel number
EP0BUF[1] = 3;  // front L and front R
EP0BUF[2] = 0;
EP0BUF[3] = 0;
EP0BUF[4] = 0;
EP0BUF[5] = 0;
SYNCDELAY; 
EP0BCH = SETUPDAT[7];   返信バイト数上位=0
SYNCDELAY; 
EP0BCL = SETUPDAT[6];   返信バイト数下位=6
SYNCDELAY; 
}

SETUPDAT={0xa1,1,0,2,0,0x12,1}   clock source ID=0x12のサンプリング周波数が適切なのかどうかが問われている.1byteで返信することが求められている.TRUEを返しとく.
// Get smpl freq valid
else if(SETUPDAT[0]==0xA1 && SETUPDAT[1]==0x01 && SETUPDAT[2]==0 && SETUPDAT[3]==2 && SETUPDAT[4]==0 && SETUPDAT[5]==0x12 && SETUPDAT[6]==1) {
EP0BUF[0] = TRUE; // TRUE
EP0BUF[1] = 0x00;
SYNCDELAY; 
EP0BCH = SETUPDAT[7];   返信バイト数上位=0
SYNCDELAY; 
EP0BCL = SETUPDAT[6];   返信バイト数下位=1
SYNCDELAY; 
}

SETUPDAT={0xa1,1,0,1,0,0x12,4}  現状のサンプリング周波数を返信せよと要求されている.返信は32bit整数で.0x12はclock source IDを表す.4は返信4bytesを表す.
// Get current smpl freq
else if(SETUPDAT[0]==0xA1 && SETUPDAT[1]==0x01 && SETUPDAT[2]==0 && SETUPDAT[3]==1 && SETUPDAT[4]==0 && SETUPDAT[5]==0x12 && SETUPDAT[6]==4) {
EP0BUF[0] = FS % 256;
EP0BUF[1] = FS / 256;
EP0BUF[2] = FS / 65536;
EP0BUF[3] = FS / 16777216;
SYNCDELAY; 
EP0BCH = SETUPDAT[7];
SYNCDELAY; 
EP0BCL = SETUPDAT[6];
SYNCDELAY; 
}

SETUPDAT={0xa1,1,0,1,0,0x0d,1}    MUTEせよ要求.descriptorでmute機能を殺してしまったのでもうこのリクエストは来ないけどね.1bytes返信を求められているのでゼロを返しておく.ゼロを返すのが正しいのかどうかは知らない.
// Audio class MUTE ctl
else if(SETUPDAT[0]==0xA1 && SETUPDAT[1]==0x01 && SETUPDAT[2]==0 && SETUPDAT[3]==1 && SETUPDAT[4]==0 && SETUPDAT[5]==0x0D && SETUPDAT[6]==1) { 
EP0BUF[0]=0;
SYNCDELAY; 
EP0BCH=0;
SYNCDELAY; 
EP0BCL=1;
SYNCDELAY; 
}

SETUPDAT={0xa1,2,0,1,0,0x12}      サンプル周波数の全リストを返信せよという要求.descriptorファイルの末尾にあるFsRangeDscrのデータを返信する.フォーマットはdescriptorを参照のこと.
返信のやり方その2がここにある.このやり方ではEP0BUFを操作していない.その代わりに、SUDPTRH/SUPPTRLに送信データの所在するpointerをセットするのだ.返信バイト数はSETUPDAT[7:6]が自動的に参照される.
// Get smpl freq range
else if(SETUPDAT[0]==0xA1 && SETUPDAT[1]==0x02 && SETUPDAT[2]==0 && SETUPDAT[3]==1 && SETUPDAT[4]==0 && SETUPDAT[5]==0x12 ) {
dscr_ptr = (void*)pFsRangeDscr;
SUDPTRH = MSB(dscr_ptr);
SYNCDELAY; 
SUDPTRL = LSB(dscr_ptr);
SYNCDELAY; 
}
なお、hostからのリクエストを注意深く観察すると、このリクエストが連続して2度発行されるケースがある.その意図を知っておくとよい.
1度目:返信2byteが要求される.FsRangeDscrの先頭2bytesには、何種類のサンプル周波数に対応しているかの数値が記載されている.ここでは8種類である.
2度目:hostは8種類と知ると全部で2+8*4*3=98bytesのサンプル周波数テーブルが在るのだと知る.そこで2度目は98bytesの返信を要求する.
1度目も2度目も、EZ-USBの操作は上の通りで構わないのである.返信バイト数は自動的にセットされるからだ.
さらにいうと、hostのdriverによっては、1度目でイキナリ256bytes返信をしろとアバウトな要求で済まされてしまい、2度目が無いケースもある.windows10のusbaudio2.dllはそういう挙動に見える.(version upで変わるかもだが)

ここから下にもcodeはあるが、cypressのsample codeなので説明は割愛する.



【bulkloop.c】
初期化ルーチン、ポーリングルーチン、割り込みルーチン、などが記載されている.

EPの初期設定はここで行われている.
void TD_Init(void)        // Called once at startup
{

FIFO clockなどの設定.
    // set the slave FIFO mode & interface to external clock
    // [7] 1:IFCLK internal    0:IFCLK external
    // [6] 1:48MHz   0:30MHz
    // [5] 1:IFCLK output     0:not output
    // [4] IFCLK polality
    // [3] 0:synchronous    1:asynchronous
    // [2] 0 GSTATE off
    // [1:0] 11 slave FIFO 
    IFCONFIG = 0x0b; // 0000_1011
    SYNCDELAY;

EPの設定.
EZ-USB FX2LPには、EP0,1,2,4,6,8がある.EP0,1はFIFOサイズが64byteしかないし、リクエスト制御に頻繁に使われるのでuserには使い勝手が悪い.userが使えるのは2,4,6,8だと思っていい.
このDCCでは次のようにEPをアサインしている.
  EP2   feedback
  EP4   PCM stream
  EP6   audio control
  EP8   未使用
各EPのFIFOサイズは、512bytesを2本である.
  // EPx configuration
  // [7]ON
  // [6]DIR     0:out   1:in
  // [5:4]TYPE   01:ISO 10:BULK 11:INT
  // [3]SIZE 0:512  1:1024
  // [2]
  // [1:0]FIFO個数    00:4  10:2    11:3
  EP1OUTCFG = 0xB0;  // 1011_0000 interrupt
  SYNCDELAY;
  EP1INCFG  = 0xB0;  // 1011_0000 interrupt
  SYNCDELAY;
  EP2CFG    = 0xD2;  // 1101_0x10  in Isochronous 512byte double, feedback
  SYNCDELAY;
  EP4CFG    = 0x92;  // 1001_0x10 out Isochronous 512BYTE double, audio stream
  SYNCDELAY;
  EP6CFG    = 0xF2;  // 1111_0x10  in interrupt 512byte double, control
  SYNCDELAY;
  EP8CFG    = 0xF2;  // 1111_0x10  in interrupt 512byte double, HID
  SYNCDELAY;

EP2,4,6,8をリセットする.
  // RESET FIFO
  FIFORESET = 0x80;
  SYNCDELAY;
  FIFORESET = 0x82; // reset EP2
  SYNCDELAY;
  FIFORESET = 0x84; // reset EP4
  SYNCDELAY;
  FIFORESET = 0x86; // reset EP6
  SYNCDELAY;
  FIFORESET = 0x88; // reset EP8
  SYNCDELAY;
  FIFORESET = 0x00;
  SYNCDELAY;

EP2,6,8はIN方向である.512byte満杯になったら自動的にhostへ送信する機能をONする.このDCCではIN方向のデータ量が少ないのでこの機能が動く場面は無い.
  // EPx AUTOLENGTH    Auto-commit 512-byte packets
  EP2AUTOINLENH = 0x02;
  SYNCDELAY;
  EP2AUTOINLENL = 0x00;
  SYNCDELAY;
  EP6AUTOINLENH = 0x02;
  SYNCDELAY;
  EP6AUTOINLENL = 0x00;
  SYNCDELAY;
  EP8AUTOINLENH = 0x02;
  SYNCDELAY;
  EP8AUTOINLENL = 0x00;
  SYNCDELAY;

EP4はOUT方向である.FIFOを空っぽにする.
  // ARM FIFO EP4
  OUTPKTEND = 0x84;
  SYNCDELAY;
  OUTPKTEND = 0x84;
  SYNCDELAY;

EP2,6,8を空っぽにする.
  // ARM FIFO
  INPKTEND = 0x82;
  SYNCDELAY;
  INPKTEND = 0x82;
  SYNCDELAY;
  INPKTEND = 0x86;
  SYNCDELAY;
  INPKTEND = 0x86;
  SYNCDELAY;
  INPKTEND = 0x88;
  SYNCDELAY;
  INPKTEND = 0x88;
  SYNCDELAY;

EP1,4を動かす.
  // arm EPOUT
  EP1OUTBC = 0x40; // arm EP1 OUT by writing to the byte count
  SYNCDELAY;
  EP4BCL = 0x80;   // arm EP2 OUT by writing byte count w/skip.
  SYNCDELAY;                    

EP4をAUTOOUTにする.AUTOOUTとは、hostから届いたデータがFIFOに積まれたらCPUの介在なしに外部へデータ出力される機能である.
EP2,6,8はAUTOINにしないので、FIFOにデータを積むのはCPUの仕事になる.
  // EPx FIFO CONFIG
  // [7]
  // [6] FULL FLAG
  // [5] EMPTY FLAG
  // [4] AUTOOUT       1:No CPU involvement
  // [3] AUTOIN
  // [2] ZEROLENIN
  // [1]
  // [0] WORDWIDE     0:8bit PB[7:0]
  EP2FIFOCFG = 0x00; // [3]AUTOIN=0, [2]ZEROLEN=0
  SYNCDELAY;
  EP4FIFOCFG = 0x10; // [4]AUTOOUT=1, [2]ZEROLEN=0
  SYNCDELAY;
  EP6FIFOCFG = 0x00; // [3]AUTOIN=0, [2]ZEROLEN=0
  SYNCDELAY;
  EP8FIFOCFG = 0x00; // [3]AUTOIN=0, [2]ZEROLEN=0
  SYNCDELAY;
}
EP初期化はここまで.


ポーリング処理のルーチンここから.
void TD_Poll(void){

feedback機能.FPGAに1024Fsで8つのSOF周期をカウントさせるように別途作ってある.0xC000ぐらいの値になる.
(49.152MHz x 125uSec = 6144、6144x8=49152=0xC000)
それをEZ-USBのPD7,PD5を通してFPGAからシリアルで読む.SOFvalueに格納する.
SOFcmplは、FPGAが発するINT0割り込み処理ルーチンで1にセットされる.
BOOL x;
if(SOFcmpl==1){
// read SOF value from FPGA
SOFvalue=0;
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 32768 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 16384 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 8192 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 4096 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 2048 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 1024 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 512 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 256 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 128 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 64 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 32 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 16 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 8 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 4 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 2 : 0);
PD5=1; x=PD7; PD5=0; SOFvalue += (x ? 1 : 0);
SOFvalueをEP2 feedbackを通してhostへ送る.4bytesである.
しかし4bytesの位取りがよくわからない.
CM6631やXMOSでは0x00180000が送信されているのは判っている.
そこで、C000を1800にするために以下のbit shiftにしてある.でもこれが正しいのかどうかはわかっていない.
if( (EP2CS & 4) == 4 ){ // EP2 empty
EP2FIFOBUF[0] = (BYTE)( (SOFvalue << 5 ) & 0xFF); // SOFvalue[2:0]
EP2FIFOBUF[1] = (BYTE)( (SOFvalue >> 3 ) & 0xFF); // SOFvalue[10:3]
EP2FIFOBUF[2] = (BYTE)( (SOFvalue >> 11) & 0xFF); // SOFvalue[15:11]
EP2FIFOBUF[3] =0;
SYNCDELAY;
EP2BCH = 0;
  SYNCDELAY;
  EP2BCL = 4;
  SYNCDELAY;
}
SOFcmpl=0;
    }

SOFvalueをI2C経由でArduinoに送信してモニタする機能.ArduinoはI2CをCOM port経由でPCのterminalに表示する.DCCに必須の機能ではない.
if(sof_print_flag){
PA6=~PA6;
I2C_printnum2(12, SOFvalue>>8);
I2C_printnum2(12, SOFvalue&0xff);
EZUSB_WriteI2C_str2(12, (BYTE xdata*)" FIFOempty= ");
I2C_printnum2(12, FIFOempty>>8);
I2C_printnum2(12, FIFOempty&0xff);
if(FIFOempty==0) EZUSB_WriteI2C_str2(12, (BYTE xdata*)" @@@@");
EZUSB_WriteI2C_str2(12, (BYTE xdata*)"\n");
FIFOempty=0;
sof_print_flag=FALSE;
//SOFvalue++;
}
}

SetupCommand()からこれがコールされる.set interfaceリクエスト.
やっていることは、まずalternateのセット{0,1,2,3}.
 alternate0は音声再生しないで止まっている状態.
 alternate1は16bit.
 alternate2は24bit.
 alternate3は32bit.
PD[2:1]に{0,1,2,3}を出力する.PD[2:1]はFPGAへ与えられ、FPGAは32,24,16bitによって処理内容を変える.
EX1はINT1のenable.
bit数を変えたので念のためEP4をリセットする.
BOOL DR_SetInterface(void){
   AlternateSetting = SETUPDAT[2];
   switch(AlternateSetting){
case(0): PD2=0; PD1=0; EX1=0; SYNCDELAY; break;
case(1): PD2=0; PD1=1; EX1=1; SYNCDELAY; break;
case(2): PD2=1; PD1=0; EX1=1; SYNCDELAY; break;
case(3): PD2=1; PD1=1; EX1=1; SYNCDELAY; break;
default: PD2=0; PD1=0; EX1=0; SYNCDELAY; 
}
FIFORESET = 0x80; // activate NAK-ALL
SYNCDELAY;
EP4FIFOCFG = 0x00; //switching to manual mode
SYNCDELAY;
FIFORESET = 0x84; // Reset FIFO 4
SYNCDELAY;
OUTPKTEND = 0X84; //OUTPKTEND
SYNCDELAY;
OUTPKTEND = 0X84;
SYNCDELAY;
EP4FIFOCFG = 0x10; //switching to auto mode
SYNCDELAY;
FIFORESET = 0x00; //Release NAKALL
SYNCDELAY;
   return(TRUE);            // Handled by user code
}


ここから下は割り込み処理ルーチン.
EZ-USB FX2LPの割り込みにはこの13種類がある.
なのだが、8番と10番はさらに多種に別れていて多様な割り込みに対応する.
//--------------------------------------------------
// Interrupt Handlers
#define  INT0_VECT   0  // 0x03   INT0
#define  TMR0_VECT   1  // 0x0B
#define  INT1_VECT   2  // 0x13   INT1
#define  TMR1_VECT   3  // 0x1B
#define  COM0_VECT   4  // 0x23
#define  TMR2_VECT   5  // 0x2B
#define  WKUP_VECT   6  // 0x33
#define  COM1_VECT   7  // 0x3B
#define  USB_VECT    8  // 0x43   INT2 USB
#define  I2C_VECT    9  // 0x4B   INT3
#define  INT4_VECT   10 // 0x53   INT4 GPIF
#define  INT5_VECT   11 // 0x5B   INT5
#define  INT6_VECT   12 // 0x63   INT6
//--------------------------------------------------

INT0割り込み処理.FPGAが8つのSOF周期をカウント完了したらINT0に割り込んでくるように作った.
void ISR_INT0(void) interrupt 0{  // when SOF count complete, comes here
SOFcmpl=1; // completed SOF measurement
TCON &= 0xFD;   // Clear INT0  TCON.1 Flag
INT0cnt++;
if(INT0cnt==200) {PA7=~PA7; INT0cnt=0; }  LEDチカチカ
}

INT1割り込み処理.FIFO emptyで割り込んでくる.empty発生個数をカウント.
void ISR_INT1(void) interrupt 2{  // when FIFOempty, comes here
FIFOempty++; // count up FIFO empty
TCON &= 0xF7; // Clear INT1  TCON.3 Flag
FIFOemptyLEDcnt=0;
PA3=1;  // LED on  LEDチカチカ
}

setupdataが来たら割り込み.
void ISR_Sudav(void) interrupt USB_VECT{
   GotSUD = TRUE;      // Set flag
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUDAV; // Clear SUDAV IRQ
}

SOF割り込み.SOF周期(125uSec)は別名micro frameとも呼ばれ、host PCが周期的に発するpacketの周期である.
DCC機能的に重要なのは、PD6をtoggleしているところで、PD6をFPGAに与え、FPGAはPD6周期をカウントしている.その値をfeedbackを介してhost PCに送信する.
それ以外にはLEDチカチカやI2C送信などのタイマーとして使っている.
void ISR_Sof(void) interrupt USB_VECT{
PD6 = ~PD6;   // SOF indicator

if(AlternateSetting==0) {
sof_print_flag=FALSE;
sof_timer=0;
}
else if(sof_timer==40000) { // 5Sec timer
//PA7=~PA7;
sof_print_flag = TRUE;
sof_timer=0;
}
else sof_timer++;

FIFOemptyLEDcnt++;
if(FIFOemptyLEDcnt==8000){ FIFOemptyLEDcnt=0; PA3=0; } // LED off
    EZUSB_IRQ_CLEAR();
    USBIRQ = bmSOF;            // Clear SOF IRQ
}

以下の割り込みルーチンはCypressのsample codeなので説明を略す.


【USBJmpTb.a51】
これは割り込みvectorが記述されている.

冒頭のこれらの宣言は、割り込み処理ルーチンの全リストである.bulkloop.cに本体が記述されている.
ほとんどがCypressによるsample codeなのだが、ISR_INT0とISR_INT1はヒラサカが追加したルーチンである.
extrn code (ISR_INT0, ISR_INT1)
extrn code (ISR_Sudav, ISR_Sof, ISR_Sutok, ISR_Susp, ISR_Ures, ISR_Highspeed, ISR_Ep0ack, ISR_Stub, ISR_Ep0in, ISR_Ep0out, ISR_Ep1in, ISR_Ep1out, ISR_Ep2inout, ISR_Ep4inout, ISR_Ep6inout, ISR_Ep8inout, ISR_Ibn)
extrn code (ISR_Ep0pingnak, ISR_Ep1pingnak, ISR_Ep2pingnak, ISR_Ep4pingnak, ISR_Ep6pingnak, ISR_Ep8pingnak, ISR_Errorlimit, ISR_Ep2piderror, ISR_Ep4piderror, ISR_Ep6piderror, ISR_Ep8piderror, ISR_Ep2pflag)
extrn code (ISR_Ep4pflag, ISR_Ep6pflag, ISR_Ep8pflag, ISR_Ep2eflag, ISR_Ep4eflag, ISR_Ep6eflag, ISR_Ep8eflag, ISR_Ep2fflag, ISR_Ep4fflag, ISR_Ep6fflag, ISR_Ep8fflag, ISR_GpifComplete, ISR_GpifWaveform)

ISR_INT0とISR_INT1はヒラサカが追加したルーチンなのだから、vectorにも追加する必要があるだろう.
どこにどのように追加したらよいのだろうか?
fx2.hの中に定義されているこの部分がわかりやすい.
INT0のvectorは3番地、INT1のvectorは0x13番地である.
#define  INT0_VECT   0  // 0x03   INT0
#define  TMR0_VECT   1  // 0x0B
#define  INT1_VECT   2  // 0x13   INT1
#define  TMR1_VECT   3  // 0x1B
#define  COM0_VECT   4  // 0x23
#define  TMR2_VECT   5  // 0x2B
#define  WKUP_VECT   6  // 0x33
#define  COM1_VECT   7  // 0x3B
#define  USB_VECT    8  // 0x43   INT2 USB
#define  I2C_VECT    9  // 0x4B   INT3
#define  INT4_VECT   10 // 0x53   INT4 GPIF
#define  INT5_VECT   11 // 0x5B   INT5
#define  INT6_VECT   12 // 0x63   INT6

これがINT0,INT1のために追加したところである.割り込みvectorに記述されているのはLJMP命令そのものだ.すぐ下に43番地と53番地とあるのはUSB関連のたくさんある割り込みルーチンに対応するものだ.
      CSEG   AT 03H
      ljmp   ISR_INT0   ; INT0 goes to ISR_INT0

      CSEG   AT 13H
      ljmp   ISR_INT1   ; INT1 goes to ISR_INT1

      CSEG   AT 43H
USB_Int2AutoVector   equ   $ + 2  ; 43+2=45
      ljmp   USB_Jump_Table   ; INT2 goes to USB_jump_table

      CSEG   AT 53H
USB_Int4AutoVector   equ   $ + 2
      ljmp   USB_Jump_Table   ; INT4 goes to USB_jump_table

以下は省略.


【i2c_rw.c】
setupdataをI2Cへ出力するルーチン.基本的にCypressのsample codeだが、一部ヒラサカが追加した.
BYTE hex2char( BYTE x ){
  if(x<10) return('0'+x);
  else return('A'+x-10);
}

void I2C_printnum(BYTE addr, BYTE x){
BYTE xdata c[3];
c[0] = hex2char(x>>4);
c[1] = hex2char(x&0xf);
c[2] = ' ';
EZUSB_WriteI2C(addr, 3, c);
}

void I2C_printnum2(BYTE addr, BYTE x){
BYTE xdata c[2];
c[0] = hex2char(x>>4);
c[1] = hex2char(x&0xf);
EZUSB_WriteI2C(addr, 2, c);
}

void I2C_printSUD(BYTE addr, BYTE n){
int i;
EZUSB_WriteI2C_str2(addr, (BYTE xdata*)"#");
for(i=0;i<8;i++) I2C_printnum(addr, SETUPDAT[i]);
for(i=0;i<n;i++) I2C_printnum(addr, EP0BUF[i]);
EZUSB_WriteI2C_str2(addr, (BYTE xdata*)"\n");
}




【②FPGA verilog code】
top.vというファイルひとつだけである.

主な仕事は、EZ-USBのFIFOから読みだしてI2Sに変換することである.FIFOに出てくる音声データはリトルエンディアンなのだが、I2Sはビッグエンディアンなので並び替えもやらなくちゃいけない.
音声モードは、16,24,32bit、44.1~384kHzに対応するので、clock切り替えなどの操作が必要になる.
ただし、実機動作確認したのは32bit 384kHzだけである.

もう一つの仕事として、SOF間隔を1024Fsでカウントする仕事もさせている.

途中で投げ出したcodeなので汚い.シーケンサで書き換えたいとも思うが放置した.

現物で使ったFPGAはXILINX Spartan6であるが、そんな巨大なデバイスは不要だ.


まずはclock系の理解のため、このチャートで分周比を考える.
源発信はxtalの49.152MHzをつかう.48kHz系の1024Fsが49.152MHzだ.(44.1kHz系は45.1584MHzのxtalを使う)
49.152MHzを10bit分周する.
MCKはDACへ渡すclockである.[0]を使って24.576MHz固定.
FIFOCKはEZ-USBのIFCLKへ接続する.[0]を使って24.576MHz固定.
BCKはI2Sのbit clockであり、64Fsである.LchRch各々32bitなので合計64bitという理由だ.それゆえ、サンプリング周波数に応じて切り替える必要がある.384kHzのときは[0]24.576MHz、192kHzのときは[1]12.288MHzなどという具合に.
SLRDはFIFOのread enableである.FIFOは8bit busで運用する.4bytesの2ch分を毎度読みだすのが仕事なので8Fsとする.384kHzのときは[3]3.072MHz、192kHzのときは[4]1.536MHzなどとなる.
LRCKはI2Sのサンプリング周波数である.384kHzのときは[6]384kHz、192kHzのときは[7]192kHzなどとする.
//    49152000
//[0] 24576000               oBCK    MCLK    FIFOCK
//[1] 12288000           *
//[2] 6144000        x               
//[3] 3072000    o           oSLRD
//[4] 1536000            *
//[5] 768000         x
//[6] 384000     o           oLRCK
//[7] 192000             *
//[8] 96000          x
//[9] 48000      o

IO定義
module top(
    input xtal_i,         // xtal 49MHz
EZ-USBから受け取る制御信号
    input [1:0] bitsel_i, // 0:off 1:16 2:24 3:32
    input [1:0] fssel_i,  // 0:48k 1:96k 2:192k 3:384k
    input [7:0] fifodata_i, // FIFO data bus
    input xfifoempty_i,   // FIFO empty flag
SOFカウントのための信号
    input sof_i,     // from ez-usb, sof cycle 4kHz
    input sof_ck,  // from ez-usb, read clock of sof measurement 
    output sof_int_o,   // to ez-usb, interrupt, sof measurement value ready
    output sof_o,    // to ez-usb, SOF measure value serial output
    output sof_timeout, // SOF serial timeout
音声データのためのclockやI2S信号
    output mck_o,      // 24MHz fix, musked by fifoempty
    output bck_o,      // not musked
    output fifock_o,   // 24MHz fix, not musked
    output xslrd_o,    // FIFO read enable BCK/8
    output lrck_o,     // LRCK BCK/64
    output data_o,
    input xrst,
    input xslrd_i,  // loopback of xslrd_o
インジケータ類
    output led_1,
    output led_2,
    input key_1, key_2, sw1,
    output fs384_o, fs192_o, fs96_o, fs48_o,  // LED
    output bit32_o, bit24_o, bit16_o   // LED
);

assign led_1 = 0;
assign led_2 = 0;

wire fifoempty = ~xfifoempty_i;

EZ-USBから受け取るFsセレクト及びbitセレクト.
sleepについてはひと手間かけてある.bitが変わったら一瞬sleepに入れる、Fsが変わったら一瞬sleepに入れる、ようにしている.リセットのためだ.
assign fs384 = fssel_r==3;
assign fs192 = fssel_r==2;
assign fs96 = fssel_r==1;
assign fs48 = fssel_r==0;
assign bit32 = bitsel_r==3; // alt3
assign bit24 = bitsel_r==2; // alt2
assign bit16 = bitsel_r==1; // alt1
assign sleep = bitsel_r==0 || // alt0
(bitsel_rr!=bitsel_r) ||  // change alt
(fssel_rr!=fssel_r); // change fs

モニタのためにLEDを切り替えてるだけなので無視してかわない.
assign fs384_o = sw1 ? 0 : fs384;
assign fs192_o = sw1 ? 0 : fs192;
assign fs96_o = sw1 ? fssel_i[1] : fs96;
assign fs48_o = sw1 ? fssel_i[0] : fs48;
assign bit32_o = sw1 ? 0 : bit32; // alt3
assign bit24_o = sw1 ? bitsel_i[1] : bit24; // alt2
assign bit16_o = sw1 ? bitsel_i[0] : bit16; // alt1

fsselとbitselの取り込み.
reg [1:0] fssel_r, fssel_rr;  // 48k 96k 192k 384k
always@(posedge xtal_i or negedge xrst)
if(!xrst) {fssel_rr,fssel_r} <= 3;
else {fssel_rr,fssel_r} <= {fssel_r,fssel_i};

reg [1:0] bitsel_r, bitsel_rr;  // 32bir 24bit 16bit, sleep
always@(posedge xtal_i or negedge xrst)
if(!xrst) {bitsel_rr,bitsel_r} <= 0;
else {bitsel_rr,bitsel_r} <= {bitsel_r,bitsel_i};

I2SとFIFOの信号を発生するキモのところ.
基本的にはFsで切り替えているだけである.
ただし、10分周カウンタにsleepでリセットをかけている.また、FIFO emptyでpauseさせている.これらは、byteズレを防止するために必須である.
reg [9:0] div1; // 0-1023 sequencer
always@(posedge xtal_i or negedge xrst)
if(!xrst) div1 <= 0;
else if(sleep) div1<=10'b11_1111_1111;  // restart
else if(fifoempty) ;   // paused
else div1 <= div1+1;

assign bck= fs48  ? div1[3] :
fs96  ? div1[2] :
fs192 ? div1[1] : div1[0];
assign bck_en= fs48  ? div1[3:0]==1 :
fs96  ? div1[2:0]==1 :
fs192 ? div1[1:0]==1 : div1[0];
assign slrd= fs48  ? div1[6:1]==0 :
fs96  ? div1[5:1]==0 :
fs192 ? div1[4:1]==0 : div1[3:1]==0;
assign lrck =  fs48  ? div1[9] :
fs96  ? div1[8] :
fs192 ? div1[7] : div1[6] ;

音声PCMデータが、USBはリトルエンディアン、I2Sはビッグエンディアンなので並び替えのための信号を作っておく.後で使う.
wire [1:0] byte_cnt;
assign byte_cnt= fs48 ? div1[8:7] :
fs96 ? div1[7:6] :
fs192 ? div1[6:5] : div1[5:4];

AK4495のmckを作る.
24.576MHz固定でよいのだが、sleepで止める.AK4495はmckが停まるとパワーセーブになるのだ.
ただし、mckをFIFO emptyでpauseさせるべきではない.ノイズを出させないため.
なおAK4495 datsheetによるとbckとmckの位相に縛りは無いので、別途此処でmckを生成させても不都合は生じない.
reg mck_r;
always@(posedge xtal_i or negedge xrst)
if(!xrst) mck_r <= 0;
else if(sleep)  mck_r <= 0;
else mck_r <= ~mck_r;

FIFO clockをつくる.
24.576MHz固定でよいのだが、これは止めてはだめ.止めるとFIFOが狂う.
なお、FIFO clockはEZ-USB内部の48MHzでも構わないはずである.ここでは同期読み出しはやってないからだ.(=非同期読み出しでFIFOアクセスしている)
reg fifock_r;
always@(posedge xtal_i or negedge xrst)
if(!xrst) fifock_r <= 0;
else fifock_r <= ~fifock_r;

bckのタイミング合わせ.2つ遅れにさせているのはFIFO emptyから復帰したときのグリッジを防ぐため.
reg bck_r, bck_rr;
always@(posedge xtal_i) {bck_rr,bck_r} <= {bck_r,bck};

FIFO read strobe作成
reg xslrd_r;
always@(posedge xtal_i)
if(!xrst) xslrd_r <= 0;
else if(bck_en) xslrd_r <= ~slrd;

LRCK作成.リトルエンディアン→ビッグエンディアンの変換とタイミングを合わせてもいる.
reg lrck_r,lrck_rr;
always@(posedge xtal_i)
if(!xrst) {lrck_rr,lrck_r} <= 0;
else if(bck_en) {lrck_rr,lrck_r} <= {lrck_r,~lrck};

リトルエンディアン→ビッグエンディアン変換
16,24,32bit modeに関わらず4bytesで音声streamが来るようdescriptorに記述した.
なので、bitに関わらず4bytesのエンディアン変換をすればよい.
reg [31:0] fifodataL_r, fifodataR_r;
always@(posedge xtal_i)
if(!xrst) {fifodataL_r,fifodataR_r}<=0;
else if(bck_en) begin
   if(xslrd_i==0 && lrck==0) begin
if     (byte_cnt==0) fifodataL_r[7:0]   <= fifodata_i;
else if(byte_cnt==1) fifodataL_r[15:8] <= fifodata_i;
else if(byte_cnt==2) fifodataL_r[23:16] <= fifodata_i;
else if(byte_cnt==3) fifodataL_r[31:24] <= fifodata_i;
   end
   if(xslrd_i==0 && lrck==1) begin
if     (byte_cnt==0) fifodataR_r[7:0] <= fifodata_i;
else if(byte_cnt==1) fifodataR_r[15:8]  <= fifodata_i;
else if(byte_cnt==2) fifodataR_r[23:16] <= fifodata_i;
else if(byte_cnt==3) fifodataR_r[31:24] <= fifodata_i;
   end
   if(lrck_rr==0) fifodataL_r <= {fifodataL_r[30:0],1'b0};
   if(lrck_rr==1) fifodataR_r <= {fifodataR_r[30:0],1'b0};
end

出力データアサイン
assign data_o   = lrck_rr ? fifodataR_r[31] : fifodataL_r[31];
assign fifock_o = fifock_r;  // FIFO synchronization clock
assign xslrd_o = xslrd_r;   // FIFO RD
assign mck_o    = mck_r;     // 24MHz fix
assign bck_o    = bck_rr;    // I2S
assign lrck_o   = lrck_r;    // I2S

ここから下はSOF間隔を49MHzでカウントする回路.
測定結果をEZ-USBへ渡すには、sof_int_oでEZ-USBに割り込みをかける.その後にsof_ckとsof_oでシリアル出力する.
説明は略す.



【④Arduino】
I2C_EZUSB.ino である.

EZ-USBから、8bytesのsetup dataと、4bytesのEP0 dataがASCII形式でI2C経由で到来する.その番号を解析して文字列をCOM PORTへ出力するのが役割.

ここから下はs[]を解析するcodeが続く.
void analyze() {
  if(s[0]==0 && s[1]==9 && s[2]==1 && s[3]==0 && s[4]==0) Serial.println("standard SET_CONFIG");

中略

I2CとCOMの初期化.I2Cアドレスは12番.
void setup() {
  Wire.begin(12);  // join i2c bus
  Wire.onReceive(isr_i2c_slave);
  Serial.begin(115200);  // start serial for output
  Serial.print("starting USB setup monitor\n");
  n=0;
}

I2Cを受信したら割り込みがかかる.
void isr_i2c_slave() {
    while (Wire.available())
    {
      char t;
      t = Wire.read(); // receive a byte as character
      asc[n++]=t;
      if(n<MAXBUF){ ; }
      else { n=0; t=0; }
以下略.


EZ-USB DCC起動時のsetup log.
起動した時点ではalternative0になっているのでFPGAやDACはsleep状態となっている.
先頭8bytesがsetup dataである.後続の4bytesはEP0BUFの先頭4bytesである.
80 06 00 01 00 00 40 00 |02 03 00 00 standard GET_DESCRIPTOR DEVICE
80 06 00 01 00 00 12 00 |02 03 00 00 standard GET_DESCRIPTOR DEVICE
80 06 00 02 00 00 FF 00 |02 03 00 00 standard GET_DESCRIPTOR CONFIG
80 06 00 02 00 00 09 01 |02 03 00 00 standard GET_DESCRIPTOR CONFIG
80 06 00 03 00 00 FF 00 |02 03 00 00 standard GET_DESCRIPTOR STRING(0)
80 06 02 03 09 04 FF 00 |02 03 00 00 standard GET_DESCRIPTOR STRING(2)
80 06 00 01 00 00 12 00 |02 03 00 00 standard GET_DESCRIPTOR DEVICE
80 06 00 02 00 00 09 00 |02 03 00 00 standard GET_DESCRIPTOR CONFIG
80 06 00 02 00 00 09 01 |02 03 00 00 standard GET_DESCRIPTOR CONFIG
00 09 01 00 00 00 00 00 |02 03 00 00 standard SET_CONFIG
01 0B 00 00 01 00 00 00 |02 03 00 00 standard SET_INTERFACE interface(1) alt(0)
80 06 02 03 09 04 04 00 |02 03 00 00 standard GET_DESCRIPTOR STRING(2)
80 06 02 03 09 04 16 00 |02 03 00 00 standard GET_DESCRIPTOR STRING(2)
80 00 00 00 00 00 02 00 |00 00 00 00 standard GET_STATUS
80 06 00 03 00 00 04 00 |00 00 00 00 standard GET_DESCRIPTOR STRING(0)
80 06 02 03 09 04 02 00 |00 00 00 00 standard GET_DESCRIPTOR STRING(2)
80 06 02 03 09 04 16 00 |00 00 00 00 standard GET_DESCRIPTOR STRING(2)
A1 02 00 01 00 12 00 01 |00 00 00 00 Audio class GET_RANGE interface(0) clock source(18)
80 06 04 03 09 04 02 00 |00 00 00 00 standard GET_DESCRIPTOR STRING(4)
80 06 04 03 09 04 10 00 |00 00 00 00 standard GET_DESCRIPTOR STRING(4)
02 01 00 00 86 00 00 00 |00 00 00 00 standard CLEAR_FEATURE EP86
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal
A1 01 00 02 00 07 06 00 |02 03 00 00 Get TE_CONNECTOR_CONTROL of output terminal


PCで音声再生アプリをPLAYにしたときのlog.
サンプリング周波数が0x05dc00=384000にセットされている.
aiternative3にセットされている.=32bit
01 0B 03 00 01 00 00 00 |02 03 00 00 standard SET_INTERFACE interface(1) alt(3)
01 0B 00 00 01 00 00 00 |02 03 00 00 standard SET_INTERFACE interface(1) alt(0)
21 01 00 01 00 12 04 00 |00 DC 05 00 Audio class SET_CURRENT Fs ID(18)
01 0B 03 00 01 00 00 00 |00 DC 05 00 standard SET_INTERFACE interface(1) alt(3)

PCで音声再生アプリを停止したときのlog.
alternative0にセットされている.
01 0B 00 00 01 00 00 00 |00 DC 05 00 standard SET_INTERFACE interface(1) alt(0)



【EZ-USBを中心にした結線図】

あー書き疲れたびー

かしこ