So-net無料ブログ作成

JB16ボードでシリアル→キーボードガジェットを作る(作った!) [USB]

P1010002.jpg久しぶりの開発物。
例のJB16 USBマイコンボードを使って、シリアル→キーボードブリッジみたいな物を作りました。
キーコード参照テーブルも前回から修正が入っています。
シリアルのボーレートは38400bps、8ビット長、ストップビット1、ノンパリティ、ターミナルソフトと、大量に送るなら、XON/XOFFのフローコントロールが必要です。


下の図はTERATERMから文字を投げてみました。一台のパソコンでやるとループするので、文字が増殖していきます(笑)。
serial_key_001.png


右クリックで落して、拡張子をzipに変更してください。
serial2key.zip

☆でたらめ☆LOW SPEEDデバイス(HID)のインタラプト転送の周期を1msにしてみた [USB]

hid_in_timig_03.pngTsuneoさんからのアドバイス(*´ー`) に従って、エンドポイントディスクリプタのポーリング周期を書き換え、通常10ms(実際は8ms)を1msにしてみました。


書き換える場所は”usb_descriptors.c”の多分69行目の以下の行
10 // Polling Interval (Interrupt) in ms
これを
1 // Polling Interval (Interrupt) in ms
とします。これだけ。

まず2Kマシンでやってみました。
それで動かした結果が上のキャプチャなのですが、半周期が1msとなっている事が判ります。
ただし常に1msと言う訳ではなく、流石にJB16マイコンにも1msの割り込みを取りこぼし無く処理するのがきついと思われ、偶に2msになったりもします。
しかしタイピングは早いです。

今度はXPマシンでやってみました。
hid_apli_result_004.png明らかにこちらはタイピングが遅いです。周期も8msに戻っています。

つまり2Kはこの点に関してもルーズで、XPはスペックを遵守していると言えるのでしょう。
この結果はOSやハードウエア等に大きく依存しますので、一つのオプションとして考えてください。




追加
どうせ3byteしか有効なデータは無いのだから、同じ”usb_descriptors.c”のエンドポイントディスクリプタのエンドポイントのサイズを変更してみました。
{0x08, 0x00}, // Max. Endpoint Packet Size

{0x03, 0x00}, // Max. Endpoint Packet Size
しかし結果は全然駄目です。メモ帳に文字がタイプされません。一体どこで止まっているのか原因は不明です。

HIDキーボード(もどき)プログラムで機能アップ [USB]

P1010002.jpg従来型は大文字が有っても小文字に変換されてしまったので、今度は大文字、小文字を区別するように改造しました。改造したプログラムだけ掲載します。


/****************************************************************************/
/* 英字の大文字/小文字に対応した文字列を送信する処理                        */
/* 今度はバッファリングしていないので、最大長の制限無し                     */
/****************************************************************************/
void Str2PC2( const char *str )
{
  int i;
  unsigned char code,shift;
  char old;

  (void)memset( &KbBuffer[0], 0, 8 );  /*一度バッファ全てをクリアする*/

  for( i = strlen( str ), old = 0; i > 0; )
  {
    if( search_from_tbl( &code, &shift, *str ) == 0 )  /*該当コードが見つかった時*/
    {
      wait();
      if( code != old )  /*前回と異なる時*/
      {
        if( shift != 0 ) KbBuffer[ 0 ] |= LEFT_SHIFT;
        else KbBuffer[ 0 ] &= ~LEFT_SHIFT;

        KbBuffer[ 2 ] = code;
        str++;
        i--;
      }
      else
      {
        KbBuffer[ 0 ] = 0;
        KbBuffer[ 2 ] = 0;
      }
      old = KbBuffer[ 2 ];  /*送信したデータを記憶して置く*/
    }
    else
    {
      str++;  /*該当コードが見つからない時*/
      i--;
    }
  }

  wait();
  KbBuffer[ 0 ] = 0;
  KbBuffer[ 2 ] = 0;
}

送信した元文字は以下の通り
static const char abc[] = "AaBbCcDdefghijklmnOPQRSTUVWXYZ\r";
hid_apli_result_003.png左はその結果です。取り敢えずOKと言う事で。



※キーボードデバイスのデバックはなかなかスリリングです。止せば良いのに、開発機と実験機が同じな為、キーボードデバイスのプログラムを失敗して暴走すると、判っていても思うようにキーが効かないとか、全然入力できなかったりとか、、、本当に止せば良いのですけれどね(*´ー`) 。
さあ!皆さんもJB8、JB16ボードで是非スリリングな体験をしてみましょう。

HID(キーボードもどき)で一文字ずつ送ってみた。 [USB]

