低電圧ヘッドホンアンプ

2008/10/14工作::ampimport

低電圧ヘッドホンアンプ2?(nabeさん設計) with 基板ありがとうございます

nabeの雑記帳にて,40万ヒットのプレゼント(2008-09-17)がありました.
迷わず申し込んで,基板+OPAMPをいただくことができました.ちょっとした郵便自己があってケミコンは破裂*1していましたが(笑)

20081014_opbuf01.JPG

ご覧のとおり,いじくっている最中ではありますが,blogへのコメント期限が近いので,途中経過を報告させていただきます.なお,こちらに書く前に,mixiで少しメモっていたので引用してきますので,文体がいつも以上に酷いです*2


*1 : 郵便局の機械で詰まったらしいです.機械のほうが心配だったよ...

*2 : mixiメモへの自分用リンク:2008年10月09日02:24, 2008年10月14日02:02

結論

現時点では,USBDAC出力をPC側で絞った音のほうが好みです.
ヘッドフォンアンプにより,アナログアッテネータで減衰することで音質の向上が見込めるということですが,しばらくUSBDACの音に惚れていたせいか,未だ馴染めません.

回路定数の修正や,ボリュームの変更で大きく変わるのか微妙ですけれど,低音が強調されすぎの感じがします.もともとこういう音かもしれませんが・・・.


[TRY]foobar2000で音量を下げる

アンプの出力をあげて,USB-DACをヘッドフォン直結で聞いていた音量にしてみました.
これこれ.低音が弱まって聞きなれた音になりました.ということは,PCで音量を下げた弊害で音が変わっていたということか!?

音声データはCDから可逆圧縮でリッピングしたものなのですが,デジタル処理しただけでは情報が変わってしまうというのか.


TRY予定

エミッタ抵抗で音が大きくは変わらないとは思いますが,コレも経験.
推奨値の1Ωに置換して聞いてみます.

本家のコメント85にて,OP-AMP近傍にパスコンがないとの指摘.OSコンから数センチ離れていて,間にトランジスタさんもいるようです.トランジスタが電流をそんなに引っ張らない気もしますが.これもパスコンもしくはバイパス配線してやると向上が期待できるかもしれません.
というか,先に電源ラインに問題があるかを確認すべきですね.
シンクロスコープで見えるか(要観測)



以下,日記形式にて.

実装前

ダイアモンドバッファ部分について,トランジスタの選別が必要と思い込んでいました.部品入着を待っていたり,選別作業に音を上げていたら,コメントが... 一週間近く見落としていました(失礼しました)

もう一度回路を見直すと,ダイアモンドバッファ出力がOP-AMPへと帰っているではありませんか!.帰還してるなら,選別しなくても出力にDCが乗ることもなさそうですし,どうせコンプリメンタリでも歪むのだから,と考えて実装へと移りました.


実装当日

nabe先生のヘッドフォンアンプ基板,選別あきらめて実装しますた.とりあえずバラック状態でエージング開始.ケーシングすれば半田付けしなおすわけで,熱劣化再発生という罠も...レポを一度出してからケース入れすることにしよう.


とりあえず電源入れてすぐは,すごくもやのかかった感じがした.高音がのびず,低音がboostされた感じだ.PC側ボリュームをMAX.にしているせいもあるし,回路定数を在庫で合わせてしまっている(後述)から,差分もあるだろう.

で,しばらく温まってきたせいか,耳が慣れてきたせいか,もやが少しマシになる.というか,もともとエコーがかかっていて,ソレが強調された感じだった,かな..注力して効いてしまうと,耳のフィルタのせいで感じも変わるから難しいねぇ.

低音が増してるのは間違いないな... 長時間使うと疲れそうだ.しばらく放置して様子を見るか.入力短絡しておいたほうがいいんだろうな.

エミッタ抵抗は手持ち在庫の都合で4.7Ωを実装.
CRDは1mAを使用.
電池はeneloop単3で初期充電のものを使用.

エージング三日ほど

