さて、先ずはOpenScopeMZがどのように通信をしているかを説明します。
OpenScopeMZをただのオシロスコープとして使用するだけであるなら、WiFiテザリングが可能なアンドロイド携帯にWaveFormsアプリをダウンロードし、ワイヤレスオシロスコープとして使用すればいいのですが、普通の人はデータを測定し、保存・解析がしたいと思います。そのためにはPCを使う必要があり、PCでWiFiテザリング機能を持っているのはまれなため、基本的にはWiFiルーターを介してデータをやり取りする形になります。
OpenScope MZとPCがそれぞれWiFiルーターにアクセスし、PCとOpenScopeに割り当てられたIPアドレスを使いWiFiルーターを経由してデータのやり取りをします。
これが、とても使い辛い。
例えば、何らかの原因でPCからOpenScopeMZにアクセスできなくなった場合、何が原因で切れてしまったのかがわからない。そして、再接続するたびにOpenScopeMZに割り振られるIPアドレスが変わってしまう可能性もある。(実際にはソースコードの一部分を変更することでIPアドレスを固定することは可能。)
そこで、直接PCとOpenScopeMZを接続し、通信することでその問題に対処することを考えます。
その時、OpenScopeMZをWiFiルーターの様に親機として機能させるモードがsoftAPモードになります。
さて、MRF24のデータシートを確認したいのですが、残念なことにどのようにプログラミングすれば、モードを変更し、データをやり取りするのかが公開されていません。
MRFのプログラムインターフェースはOpenScopeMZを開発しているDigilent 社の deIPcKライブラリによって提供されていて、動き方は下のようなフローチャートになります。
先ずは、WiFi機能を初期化し、接続し、ネットワークを確立するところまで行い、その後にTCPソケット通信でデータをやり取りします。(TCPの他にUDPという通信方法も考えられますが、今回のような遅延やデータの欠落が許されていない使用目的の場合には、データが相手まで届くことを確証しないUDP通信は適していません。)
ここでは、WiFi Adaptorとしてクラスを宣言し、WiFiルーターに経由する方法と自分がWiFiルーターになる方法があります。しかし、残念ながら、OpenScopeMZのファームウェアのライブラリフォルダの中にあるWiFi.ccp及び、deIPcKライブラリの中にはWiFiルーターに経由する方法の関数しか記述されていない...!(ように見える。)
そこで、MRF24のライブラリコードからリバースエンジニアリングし、コードの動作を理解し、直接MRF24を動かすコードを作成することにします。(思った以上に難易度が高いなあ...汗)
MRF24のコードはOpenScopeMZのlibrariesフォルダの中に格納されています。
さて、問題となるコードはWiFi Adaptorクラスの IsInitailized関数の中にあり、そのコードが下記になります。
ふーむ、、汗
static bool IsInitialized(IPSTATUS * pStatus)
{
// we ONLY DO THIS ONCE
static bool fInitSetup = false;
AssignStatusSafely(pStatus, wfmrf24.priv.initStatus);
// Run the task because we might not be in the Adaptor yet
WF_Task();
if(!fInitSetup && wfmrf24.priv.initStatus == (InitMask | WF_INIT_SUCCESSFUL))
{
uint8_t channels[] = {};
t_scanContext scanContext = {WF_ACTIVE_SCAN, 1, 200, 400, 20};
WF_RegionalDomainSet(WF_DOMAIN_FCC);
WF_NetworkTypeSet(WF_NETWORK_TYPE_INFRASTRUCTURE);
WF_ChannelListSet(channels, sizeof(channels));
WF_ReconnectModeSet(3, WF_ATTEMPT_TO_RECONNECT, 40, WF_ATTEMPT_TO_RECONNECT);
WF_ScanContextSet(&scanContext);
// fixup the MAC
if(memcmp(&wfmrf24.adpMRF24G.mac, &MACNONE, sizeof(MACADDR)) == 0)
{
WF_MacAddressGet((uint8_t *) &wfmrf24.adpMRF24G.mac);
}
else
{
WF_MacAddressSet((uint8_t *) &wfmrf24.adpMRF24G.mac);
}
// set up the hardware filters
//WF_SetHwMultiCastFilter(WF_MULTICAST_FILTER_1, (uint8_t *) &wfmrf24.adpMRF24G.mac);
WF_SetHwMultiCastFilter(WF_MULTICAST_FILTER_2, (uint8_t *) &MACNONE);
// we are done
fInitSetup = true;
}
return(wfmrf24.priv.initStatus == (InitMask | WF_INIT_SUCCESSFUL));
}
ここでネットワークタイプが初期値はWF_NETWORK_TYPE_INFRASTRUCTUREと宣言されているので、ここを変更すればいいと思うのだけどれも、
// see WF_SetNetworkType()
typedef enum t_networkType
{
WF_MIN_NETWORK_TYPE = 1,
WF_NETWORK_TYPE_INFRASTRUCTURE = 1,
WF_NETWORK_TYPE_ADHOC = 2,
WF_NETWORK_TYPE_P2P = 3,
WF_MAX_NETWORK_TYPE = 3
} t_networkType;
あれ、ここの記述にもそもそもsoftAPモードが見当たらない。
softAPモードの数値はMRF24のデータシートでは4に割り当てられているようなので、
仕方がないので、networkTypeにsoftAPモードを追記する。
// see WF_SetNetworkType()
typedef enum t_networkType
{
WF_MIN_NETWORK_TYPE = 1,
WF_NETWORK_TYPE_INFRASTRUCTURE = 1,
WF_NETWORK_TYPE_ADHOC = 2,
WF_NETWORK_TYPE_P2P = 3,
WF_NETTWORK_TYPE_SOFTAP = 4, // 20190216 modified by chino
WF_MAX_NETWORK_TYPE = 4 // 20190216 modified by chino
} t_networkType;
さて、あとはネットワークリージョンもFCC(アメリカ)になっているので、JAPANに変更する。
これは、ちゃんと宣言されている。
// See WF_SetRegionalDomain()
typedef enum t_regionalDomain
{
WF_DOMAIN_FCC = 0, // Available Channels: 1 - 11
WF_DOMAIN_ETSI = 2, // Available Channels: 1 - 13
WF_DOMAIN_JAPAN = 7, // Available Channels: 1 - 14
WF_DOMAIN_OTHER = 7 // Available Channels: 1 - 14
} t_regionalDomain;
次回に状態遷移図を作って、どのように動かすかを検討する。