hid_apli_result_002.pngまるで昨日の結果と変わらない、「捏造?」と思われてしまうかも知れないけれど、新しいプログラムの結果です。以下の関数を書き換えてみました。


void Str2PC( const char *str )
{
  int i;
  char *ptr;
  char old,dst[ 40 ];

  (void)Str2Keycode( dst, str );

  (void)memset( &KbBuffer[0], 0, 8 );  /*一度バッファ全てをクリアする*/

  for( i = strlen( str ), ptr = dst, old = 0; i > 0; )
  {
    wait();
    if( *ptr != old )  /*前回と異なる時*/
    {
      KbBuffer[ 2 ] = *ptr++;
      i--;
    }
    else
    {
      KbBuffer[ 2 ] = 0;
    }

    old = KbBuffer[ 2 ];  /*送信したデータを記憶して置く*/
  }
  wait();
  KbBuffer[ 2 ] = 0;
}

うーん!イメージとしては、6byteまとめての場合は一行一行がパッ、パッ、パッって表示されるんだけれど、このプログラムの場合は、やはり一文字ずつと言うのが目に見えて判ります。と言ってもタイピング速度は私なんかよりも遥かに早いのですが。

※もう一つ!
昨日のバッファ6byte使って送信するプログラムで”aaabbb”みたいなパターンが正常に入力されたのはWindowsの2Kでした。
先程同じプログラムをWindowsのXPでやってみたところ、”aaabbb”は”ab”と縮小されてしまいました。
と言う訳で、最初から1byteずつ送る方法が一番安全ですが、まとめて送る時は、バッファ中に同じデータが存在しない様に処理をする必要が有りますね。
2KとXPでこれだけ動作に違いが有るので、VISTAだったらどうなる事やら。持っていないから判らないけれど。

※更に更に追試
では”ababab”ならどうなるか?。XPでやってみましたら、”abababcdefghijklmnopqrstuvwxyz”となりました。
そこで勝手に推測すると、XPの場合はまずバッファの先頭から評価、ここで連続データは一定以上の連続で無い限りリピートとは判断せず、1個のデータとして見る。
しかしバッファの中で連続しないで同一データが配置されている時は、チェックがルーズなので、同一データとしては見ていない。ちなみに2Kはもっとルーズ。
あくまでも勝手な想像ですからね。

まだまだ続くぞ!多分。

HIDのバッファはあてにならないのか? [USB]

hid_apli_result_001.pngまあ確かに中途半端な知識でこれをやっていると言うのは事実ですが、もう少し色々検証してみたいと思います。

そもそもHIDデバイスか、否か、と言うのはチップで決まる訳ではなく、ディスクリプタの中でPC側に、「この様に扱って下さいね!」と宣言しているからで、エンドポイントのバッファが、デバイス側で順番に入れたデータがPC側に到着した時、順番が入れ替わっています!なんて事は有り得ないでしょう。そんな事では危なくてバッファなんて使えません。

左の図は以下のプログラムを動かした結果です。「abcd・・・」を100行分メモ帳に書かせて、順番の入れ替わりが無いか確かめてみました。
/****************************************************************************/
/* HIDでHello World!                                                       */
/****************************************************************************/

//Simple HID Keyboard Demo Code For ElectronicLaden USB08 board
//The 3 keys on the demo board emulated up/down or left/right arrow keys
//Compiled under CW for HCS08 Ver 5.0
//Jay, MJ Labs
//Modify the usb_descriptors.c for USB device identifiers

#include  /* for EnableInterrupts macro */
#include 
#include "derivative.h" /* include peripheral declarations */
#include "usb_lowlevel.h"

#define _CPU_CLOCK_  (12000000UL)
#define _BUS_CLOCK_  (6000000UL)
#define PERIOD_10R0ms  ((_BUS_CLOCK_ / 1 / 100) - 1)

typedef struct
{
  unsigned char ascii;
  unsigned char shift;
  unsigned char code;
} KEY_CODE;

/****************************************************************************/
/* 変数定義                                                                 */
/****************************************************************************/
volatile char KbBuffer[ 8 ];
unsigned char LedBuffer;
volatile char int_flg;
extern const KEY_CODE tbl109A[];
unsigned long systime;

/****************************************************************************/
/* 関数プロトタイプ宣言                                                     */
/****************************************************************************/
int search_from_tbl( unsigned char *code, unsigned char *shift, unsigned char c );
int Str2Keycode( char *dst, const char *src );
void Str2PC( const char *str );

/****************************************************************************/
/* ソフトウエアwait                                                         */
/* インタラプト転送のタイミングでフラグが1になるので、それまで待つ。        */
/****************************************************************************/
static void wait( void )
{
  while( int_flg == 0 ) ;
  int_flg = 0;
}