ヘッドフォンアンプ,三日三晩くらいは放置したので,エージングは十分なはずなのだが,高音が伸びない.
良く考えたら,以下のことがあげられる.

  • eneloopは初期充電のものを使っている
  • 出力段の抵抗が定数違いである
  • ボリュームが推奨品ではない*3

抵抗は明日にでも入着する*4ようなので,電池を疑ってみた.

寝る前にするんじゃなかったwwww

電池交換後

アルカリの中古電池があったので,コレを使用.新品過ぎると少し電圧が心配だった.とはいえ,アンプとOSCONの耐圧が2.5Vというのに引っかからなければいいので,1.5+αであれば耐えられたとは思う.設計は1.2Vなので,コレで比較しなければならないわけだが.# 充電器が見つからない.結構片づけが進んでいるはずなのに.チェックする前にしまったか.

電源電圧向上により,高音の伸びが復活.低音は相変わらずboostされている.解像度はUSBDAC並みに上がったと思われる.注意深く効くようになって,耳がエージングされて*5しまっているところもあるので,比較時には聞き込んだものか,初めて聞くもので比較すべきだろうか.

現在の評価楽曲

現状,水樹奈々嬢のSecret Ambitionと Heart-Shaped Chantとを使用.前者はハイハット,後者は弦楽器(ハープみたいなやつ)がどこまで聞こえるか,で,解像度の良し悪しを判断している.他の音に混じって聞こえてこなかったのが,聞き分けられるようになってきた.耳がなじんだせいもあるから,これだけで評価してはいけないということだなw

特にレコーディングされたものは,vocalのブレスを殆ど意図的に消してしまっていて,それが楽曲に紛れて消えるかどうか,とか,息遣いが判るか,なども判断材料にしたかった.その点,同人CDはブレス消してないのもそこそこあるようなので,狙ってみるといいかもしれない.

電子楽器が多いのはちょっと耳が痛い.低音boostされたものを聞いても,疲れる.寝る前だからか?w


寝る前の考察

ボリューム調整による入力段のフィルタ特性の変化も気がかりではあるが,PC出力を同じ大きさで比較してみると,ちょっと出方が違うみたい.
USBDACは出力振幅がでかいので,PCで絞って聞いていたけれど,今回はPC出力はDAC, このヘッドフォンアンプで減衰させているわけだけれども,本来の音がこういう低音の効いたものなのかもしれない.な...

リファレンスが無いから,なにが正しいのかわからなくなってきたぜwww
もうひとついえるのは,ヘッドフォンは所詮ヘッドフォンであるということかな...音圧を体で感じられるスピーカには敵わないわ.たぶん.