/****************************************************************************/
/* rel_wait                                                                 */
/* 相対時間の待ちを行う。単位は10ms。                                       */
/* ※何時かはオーバーフローして正しく動かなくなるが、それは1年以上先。      */
/****************************************************************************/
void rel_wai( unsigned long reltim )
{
  unsigned long next = systime + reltim;

  while( systime <= next ) wait();
}

/****************************************************************************/
/* 文字列をキーコードに変換する。                                           */
/****************************************************************************/
int Str2Keycode( char *dst, const char *src )
{
  unsigned char code,shift;

  while( *src )
  {
    if( search_from_tbl( &code, &shift, *src++ ) == (-1) ) return (-1);
    *dst++ = code;
  }
  *dst = 0;

  return 0;
}

/****************************************************************************/
/* 文字列を送信する処理                                                     */
/* 文字列の最大長は40文字とする                                             */
/****************************************************************************/
void Str2PC( const char *str )
{
  int i;
  char *ptr;
  char dst[ 40 ];

  (void)Str2Keycode( dst, str );

  for( i = strlen( str ), ptr = dst; i > 0; i -= 6 )
  {
    wait();
    (void)memcpy( &KbBuffer[2], ptr, (i < 6) ? i : 6 );
    ptr += 6;

    wait();
    (void)memset( &KbBuffer[2], 0, 6 );
  }
}

/****************************************************************************/
/* main                                                                     */
/****************************************************************************/
void main( void )
{
  int i;
  static const char abc[] = "aaabbbcdefghijklmnopqrstuvwxyz\r";

  CONFIG = 0x21;	// USB Reset Disable, COP Disable
  T1SC = 0x00;	// clear TSTOP, Prescaler=0

  T1SC = 0x20;     /*0b0010 0000 タイマー停止、system clock / 1*/
  T1MOD = PERIOD_10R0ms;  /*周期設定*/
  T1SC_TOIE = 1;   /*オーバーフロー割込みの有効化*/
  T1SC_TSTOP = 0;  /*タイマースタート*/

  DDRD |= 0x20;		// init LEDs
  PTD |= 0x20;

  initUSB();		/*USBレジスタの初期化*/
  (void)memset( KbBuffer, 0, 8 );

  EnableInterrupts  /*割込み許可*/

  rel_wai( 200 );  /*2秒間の待ちを入れる*/

  KbBuffer[0] = 0x08;  /*左GUI、つまりWindowsキー*/

  wait();
  (void)memset( KbBuffer, 0, 8 );

  wait();
  KbBuffer[2] = 0x15;  /*Rのタイプ*/

  wait();
  (void)memset( KbBuffer, 0, 8 );

  wait();
  Str2PC( "notepad\r" );  /*メモ帳の起動*/

  wait();
  (void)memset( KbBuffer, 0, 8 );

  rel_wai( 100 );  /*1秒間の待ちを入れる*/

  for( i = 0; i< 100 ;i++ )
    Str2PC( abc );  /*文字の書き込み*/

  for( ; ; ) ;
}

/****************************************************************************/
/* タイマー1割込み                                                          */
/* 10ms周期                                                                 */
/****************************************************************************/
void interrupt VectorNumber_TIM1Ovr Int_TIM1_Ovr()
{
  T1SC_TOF = 0;	/*clear status*/
  systime++;  /*システムタイマーの更新*/
}

/****************************************************************************/
/* end of file                                                              */
/*                                                      designed by hamayan */
/****************************************************************************/

結果は、100行全て正しく記述できています。

面白いのは、一回の送信でなら、同じキーコードが連続した分、メモ帳にも書かれている点です。
先頭の”a”と”b"が連続しているのが判ります。"aaabbb"なので、この部分が丸ごと6byteのバッファに収められてPC側に送信された事になります。

もしこれが人間の入力なら、複数のキーを同時に(実際には時間差が有って当然)押した時の順番なんて判らないのですから、順不同が当然です。
しかし今回キーコードを生成しているのはマイコンですから、バッファにデータを詰める順番には十分意味が有ります。
そして、このデータを受ける側のPCもまたコンピュータなのですから、順番に入ってきたデータを、順不同で評価するなんて事もわざわざやらない限りは無いでしょう。

勿論これは結果を元にしたフィクションなのですが。

HIDでHello World [USB]

P1010002.jpgUSBのWindows側のプログラミングにどっぷり嵌る前に、適当なHIDデバイスアプリケーションを試してみようと言う話。

オリジナルはnoritanさんの所で公開されているHIDアプリケーションをベースにやっています。

JB16のエンドポイント1には8byteのバッファが有りますが、キーボードデバイスとして使用した場合、先頭の1byteにはシフトキーやコントロールキーの状態が入ります。
bit7:右GUI、つまりプロパティキー
bit6:右Alt
bit5:右シフト
bit4:右コントロール
bit3:左GUI、つまりWindowsキー
bit2:左Alt
bit1:左シフト
bit0:左コントロール

またキーコードが入る領域は3byte目から8byte目までの6byteとなります。
キーコードは、Make/Breakを表現する為に、コードを転送した後は0を転送しています。これは、同じコードを送りつづけているとリピートとは判断してくれないからです。
例えばAの文字を2回送る時は、A→0→A→0と送る事となります。

プロジェクトファイルは、拡張子をZIPに変更してから解凍して下さい。

※しかしこの事が意味するのは、HIDデバイスって危険な香りがするという事かな。
※なお、キーリピートも含めてキーボードのエミュレーションは現在研究中ですので、内容が修正される事も有ります。
特にバッファの使い方に付いては、実際のキーボードのパケットを覗いてみたいなぁ。



※Low Speedのインタラプト転送の周期は10msではない!。
以下のキャプチャ画面が、INエンドポイントのところでポートをON/OFFさせた波形です。一回の割り込みで極性を変えるので、1周期は割り込み2回分です。
hid_in_timig_02.png
普通10msで語られる事の多い周期ですが、実際には2の階乗で取られる事が多い!という話を詳しく以下のコメントでしてもらいました。キャプチャ画面も半周期(割り込み1回分)が約8msとなっている事が判るかと思います。
※あっ!間違ってACレンジで撮っちゃった。

第三回布教価格基板配布計画の計画 [USB]

USBプロジェクト - WindowsでHIDデバイスを扱う定石 (1)


ようやく、HIDデバイスを扱うためのPC側アプリケーションが書ける様になったので、HIDデバイスを操作するときの定石についてまとめておきます。


私がUSBでグダグダやっている間に、「新適当マイコン電子工作研究所」さんはどんどん進んでいるようです。素晴らしい。

マイコン電子工作ファンさん
http://6811.teacup.com/miconfan/shop
で販売していたHC08のUSBボードも売り切れてしまったようですし、そろそろ第三回布教価格基板配布計画でも立てますか。

JB16でUSBキーボードもやってみた [USB]

P1010002.jpg最初、プログラムを書き込んでUSBポートに接続!・・・しても動かない。
デバイスマネージャーで見ると、キーボードの筈なのに何故かマウスと仰っている。
ああそうか!、昨日のマウスのベンダーコードとプロダクトIDがそのままだから、PCは、「マウスのくせに訳が判らん動きをしやがって!」思っているんだな。

そこでプロダクトIDのみ適当にでっち上げてUSBポートに接続してみると。
おお!無事に認識されている。
今度はボタンを矢印キーに割り当てているから、適当なアプリケーション上のカーソルの動きを見てみると、、、イマイチ長押し時の動きが決まらない。ユーザーインタフェースだってなかなか侮れないよね。

いやいや、でも面白くなってきた。
キーボード作りたくなって来ましたぞ!。ついつい松原さんの本も買ってきてしまったし。

※こうなって来るとUSBバスアナライザとか欲しくなって来る訳ですが、個人じゃあ市販品は購入できない。
いしかわきょーすけさんのIKusbmonでも作ろうか。

USB機器の製作―わかるマイコン電子工作 (わかるマイコン電子工作)

USB機器の製作―わかるマイコン電子工作 (わかるマイコン電子工作)

  • 作者: 松原 拓也
  • 出版社/メーカー: 電波新聞社
  • 発売日: 2006/07
  • メディア: 単行本



USB 2.0とUSB On-The-Goを含むカスタムUSBデバイス開発のすべて USBコンプリート[第3版]

USB 2.0とUSB On-The-Goを含むカスタムUSBデバイス開発のすべて USBコンプリート[第3版]

  • 作者: ジャン・アクセルソン
  • 出版社/メーカー: 株式会社エスアイビー・アクセス
  • 発売日: 2006/10/20
  • メディア: 単行本



わしもJB16でUSBマウスをやってみた。 [USB]

P1010002.jpgnoritanさんありがとう!。noritanさんのUSBプロジェクトのページ
こんなに簡単にマウスができるとは、、、あまりにも呆気無く動いてしまったので、しょうがないから加速機能も入れてしまいました。
※写真の液晶は使っていません。勿論使う事も可能ですが。

フリスクのHC08 USBボードは、マイコン工作ファンSHOPで購入できます。
http://6811.teacup.com/miconfan/shop
フリスクのUSBマイコンの開発方法の詳細はマイコン工作の実験室で得られます。
http://www.cts-net.ne.jp/~kawano-r/

JB16開発ボードは、要望が多ければなんか考えます。