もちろん,双方ともにシステムがどの程度まで練られているかによるのだろうけれど.特にスピーカともなると部屋の影響まで受けてくるかなぁ.ヘッドフォンだと,密閉型を選んでしまえば,外の音を遮断できるから,場所に関係なく再現できるのが強みかなぁ.(騒音が酷すぎるところは除くw


抵抗差し替えてエージングは要るかしらねぇ.一度レポあげておいたほうがいいな.ケーシングも未だなんだけどw
# 図面ナシでエイヤで空けてしまうか・・・.いつもコレで失敗するんだよなぁ('A`

*3 : デジットの高級ボリューム(アルプス?)を使用

*4 : 配送遅れで入手できず.レポに間に合わなかった.

*5 : "こういう音が聞こえる"という記憶も含む.つまり劣化している...のか?

HID Interrupt transferの動作確認

2008/09/08工作::USBimport

HID Report DescriptorとHostとの通信について(Interrupt Transfer)

デバイス設定:断りの無い限り,下記のとおりとする.

itemvalueremark
Poling cycle10 mSecInterface Descriptorで指定
EndPointBuffer size64 bytesInterrupt transfer

Report Descriptorで定義したサイズは固定長である.


転送サイズについて

Report Descriptorでは,Variable....という記載があったので,デバイス→ホスト間の転送サイズは任意であると考えていた.実際に動かして見ると調子が悪かったので,HIDは 原則固定長であると認識した.

実際にDevice/Host間で送受信データサイズを変えて確認した.ただし,いずれもデバイスのReport Descriptorでは 8bit 64count(64octet)とし,Interface Descriptorでは,EP sizeを64octetとしている.

Transfer directionfromtoRemark
IN transactionDEV: 64byte送信HOST: 64Bytes受信OK
OUT transactionHOST: 64byte送信DEV:64byte受信OK
IN transactionDEV: 1byte送信HOST: 64Bytes受信NG
IN transactionDEV: 1byte送信HOST: 1Bytes受信NG
IN transactionDEV: 64byte送信HOST: 1Bytes受信NG

Full Speed時は64byte(max)のユーザデータを送受信できるが,固定長となる.UARTの代替として使用する場合,もしくは64octetを超えるパケット通信の土管として使用する場合には,さらに一段ラッパーをかます必要がある.Low Speedもサポートするのであれば,パケットサイズが8octetになる.

 struct {
	Byte SizeOfData ;
	BYte Data[63] ;		// Low=63, High/Full=63
	}

PC側は,Report Descriptorを受け取って,capabilityとしてサイズを認識するので,データサイズは固定としない.デバイス側で,最大長となるように設定する.デバイスのメモリの都合・データ流量の都合により,削減する場合は,descriptor・interrupt transferの転送サイズをReport通りに修正するだけでよい.


取りこぼしについて(後方参照のこと!)

Interrupt転送は,デバイス-ホスト間でのデータ取りこぼしが起こりえないという話をどこかで見かけた.本当にそうなのかを検証してみた.*1

  • デバイスは複合デバイスとして実装した.同一USB portに複数のデバイスがぶら下がっているため,Interrupt転送を占有していない.← このため,最大負荷テストではない
  • PSoC側で1mSecの分周クロックを生成して*2,INパケットに積む
  • 毎パケット,+1したシーケンス番号を積んで,取りこぼしを検出する.
  • Host側は受信スレッドを作成し,受信開始からスレッドをまわす.取得したデータはQueueに積んでいく. 表示するときにQueueから吸い上げてListに突っ込む.
Poling Timing(Report)PO cycle実測結果Remark
10mSec8mSec取りこぼしなし周期が早いのは..?
1mSec2mSecかなりこぼす複合デバイスにしたので,最速では回らないか? スレッドで0秒寝かせているのが悪いのかもしれない.回りっぱなしでもトライする?.
2mSec2mSecかなりこぼします10/Sep.の追試実験用.条件よければOK.

※試験結果を随時追加していく.★疑問:GetInputReportBufferSize は なに?EPサイズでもreportサイズでもない.. reportの記憶回数でもない..



*1 : ホスト→デバイス方向は未確認

*2 : Sysclk=24MHz, VC1-VC2-VC3接続し,Timer8bitでカウント.VC1=15, VC2=16, VC3=100 → 1mSec

追記(10/Sep./2008)

同時期に,C++ Builderでホストプログラムを作成されている方より,取りこぼしはおきない旨,伺いました.Visual C#が癌なのかという疑いが出てきます.

ホスト側実装

前回の測定時のフローを示す.
1. 受信を Threadクラスを使ってぶん回す.ひたすらRead()を呼び出し続ける.
2. 受信したデータは,下記のクラスを用いてデータを積み上げる.

System.Collection.Generic.Queue<Byte>

このとき,スレッド内では,追加時にlock(Que)する.
3. Formスレッドで,上記クラスからenqueしてデータを取り出し,表示用のListControlに追加する.
このとき,lockなし,連続して吸い出している.

チェキ1

Formスレッドで,Queから読み出すたびに,Thread.sleep(0)を入れた.体感もっさりした気がする*3.取りこぼしは消えない.

追加情報

MSVSのmanualを見ると,動的に記憶領域を延ばすと書かれていた.追加時のオーバヘッドでもこぼしている可能性があるのだろう.
また,ロックの仕方に問題がありそう.本質的にスレッドセーフではないとあるので,記載どおりのlockを行う.
・・・ために,generic Queueではなく,Collection.Queueクラスを用いる.

チェキ2

ヘルプに記載のとおり,下記のlock()を適用する.

lock(myCollection.SyncRoot)

System.Collection.Generic.Queue<>ではなく,System.Collection.Queueを使ってみた.読み書き両方でlock()を使ったが,やはり駄目だ.
Byte[]の動的確保にも負荷がかかっているのだろう.開放処理もGCが走るだろうし.

チェキ3

表示させずにデータ取得させてから,表示してみる.
取りこぼしナシ.CPU負荷がそれなりにかかる模様*4

アプリケーション走行速度・データの扱い方による問題と思われる.

また,受信バッファは512byteまで指定可能のようだ.でかい値を放り込んでも拒絶される(32byte:report値に戻る?).
ただし,これによる救済措置が図れるのかは疑問である・・・.


結論

実は,チェキ1が終わった段階で,USB Snoopy Proを使用してPC側にデータが来ているかどうかを確認していた.
案の定,データが来ていることは見て取れたので,取りこぼしているのはドライバ~アプリのアタリであるとアタリがついていたのです.

そもそもHIDと言っている以上,ヒトの応答速度程度の情報を送受信するのが目的であるし,仕様なのかもしれない.
また,Report Descriptorを見ても判るように,固定長・ビット単位で意味を持たせたデータを送るのが目的であり,今回のようにストリームデータを送るのは想定外使用なのだろう.もし,確実に双方向のデータ通信を行いたいのであれば,ホスト~デバイス間でハンドシェイクを行う必要があるでしょう.

そこまでするならBulk転送で~とも思うのだけれど,それはそれでホスト側のドライバが面倒.汎用USBドライバやWinUSBといったものがあるようなので,それらの使用も視野に入れたい.
ひとまずHIDポート制御部分を切り出してコンポーネント化しておきたいところですね.

*3 : ListControlへの追加が遅くなっただけだろう

*4 : Core2Duo 2.4GHz(E6600)で30%超. VisualC# デバッグモードにて.Debug Writeも使用.

[C#][USB] Host apllication on WindowsXP with C#

2008/08/30工作::USBimport

★本気時は書きかけのものです.頓挫する前に公開★

PC側のソフトを準備する

氏のsample"generichid_cs"から,必要なコードを流用する.C#では,Win32APIの呼び出しを直接行うことはできない.unsafe codeとして,DLLからAPIをimport宣言してやる必要がある.VBでWin32APIを用いるために宣言していたのと同様である.*1

*1 : .NET環境ではC#もVBも同じILに落ちると思いますけど

HostTest_01

  • device enumeration
  • detection of device attached/detattached
  • IN/OUT transaction check by using ReadFile/WriteFile

console applicationでもよさそうだが,今後のことを考えてGUIで作っていく.Formに配置するリソースを列挙する.

  • TextWindow or List Window
    • Status Window
    • Rx Data window(StatusWindowに書いておけばいいか?)
  • EditBox
    • Device ID
      • VID
      • PID
      • IF-ID
    • TxData
  • コマンドボタン
    • device detect
    • INPUT
    • OUTPUT

パクリ

下記のファイルをコピーする.ただし,VBのnamespaceも使ってるようなので,少し綺麗にしたいと思た.ちうことで,VBのlength/CRLFだけを使っていたので,これを排除しただけなんですがね.

  • Debugging.cs
  • DebuggingDeclarations.cs
  • DeviceManagement.cs
  • DeviceManagementDeclarations.cs
  • FileIODeclarations.cs
  • Hid.cs
  • HidDeclarations.cs


device enumeration

detection of device attached/detattached

IN/OUT transaction check by using ReadFile/WriteFile



HostTest_02

Include all functions of HostTest_01.


メモ

device change

WM_DEVICECHANGEメッセージが通知される模様.標準でフックできないようなので,WindowProcedureをoverrideしてsniffする.

class DeviceManagement(In file DeviceManagement.cs)

attached/removed検出
登録: RegisterForDeviceNotifications()
停止:StopReceivingDeviceNotifications()
DeviceManagement::Boolean DeviceNameMatch( Message m, String mydevicePathName )

WM_DEVICECHANGEメッセージを受けて,pathnameとマッチするかチェックする.マッチする場合はtrueを返す.

DeviceManagement::Boolean FindDeviceFromGuid( System.Guid myGuid, ref String[] devicePathName )

Uses SetupDi API functions to retrieve the device path name of an attached device that belongs to an interface class.


SetupDi APIを使って,interface classに属する接続されたdevice path nameを検索する.


参照資料

★MSDNより,C#で Num Text boxの作成 - 派生させてHex Edit boxでも作れ..~ 入力: hexのみ, 出力:':'区切りで表示, nibbleでfocus失うなら捨てる. 入力中は文字色変えるとか.

http://msdn.microsoft.com/ja-jp/library/ms229644(VS.80).aspx http://msdn.microsoft.com/en-us/library/ms790920.aspx http://msdn.microsoft.com/ja-jp/library/cc429201.aspx

USB keyboardのテスト

2008/08/28工作::USBimport

USB keyboardの話

HIDとして,キーボードとマウスは抑えておきたいところである.そこで,キーボードについて,仕様ではよくわからなかった動作について確認する.PCやOSに依存するかもしれないので,ここで記述する事項は実際に試したこと,推測(妄想)事項であることを明記しておく.
何らかの明確な動作に関する資料が開示されているのであれば,ポインタを教示いただきますと幸いです.

実験と確認

先日の疑問について,実装して確認する.
デバイス側のマイコンから,キーコード(usage ID)を送信し,PC側でどういう挙動を示すかを調べる.

(1)	{0x00, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(3)	{0x00, 0, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A },
(4)	{0x00, 0, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06 },
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space

	結果.
	"abcdefg "の繰り返しとなる.
	 456789a

	"押している"情報であることがわかる.
	(1)-(2)で 'a'を2回送っていることになるはず.(2回数はshift押下)
	(3),(4)で並びを変えてみたが, 反応ナシ.
	(5)で全部離したと認識して, "bcdefg"をinput.
	このとき,押下情報(3)の若い順に入力されたと考えられる.(並びを変えて確認要)

	また,別キーボードにてshiftを押下したところ,押下中は文字サイズが変わった.

# 教訓.スキップせずにコツコツと進みましょう:)

"abcdefg "....

(1)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x00, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(3)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(4)	{0x00, 0, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06 },
(5)	{0x00, 0, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00 },
(6)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	"adefgbc "で繰り返された.
	(1) 'a'を押下,
	(2) 'a'を押下しながら shift押下
	(3) 'a'とshiftを同時に離す. 
	 → (shiftはキーの前後でon状態を保つ必要がある? 少なくとも入力時に同時か一つ前?)
	(4) d,e,f,g,b,c を押下
	(5) 'g'だけ離す...
	(6) b-fを離して, spaceを押す.


(1)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x01, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(3)	{0x01, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(4)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00 },
(7)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(8)	{0x00, 0, 0x05, 0xC6, 0x00, 0x00, 0x00, 0x00 },
(9)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(A)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	^a
	^a
	def
	0xC4/0xC6は無視されたぽいな..
	b
	<space>


!ここでReport descriptorのUsage Maxが 0x65なのに気づく.
0xE7とすることで,定義値全て有効になるはず..

(1)	{0x02, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(2)	{0x02, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(3)	{0x02, 0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },
(4)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // shift入れてみる
(5)	{0x00, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // nothing
(6)	{0x00, 0, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00 },
(7)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(8)	{0x00, 0, 0x05, 0xC6, 0x00, 0x00, 0x00, 0x00 },
(9)	{0x00, 0, 0x05, 0xC6, 0xC4, 0x00, 0x00, 0x00 },
(A)	{0x00, 0, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00 },

	ならなかったなぁ.
	AAdefb "Shift"は同時に離しても,跡で開放でも良いみたい.

min.max.を 0x80 - 0x7Fにしてみた.
	→値全部無視された.SHIFTのみに反応して,"固定キー機能"ダイアログが出てくる.

0x00 - 0x00E7にしてみたが,駄目だな. 
keypadになると,usage sub-IDが変わってくるので,無視されるのだろう.
table中,keyboard/keypadと明記されていたのはコレによるものと思われる.
分けてくれよ...

utility関数の作成

usage IDとASCIIコードとはテーブル引きするしかなさそう.US keyboardをベースにしているらしく,日本語keyboardとは異なるマップと考えるしかない.また,SHIFT/CTRL等の情報は文字とは別です.
前述の結果より,本I/FでPCが受信するのはキーの押下情報であり,入力された文字情報ではないです.文字入力の肩代わりをさせる場合,ほかのキーボードとの干渉を考慮する必要がありそうです.
ゲームの入力装置として考える場合は,押下情報であったことは良いことでしょう.同時押し6つまで認識してくれそうです.(SHIFT/ALT/CTRLは別腹で同時押し可)

ASCII文字 - 0x20を index0として,下記のIDを送ると良い.
ただし,"SHIFT+"は,SHIFTを押下しながら文字を入力した場合であり,単純に1倍との送信では実現できない.

0x2C, SHIFT+0x1E, SHIFT+0x34, SHIFT+0x20, SHIFT+0x21, SHIFT+0x22, SHIFT+0x24, 0x34, SHIFT+0x26, SHIFT+0x27, SHIFT+0x25, SHIFT+0x2E, 0x36, 0x2D, 0x37, 0x38,
	// 0x20~0x2F, → <SPC>!"#$%&'()*+,-./
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, SHIFT+0x33, 0x33, SHIFT+0x36, 0x2E, SHIFT+0x37, SHIFT+0x38
	// 0x30~0x3F, → 0123456789:;<=>?
SHIFT+0x1F, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
	// 0x40~0x4F, → @ABCDEFGHIJKLMNO
	// 0x89 : Keyboard International3(17) => '\'キー
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x2F, 0x31 ,0x30, SHIFT+0x23, SHIFT+0x2D,
	// 0x50~0x5F, → PQRSTUVWXYZ[\]^_
0x34, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
	// 0x60~0x6F, → `abcdefghijklmno
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, SHIFT+0x2F, SHIFT+0x31, SHIFT+0x30, SHIFT+0x32, 0x2A
	// 0x70~0x7F, → pqrstuvwxyz{|}~<DEL>


複合デバイスの作成

作り方

PSoC環境を使う限り,自動的にInterface数を把握して,standard requestに応答してくれる模様.便利ですな.. *1

  1. Descriptorにinterfaceを追加する.
  2. EPを追加する.
  3. Report descriptorを追加する.

メモ
PSoCのEPは,入出力で同じIDが使えない?simple IOの実装でEPを1/1または3/3としたときに,IN応答が無かった.OUTを受けてからIN transactionを起こしていたので,先に処理したモン勝ちか?詳細はPSoCのTRMで確認する予定.
【宿題】の結果,下記の記述が見つかりました.

PSoC TRM, Document No. 001-14463 Rev. **
34. Full-Speed USB

The SIE supports five endpoints including a control endpoint (endpoint 0) and four data endpoints (endpoint 1, 2, 3, and4).
The control endpoint can be configured to support SETUP, IN, and OUT requests.
The data endpoints can be individually configured to respond to Interrupt, Bulk, or Isochronous IN or OUT requests.

ということで,EP1~4は,INかOUTのいずれか1つしか取れません.したがって,インタフェースIN/OUTを2つ用いるデバイスでは,EPも2つ消費します.入出力対応しているEPであれば,EP数を削減できたのですが.まぁ,物理的な制約であり,仮に入出力OKでも,IDが経るなら同じなので,こんなもんなんでしょう.
キーボード,マウス,+α(入出力)とするならば,キーボードのLED出力は受け取れないということですね.

デバッグ・お試し時のメモ

PID/VIDが同じだと,Windows Device ManagerがInterfaceを覚えているようだ.
複合→単純に変えたとき,2度目以降は複合として扱われた.
Device Manager → USBコントローラ の 該当するVID/PIDの複合デバイスを削除することで,再度認識してくれるみたいです.


*1 : 仕組みを理解する上では,手抜きになってしまうなぁ.

参考サイト



wiki機能でコンテンツにしているけれども,まとまってないな...
日々書き散らかしてまとめていないからかなぁ.使い方間違ってる?w