Lynx-EyEDの電音鍵盤 新館

広帯域制御屋の駄文とか

W5500でTCP/IP:send() , recv()をそれぞれ独立に行う

W5500でTCPソケット送受信をそれぞれ独立にしたい

ArduinoでもすっかりおなじみになったWiznetのSPI-PHYシリーズですが、思い出しては忘れを繰り返すので、自分への開発時短効果を期待してメモがわり。

W5100/5200/5500のioLibraryドライバ
GitHub - Wiznet/ioLibrary_Driver: Create a repository of WIZnet ioLibrary.

これを自分の使ってるマイコンに移植して、こんな感じで動かすと思います。

#include <____my_mcu_headers____.h>
#include "socket.h"
#include "loopback.h"	


/////////////////////////////////////////
// SOCKET NUMBER DEFINION for Examples //
/////////////////////////////////////////
#define SOCK_TCPS        0
// ....

///////////////////////////////////
// Default Network Configuration //
///////////////////////////////////
volatile wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0xAB, 0xCD, 0xEF, 0x01, 0x23},
                            .ip = {192,168,1,111},
                            .sn = {255,255,255,0},
                            .gw = {192, 168, 1, 1},
                            .dns = {0,0,0,0},
                            .dhcp = NETINFO_STATIC};

							
// 	(中略)
int main(void){

	int32_t ret = 0;
    uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};


// 初期化処理もろもろ

    
	for(;;) {
	
        if( (ret = loopback_tcps(SOCK_TCPS, gDATABUF, 5000)) < 0) { // Port=5000 (= 192.168.1.111:5000)
			printf("SOCKET ERROR : %ld\r\n", ret);
		}

// ......
	}
}

こんな感じでloopback_tcpsをポーリングで動かしてるとおもいます。
loopbackサンプルプログラムを動かして喜んでそのまま積み基板化することが多いのですが、
loopbackのサンプルプログラムを元にsend(), recv()を独立に動かすの、前知識なしではしんどい。

前知識:TCPの状態遷移図
基礎から学ぶWindowsネットワーク:第16回 信頼性のある通信を実現するTCPプロトコル(3) (3/4) - @IT

でもほかにリソース割かなくてはならないし読んでられないよ...何のためにWiznet(ryなので、loopback.cのloopback_tcps()を下記に示すコードに置き換えるだけでrecv(),send()のみできるプログラムを急ごしらえで作成しました。
send/recvの同時発生でバッファの内容を破壊しないような配慮はしてないので各自で書き換えてほしい。

bufに文字列がある場合、文字列をsend()します。bufが空の場合(buf[0]='\0')受信データがあるか確認し、あったらrecv()します。ループバックはしません。なので関数名がおかしくなります。はい。ちゃんと直せよ(殴

#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
   int32_t ret;
   uint16_t size = 0, sentsize=0;
#ifdef _LOOPBACK_DEBUG_
   uint8_t destip[4];
   uint16_t destport;
#endif

   switch(getSn_SR(sn))
   {
      case SOCK_ESTABLISHED :
         if(getSn_IR(sn) & Sn_IR_CON)
         {
#ifdef _LOOPBACK_DEBUG_
			getSn_DIPR(sn, destip);
			destport = getSn_DPORT(sn);

			printf("%d:Connected - IP:%d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
			setSn_IR(sn,Sn_IR_CON);
         }
		 if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
         {
			if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
			ret = recv(sn, buf, size);
	        if(ret <= 0){
                return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
            }
//            sentsize = 0;
//            while(size != sentsize)
//			{
//				ret = send(sn, buf+sentsize, size-sentsize);
//				if(ret < 0)
//				{
//					close(sn);
//					return ret;
//				}
//				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
//			}
         }else if((size = getSn_TX_FSR(sn)) > 0){
         
            size = strlen((const char*)buf);
            sentsize = 0;
			while(size != sentsize)
			{
				ret = send(sn, buf+sentsize, size-sentsize);
				if(ret < 0)
				{
					close(sn);
					return ret;
				}
				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
			}
        }
         break;
      case SOCK_CLOSE_WAIT :
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:CloseWait\r\n",sn);
#endif
         if((ret = disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOPBACK_DEBUG_
         printf("%d:Socket Closed\r\n", sn);
#endif
         break;
      case SOCK_INIT :
#ifdef _LOOPBACK_DEBUG_
    	 printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port);
#endif
         if( (ret = listen(sn)) != SOCK_OK) return ret;
         break;
      case SOCK_CLOSED:
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:TCP server loopback start\r\n",sn);
#endif
         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:Socket opened\r\n",sn);
#endif
         break;
      default:
         break;
   }

   return 1;
}


main関数などからループで呼び出してやればOK。
send()したい文字列があればbufにそのポインタを指定し、なければ空のバッファのポインタを指定しておく
呼び出し後にbufの中身を消しておくのを忘れずに。


PQI Air Pen向けにmips-linux-gnu-gccをソースビルドした話

事の発端

年末にNTT-XストアでPQI Air Penが破格の値段でした。
これ、有線/無線でFTPサーバーになるWi-Fiアダプタなのですが、なにより、弄り倒し甲斐のあるLinuxが入ったMIPSマイコンボードな訳です。
nttxstore.jp

そして心強いmoyashi兄さんのブログ
hitoriblog.com

もう買うしかない。正月休みに遊ぶネタが出来たわけです。
飽きてもこれだったら部屋のWiFiルータにはなります。
f:id:Lynx-EyED:20170113134645p:plain

で、クロスコンパイラはSourcery CodeBench Lite Edition for MIPS GNU/Linuxがあるので別に必要ないのですが、

Ubuntu xenial(16.04LTS)はgcc-5-mips-linux-gnuが提供されているのでこれでビルドし、PQI Air Penで動作させようとすると、

~ #./a.out

FATAL: kernel too old
Bus error

~ #

致命的エラー:カーネルおじさんめっちゃ老けてるぞ

よーし、一人だけgcc野良ビルドする苦行2017選手権やるか
正月休みにおすすめしたいとても有益な時間の浪費方法です。絶対やめた方がいい。おすすめです。
Rなんとか社のRXマイコンの時は会社でも家でも散々野良rx-gccビルド大会してましたね。このブログのアクセス解析が某軽子坂からのアクセスだらけになってたのはいい思い出です。あんな共用体地獄ライブラリ付きうんこマイコン金輪際ビルドしてやらねぇ。


息をするように野良ビルドするのも考え物ですがカーネルバージョンに合わせて自分でビルドできるので、時には必要な事もあるのかも。
まず、PQI Air Pen(ファームウェアはv0.1.24に変更済み)のカーネルを確認します

~ # cat /proc/version 
Linux version 2.6.31.AirPen_V0.1.22-g5eca71a (dio@dio) (gcc version 4.3.3 (GCC) ) #324 Thu Feb 7 17:36:23 CST 2013
~ # 

なので、Kernel2.6.31か、それより以前のカーネルヘッダでクロスコンパイラを作った方が良さそうです

mips-linux-gnuのビルド

ホスト
ビルドおよび動作確認したのは以下の環境です

ubuntuはメインで使っている14.04で動くことを目指しました。(結局16.04でもビルドできた。詳細後述)
16.04LTSいろいろ難しい…

どちらも前もってインストールしておくパッケージ

$ sudo apt-get update
$ sudo apt-get install build-essential m4 gawk g++ make


GCCビルド成功した組み合わせ

GMP,MPC,MPFRを別個にwgetしてもいいのですがGCCフォルダ内の

contrib/download_prerequisites

を起動して自動取得しています。

Ubuntu 16.04LTSがbinutilsのビルドからこけやがる件

本当は根本的な解決をするべきなのでしょうが、よくわからないところで警告出してエラー終了しているので-Wno-errorで回避していまいます。

CFLAGS=-Wno-error
binutils-${BINUTILSVERSION}/configure (中略) --disable-warnings-as-errors

スクリプトかいた

出来てしまうと大したことはないのですが、すごくめんどくさいのと大したことないのは別問題なので(?)スクリプト書きました。めっちゃ適当に書いてるので、詳しい人書き直して。
ビルド前にmips-linux-gnuをすでにインストールしている場合はアンインストールするか、$PATHをunsetしておきましょう

#!/bin/bash -ev

# see https://www.linux-mips.org/wiki/Toolchains#Roll-your-own
# see http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/
# see also http://www.hs-augsburg.de/~beckmanf/dokuwiki/doku.php?id=mips_cross_compiler

export WDIR=$HOME/tmp
export TARGET=mips-linux-gnu
export PREFIX=$HOME/mips-cross
export TARCH=mips
export PATH="${PATH}":${PREFIX}/bin

# ------------------------------
# enviroments
# ------------------------------
echo ${WDIR}
echo ${TARGET}
echo ${PREFIX}
echo ${PATH}
# ------------------------------
mkdir -p ${PREFIX}
mkdir -p $WDIR
cd $WDIR
mkdir -p ${TARGET}-toolchain 
cd ${TARGET}-toolchain


# version
BINUTILSVERSION="2.24"
GCCVERSION="4.9.2"
#GDBVERSION="7.7"
ISLVERSION="0.12.2"
CLOOGVERSION="0.18.1"
#GLIBCVERSION="2.20"
#PORTSVERSION="2.20"
GLIBCVERSION="2.19"
PORTSVERSION="2.19"
#KERNELVERSION="3.17.2"
#KERNELVERSION="2.6.27.62"
#KERNELVERSION="2.6.32.60"
KERNELVERSION="2.6.30"


# wget
if [ ! -e "binutils-${BINUTILSVERSION}.tar.bz2" ] ; then
wget http://ftp.gnu.org/gnu/binutils/binutils-${BINUTILSVERSION}.tar.bz2
fi

if [ ! -e "gcc-${GCCVERSION}.tar.bz2" ] ; then
wget http://ftp.gnu.org/gnu/gcc/gcc-${GCCVERSION}/gcc-${GCCVERSION}.tar.bz2
fi

<< COMMENTOUT
if [ ! -e "gdb-${GDBVERSION}.tar.bz2" ] ; then
wget http://ftp.gnu.org/gnu/gdb/gdb-${GDBVERSION}.tar.bz2
fi
COMMENTOUT

if [ ! -e "linux-${KERNELVERSION}.tar.xz" ] ; then
# wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.27/linux-${KERNELVERSION}.tar.xz
# wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.32/linux-${KERNELVERSION}.tar.xz
# wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-${KERNELVERSION}.tar.xz
wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-${KERNELVERSION}.tar.xz
fi

# ----------------------
# wget kernel-headers
# ----------------------
if [ ! -d "linux-${KERNELVERSION}" ] ; then
tar -Jxvf linux-${KERNELVERSION}.tar.xz
fi

# ----------------------
# binutils
# ----------------------
if [ ! -d "binutils-${BINUTILSVERSION}" ] ; then
tar xjf binutils-${BINUTILSVERSION}.tar.bz2
fi


# ----------------------
# gcc
# ----------------------
if [ ! -d "gcc-${GCCVERSION}" ] ; then
tar xjf gcc-${GCCVERSION}.tar.bz2
fi

#-----------------------
# get infrastructure
# gmp, mpfr, gmp
#-----------------------
if [ ! -d "gmp" ] ; then
gcc-${GCCVERSION}/contrib/download_prerequisites
fi

# get isl
if [ ! -e "isl-${ISLVERSION}.tar.bz2" ] ; then
  wget  ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-${ISLVERSION}.tar.bz2
fi

if [ ! -d "isl-${ISLVERSION}" ] ; then
tar -xvjf isl-${ISLVERSION}.tar.bz2
fi

# get cloog
if [ ! -e "cloog-${CLOOGVERSION}.tar.gz" ] ; then
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-${CLOOGVERSION}.tar.gz
fi

if [ ! -d "cloog-${CLOOGVERSION}" ] ; then
tar -xvf cloog-${CLOOGVERSION}.tar.gz
fi

# get glibc
if [ ! -e "glibc-${GLIBCVERSION}.tar.xz" ] ; then
wget ftp://ftp.gnu.org/gnu/glibc/glibc-${GLIBCVERSION}.tar.xz
fi


if [ ! -d "glibc-${GLIBCVERSION}" ] ; then
tar -Jxvf glibc-${GLIBCVERSION}.tar.xz
fi
<< COMMENTOUT
# get glibc-ports
if [ ! -e "glibc-ports-${PORTSVERSION}.tar.bz2" ] ; then
wget http://ftp.gnu.org/gnu/libc/glibc-ports-${PORTSVERSION}.tar.bz2
fi

if [ ! -d "glibc-ports-${PORTSVERSION}" ] ; then
tar -xvjf glibc-ports-${PORTSVERSION}.tar.bz2
fi
COMMENTOUT

#ln -sf glibc-ports-${PORTSVERSION} glibc-${GLIBCVERSION}/ports  
# cd glibc-${GLIBCVERSION}
# ln -sf ../glibc-ports-${GLIBCVERSION} ports
# cd ..
# --------------------------------------------------------
# Build step 0: make symbolic link
# 				mpfr, gmp, mpc, mpfr, isl, cloog 
# --------------------------------------------------------
cd gcc-${GCCVERSION}
ln -sf ../mpfr mpfr
ln -sf ../gmp gmp
ln -sf ../mpc mpc
ln -sf ../isl-${ISLVERSION} isl
ln -sf ../cloog-${CLOOGVERSION} cloog
cd ..

# --------------------------------------------------------
# Build step 1: make Binutils
# 		configure & make & install 
# --------------------------------------------------------
mkdir -p build-binutils
cd build-binutils

if [ ! -e "config.status" ] ; then
CFLAGS=-Wno-error ../binutils-${BINUTILSVERSION}/configure --target=${TARGET} --prefix=${PREFIX} --disable-warnings-as-errors
fi

if [ ! -e "${PREFIX}/bin/${TARGET}-ld" ] ; then
make
make install
fi

cd ..

# --------------------------------------------------------
# Build step 2: make Linux Kernel Headers
# 		make headers_install 
# --------------------------------------------------------
cd linux-${KERNELVERSION}
make ARCH=${TARCH} INSTALL_HDR_PATH=${PREFIX}/${TARGET} headers_install
cd ..

# --------------------------------------------------------
# Build step 3: Build GCC but libraries
# 		make all-gcc && make install-gcc
# --------------------------------------------------------
mkdir -p build-gcc
cd build-gcc
../gcc-${GCCVERSION}/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --disable-multilib
make all-gcc
make install-gcc
cd ..
# --------------------------------------------------------
# Build step 4: Standard C library Headers and Startup Files
# 		make (removed --enable-add-ons=ports,  --disable-sanity-checks--with-tls --disable-versioning --disable-profile)
# --------------------------------------------------------
mkdir -p build-glibc
cd build-glibc
../glibc-${GLIBCVERSION}/configure --prefix=${PREFIX}/${TARGET} --build=${MACHTYPE} --host=${TARGET} --target=${TARGET} --with-headers=${PREFIX}/${TARGET}/include --disable-multilib libc_cv_forced_unwind=yes
make install-bootstrap-headers=yes install-headers
make csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o ${PREFIX}/${TARGET}/lib
${TARGET}-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o ${PREFIX}/${TARGET}/lib/libc.so
touch ${PREFIX}/${TARGET}/include/gnu/stubs.h
cd ..
# --------------------------------------------------------
# Build step 5: Compiler Support library 
# 		make 
# --------------------------------------------------------
cd build-gcc
make all-target-libgcc
make install-target-libgcc
cd ..

# --------------------------------------------------------
# Build step 6: Standard C library 
# 		make 
# --------------------------------------------------------
cd build-glibc
make 
make install
cd ..
# --------------------------------------------------------
# Build step 7: Standard C++ library 
# 		make 
# --------------------------------------------------------
cd build-gcc
make 
make install
cd ..

ビルドが無事終わったら忘れないうちに.bashrcにPATHを通しておいた方がいいと思います。PCはCore-i5 5200Uが乗っているWindows7ノートでやったのですが、
ビルド時間はubuntuのパッケージバージョンには関係なく
VMware環境 2時間半
デュアル環境 40分
でした。仮想環境結構遅いんだね。

#include <stdio.h>
int main(int argc, char *argv[]){

	printf("hello world.\nThis is PQI Air Pen.\n");
	return 0;

}

という何の変哲もないコードをhelio.cなどと保存し、

$ mips-linux-gnu-gcc -g -O2 -Wall -pedantic -march=24kc -static -o hello hello.c

とすれば、3MB以上もある巨大バイナリが完成する。(staticビルドだからしかたない)
これをmicroSDにコピーするか、FTP経由でPQI Air Penにアップロードする。
telnetPQI Air Penにログイン

hoge@ubuntu:~$ telnet 192.168.200.1
Trying 192.168.200.1...
Connected to 192.168.200.1.
Escape character is '^]'.
(none) login: root
Password: (パスワード:pqiap)


BusyBox v1.01 (2013.02.07-09:36+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ # cd /tmp/www/ftp/sda1/
/tmp/www/ftp/sda1 # ./hello
 hello world.
 This is PQI Air Pen.

/tmp/www/ftp # 

ncursesをtelnet使ってパイプする方法がわかればslコマンドでも、と思ったのですが、いかんせんよくわからず…
また時間のあるときに、Luaでもビルドしてみよう。

おしまい。


参考サイト

https://www.linux-mips.org/wiki/Toolchains#Roll-your-own MIPSロスコンパイラをビルドするのに最低限必要な内容
http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ Linux上で動作するクロスコンパイラをビルドのするのに必要な知識
http://www.hs-augsburg.de/~beckmanf/dokuwiki/doku.php?id=mips_cross_compiler bare-metalなMIPSコンパイラを作る時に必要な知識

NXPのUART-I2CブリッジSC18IM700でLチカ

すべての道はLチカに通ず

このチップの存在を知ったとき、あまり使うことはないかなとスルーしてたのですが、かなり使い道があると思ったのでちょっとだけ。
UARTさえあれば、プログラミングせずにI2Cデバイスと通信できるのでC言語とかVerilogとかぜんぜんぜんっ知らない僕でも使えちゃいます。ガハハハハ。
やめて石投げないで
気をつけるべきはRESETとWAKEUPの端子のプルアップくらいでしょうか。SC18IM700はデフォルトで9600baud、8N1で通信するので特に気にする部分もありません。って偉そうにいってSC18IM700の通信コマンド間違えてて動かない動かないと3時間唸っていたのでした。

とりあえずGPIOでも動かしてみる

SC18IM700+秋月のFT231XボードTeraTermからLチカしてみました。
なお、SC18IM700のリセット後、'OK'という文字が送信されます。SC18IM700が動作しないように思えるときはこの文字が受信できているかまず確認します。
もしできていれば受信はOKなので、I2Cバスのプルアップ・速度が問題か、GPIOが動作していないのであればPortConfの設定を見直せばいいことになります。
詳細はデータシート参照のこと

http://cache.nxp.com/documents/customer_presentation/NXP-Interfaces-and-Power-Solutions.pdf?fsrch=1&sr=1&pageNum=1

TeraTermからコマンド送信

FT231X(USB-UARTで5V/3.3V系ならなんでもOKのはず)のTX/RXをSC18IM700のRX/TXと接続します。写真は秋月FT231X基板とダイセン変換基板に載せたSC18IM700です。
f:id:Lynx-EyED:20161019195540j:plain
SC18IM700では文字データ以外の16進数も送受信するため、任意のバイナリデータを送受信できるようTeraTermの設定を変更します。
(1)debug=on にする
デフォルトでは C:\Program Files (x86)\teraterm\TERATERM.INI が設定ファイルになっていると思いますが、このINIファイルの

debug=off

の行を見つけ出し、(自分は475行目付近にあった)

debug=on

に書き換えて上書き保存する。

(2) 送受信エンコードSJISに変更する
設定(S) -> 端末(T) -> 漢字ー受信(K)と漢字ー送信(J)のエンコードを両者ともSJISに変更する
f:id:Lynx-EyED:20161019205826p:plain
(3) 16進表示モードに切り替える。
通信中にSHIFT + ESCを何回か押すと切り替わるはず。実動作に問題はないので切り替えは実際に通信が始まってからでOK

(4) 送信コマンドのマクロを書く
(例)UARTで0x12, 0x34 , 0x56を送信したい場合、

send		$12$34$56

とマクロファイル(.ttl)に記述すればいい。
今回は以下のように書きました

send $57$02$AA$03$AA$50 	; GPIO全ピンを出力モード(push-pull)にする
send $52$02$03$50		; GPIO config(PortConf1,PortConf2)をリードする

:blink
send $4F$00$50			; GPIOに0x00をライトする
send $49$50			; GPIOのピン状態をリードする(ライトした'00'がリードされるはず)
mpause 1000			; 1秒待つ
send $4F$FF$50			; GPIOに0xFFをライトする
send $49$50			; GPIOのピン状態をリードする(ライトした'FF'がリードされるはず)
mpause 1000			; 1秒待つ	
goto blink			; 繰り返し

上記のマクロをメモ帳などで記述し、 foobar.ttlみたいなファイル名で保存。
TeraTermのコントロール(O) -> マクロ(M)でfoobar.ttlを呼び出す。

TeraTermの画面はこうなるはず
f:id:Lynx-EyED:20161019204145p:plain
GPIO0~7にLEDをつけて確認すれば2秒周期でLEDがブリンクしているのが確認できるはず。

mbedで動かないものはデバイスに非ず

SC18IM700が動かずにウンウン唸っていたところ、非合法組織クソコード撲滅委員会北関東支部のクマーおさんに助けていただきました。
https://developer.mbed.org/users/okano/code/SC18IM700_GPIO_pin_operation_sample/file/16ad158dc535/main.cpp
ホントに助かりました。ありがとうございます。マヨネーズ反対!

I2Cは?

手元にI2Cデバイスがないので動作を確認できないのですが、オシロで信号を見てみました。TeraTermマクロは以下の通り。
I2Cアドレス0xA0に1バイトデータ0xAAを送信するマクロです。

send $53$A0$01$AA$50			; write I2C (S(0x53) + Address(W:LSB=0) + Num of Byte + DATA + P(0x50))
send $52$0A$50				; read I2C Status

信号波形。
f:id:Lynx-EyED:20161020113649p:plain
バイスが接続されていないので当たり前ですが、アドレスに対してACKが返ってきてないのでエラーで終わっています。この状態でSC18IM700のI2C Statusをリードすると、'F1'=I2C_NACK_ON_ADDRESS が返ってきます。詳細はデータシートの9.2.7参照。

次回は、本命のI2Cデバイスを動かしてみます

Radeon R4 が載ってる最強AMDタブレットBungBungame Photon 2を買った

今まで8インチWinタブを愛用してきたのですが、ここに来て色々行き詰まりを感じていました。
8インチは軽くて持ち運びも楽で価格も手頃でとても良いのですが、メールとかSNS確認以上のことをやろうとすると、画面サイズの制約やらハードウェアスペックの制約やらで少しつらい。

余りそんな事案があって欲しくはないのですが、客先で自社装置のファームを書き換えたりするのにやむなく組み込み開発環境を入れてありますが、最近は64bitのみの対応しかしていないものも増えてきています。
あとプレゼン資料を確認修正するのに、8インチタブレットで確認するのはちょっときつかったりします。

2015年冬のコスパ最強の10インチWinタブは?

ならば10インチ以上のタブレットか2-in-1でそこそこのスペック、となるわけですが、Surface Pro 3や少しスペックダウンしてもThinkpad10になるかと思いますが…ちょっと高くないかなー。

いつもチェックしているウィンタブさんで話題になっていたPhoton 2。
win-tab.net
AMDのAPU搭載クアッドコア。よくわからないけどスペック強いし訳分からなくてヤバそうだし4万円弱。こんな安くてハイスペックなマシンを望んでいたので即BungBungameにメールして購入方法を尋ね、金額を指定口座に振り込みました。
なお2015年12月現在、Photon2の取り扱いはAMD A6モデルのみのようです。

① PHOTON2 A6モデル (タブレットタッチペン付き) 【税込・送料無料】 39900円
② 上記①+キーボード+革ケース付き 【税込・送料無料】 44900円

どちらを頼んでもN-Trigなスタイラスペンがついてくる!やった!
自分は①を購入しました。スタイラスも固定できるタッチパッド付きのキーボードケースは魅力的だったのですが、キーボードを外してタブレット+ケースで持ち歩きたいときもあるので以下をAmazonで購入しました。

Photon2に装着したところです。なかなか使いやすいと思います。

Photon2にWindows 10導入

1.ディスプレー暗転問題対策
bungbungameのサイトにもあるようにWindows10にアップデートすると画面が徐々に暗転して最後は完全に暗くなってしまいます。電源ボタンを軽く押すと復帰するのですが、これでは使い物にならないのでAMDドライバをさっさと当ててしまい、再起動する
http://www.bungbungame.com/JP/products/products.aspx?name=Photon2&Tab=4

2.SDカードが勝手にアンマウントされたりそもそも認識しないときがある
SDを仮想ディスクとしてマウントして使いたいので、これは結構大きい問題です。いろいろ調べた結果Realtek SD readerドライバをWin10用にすればよいということが判明。
http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=4&PNid=15&PFid=25&Level=4&Conn=3&DownTypeID=3&GetDown=false
↑Micorsoft Edgeだとなぜかダウンロードできません。IEを使うといいと思います。
参考 WIndows10にしたらSDカードを認識しない - マイクロソフト コミュニティ
3.てかそもそもPhoton2に入ってるいろんなドライバが古すぎじゃね?
上記①、②が終えたら他のドライバはDriver Booster 3というソフトで一気にアップグレードしました。
Driver Booster 3 Free - IObit日本公式サイト
ここまで終えるともっさりのろのろ起動していたWindows10が体感でわかるくらい早くなっていると思います。やれやれ。

ベンチマークテスト

上記項目を終えてようやく使い物になるレベルになったので、ベンチマークを計測しました。ウインタブさんのところでテストしている環境「ドラクエベンチ、1280x720、標準品質、ウインドウ」に合わせてテストしました。

スコア:2160
ウインタブさんの記事によると、Bay TrailATOMのスコアが1100台なので倍近い性能を示せています。
あらやだこのタブレットすんごいざますw

N-Trigタッチペン手書きもサクサクっと。手書き文字認識も超優秀♪

ラドン

ちょっと気になる点

ハイスペックで画面も綺麗だしとてもいい感じなのですが、不満な点もちょっとあるのでそれを。

  • フルサイズSDカードソケット

フルサイズSDとmicroSDのソケットが1つずつあります。が、フルサイズSDの方はSDカードの3分の1は外にはみ出てしまいます。挿しっぱなしでの利用はできない感じです。あと装着するカバー次第ではそもそも使えないことになるかもしれません。

10インチクラスのタブレットはフルサイズのUSB-Aコネクタが付いてる機種が多いと思います。8インチタブなら諦めるとして、10インチクラスにはフルサイズSDのコネクタ乗せるくらいなら、USBをフルサイズにしてほしかったかなー、などと。

  • Windows10にした後に使えなくなったもの
  1. SD(フルサイズの方のみ。microSDは無問題)
  2. NFC

→自分の用途だと特に困ることもないし解決方法がわからないので放置してます(ぉぃ




その他そろえておきたいもの

液晶保護フィルム
スタイラスでガツガツと叩いてしまいがちなので、保護フィルムは必須かもしれません。

また、このタブレットはそこそこスペックが高いので外出先での使用のほか、家ではHDMI接続して外部ディスプレーでの使用にも十分耐えうるものと思います。

参考:
win-tab.net

Vinculum-IIでUARTからUSBメモリに書き込んでみる

いまさらVinculum-IIを使ってみた

VinCulum-IIのDIP化モジュールV2DIP1-32を以前に買って3年近く積んでたのですが、FSながらもUSBホストが2つあるのと、サンプルコードが豊富ということで使ってみました。
f:id:Lynx-EyED:20150710223943j:plain
UVC対応Webカメラのサンプルコードなんかもあっていいですね。時間があったら触ってみよう。
2.0mmピッチのコネクタがついていたのですが、接触不良を起こしていたのでmolexのソケットに交換したV2DIP1-32とVNC2 Debugger/Programmer
3年前の自分は一番安いボードって理由だけでV2DIP32-1を選択したんだろうと思うんだけど、USBホストコネクタがはじめから2ポートあるV2DIP2のほうがコネクタを増設したりする作業がないので良いと思います。詳細はDevelopment Modules
Vinculum-IIは16bitオリジナルコアで、RTOSがのってるなど、いろいろルネサsを彷彿とさせる地雷臭がちょっとするとか思うところがありますが、使ってみたところ非常に好感が持てる環境でした。

IDEはVinculum-II IDE(以下VinIDE)ですが、初期設定はテキストで書かず、メニューのModifyから選択し、すべて自動生成させます。VOSというRTOS上で動くドライバを自動生成してくれます。

UARTから受信したテキストデータをUSBメモリに保存するサンプルコードをV2DIP1-32用にmodifyしてみました。
元のソースコードはこちらhttp://www.ftdichip.com/Firmware/Precompiled/UART2DSC.zip/
まず、V2DIP1-32のUSBホストコネクタはUSB Port2のものなので、Port1を前提としているサンプルコードの設定を変更します。

メニューのFileタブ → Modify → AppWizardのTarget ModuleタブでV2DIP132pinを選択

DriversタブでUSBHost1のチェックを外し、USBHost2をチェック
FAT File System → BOMS → USBHost2のみチェック
Kernelタブで12MHzを選択
IOMuxタブで
Debugger -> IO0
UART_TXD -> IO4
UART_RXD -> IO5
が緑色でアサインされているのを確認してFinish
f:id:Lynx-EyED:20150711001229p:plain

余談。VinIDEはよくソースコードウィンドウが行方不明になったり、ウィンドウレイアウトが滅茶苦茶になって直らないときがある。こうなったら、C:\Users\(user_name)\AppData\Roaming\FTDI\VinIDEのなかにあるxmlファイルをすべて消す。
こうすると、ウィンドウレイアウトがインストール時のものに戻る。

UART2DSC.cを少しだけ修正。
258行目あたりのコードをUSBHOST_2を使うように変更

hUSBHOST_2 = vos_dev_open(VOS_DEV_USBHOST_2);

あと、エディタの置換機能を使ってhUSBHOST_1をhUSBHOST_2に置き換えておく。
このサンプルコードだと、UARTがループバックしないので、ループバックコードの追加をする。
TXD、RXDの2線のみで通信したいので、RTS,CTSは使わない設定に直す。
21行目

#define DEF_UART_PARITY		UART_PARITY_NONE

367行目のvos_dev_read(hUART...の次の行に以下を追加

vos_dev_write(hUART, &buf[pBuf], numRead, NULL);

メニュー→Buildタブ→Buildして、Debugタブに移行し、VII Debugger ModuleをConnectしてから書き込み。
f:id:Lynx-EyED:20150711001641p:plain

V2DIP1-32のUART(UART_TXD -> IO4,UART_RXD -> IO5)を秋月のFT232RLモジュールと接続
f:id:Lynx-EyED:20150710235850j:plain

FT232RLへTeraTermから9600baud,8N1で文字を打ちこむ
f:id:Lynx-EyED:20150711000756p:plain

USBメモリエクスプローラで確認すると、TEST.TXTが生成されているはず。USBメモリはFAT32フォーマットしているものを使用しました。
f:id:Lynx-EyED:20150711000947p:plain

無事書き込まれうんこ。
f:id:Lynx-EyED:20150711001047p:plain



IFTTT Maker ChannelをFlashAirで使ってみた

IFTTT Maker Channelがおもしろい

スイッチサイエンスマガジンの記事を読んで知ったIFTTT。
IFTTTにMaker Channelができました | スイッチサイエンス マガジン
ウェッブ上のサービス同士をつなげるサービスなわけですが、非常に直感的にできているようで面白いと思いました。
ここではFlashAirで使ってみようと思います。

細かい設定等は上記記事に頼るとして、FlashAirから任意の文字列をiOS通知に表示させようと思います。

iOS通知はiOSデバイス側にIFTTTのアプリが必要になります。AppStoreからダウンロードしておきます。またIFTTTの通知設定がONになっているか確認します
(IFTTTアプリの乳鉢のマーク(レシピ)→歯車のマーク→Channels→iOS Notifications→Edit Channel)
f:id:Lynx-EyED:20150629151334p:plain
上記記事を参考にして、IFTTTのアカウント、レシピで使うシークレットキーを取得します。(投げやりですみません。この記事とても丁寧に説明されており、私がここで二番煎じ劣化説明を書くのはアレなので…)

今回は上記記事と同じくトリガーがMake、アクションがiOS notificationになります。
HTTP POSTかGETが使え、クエリパラメタとしてvalue1,2,3の3つの変数をJSON形式で送ることができるようです。
3つあればFlashAirで温度、湿度、気圧なんかを測定してトリガーとして使えるかもしれません。

LuaでIFTTTにトリガーとJSON形式で変数を与えるコードを書きます。GETをつかっているのでURLべた書きでもかまいませんが、FlashAir W-03にはCJSONがインプリメントされているので、そちらを使いました。

value1 = "foo"
value2 = "bar"
value3 = NICTから取得した現在の時刻

を与えています。

print("HTTP/1.1 200 OK\r\nContent-Type:text/html;charset=utf-8\r\n")

local s_find = string.find
local s_len = string.len
local fa_req = fa.request
local cjson = require "cjson"

contenttype = "application/json;charset=utf-8"			
			
bb,cc,hh = fa_req{url = "https://ntp-a1.nict.go.jp/cgi-bin/time",
			method = "GET"
}

mes = { 
	value1 = "foo", 
	value2 = "bar",
	value3 = tostring(bb)
}

mes = cjson.encode(mes)
blen = string.len(mes)
b,c,h = fa_req{url = "http://maker.ifttt.com/trigger/{トリガーイベント名}/with/key/{シークレットキー}", 
 method = "GET",
 headers = {["Content-Length"] = tostring(blen),
 ["Content-Type"] = contenttype},
 body = mes
	}
print(tostring(b))



また通知メッセージを以下の図のように修正しておきます。
f:id:Lynx-EyED:20150629150712p:plain

value1={{Value1}} ,value2={{Value2}} ,value3={{Value3}} on the Maker Channel

これで、FlashAir内のLuaスクリプトをキックすると、
f:id:Lynx-EyED:20150629151355p:plain

となります。

第4世代の新オーディオDSP、SigmaDSP ADAU145xの試食

CES2014で発表されて以来ずっとウオッチしてきたADAU1452ですが、開発ツールSigmaStudioの対応が成熟してきたので使ってみようと思いました。主な特徴として

  • 最大294.912MHz動作
  • 周波数ドメインの演算ができるようになった(FFTなど)
  • Master Control Portを搭載しSPI/I2Cマスタとして動作するほか、外部のDAC/ADC/EEPROMなどのコンフィグができるようになった*1

ほかにも多くあるのですが、自分が注目したのはこのくらい。
ADAU170x/1401Aにあったヒルベルト変換が無いのですが、今後追加されるようです。
ところで、ADAU145xにはオーディオ用ADC/DACがありません。補助的な低精度のADCを持っているのみで、外付けする必要があります。それでも前述のようなことから採用する理由は十分にあると思います。(でも電池駆動のポータブルオーディオには向かないかも)

で、試食用ボード第1版。どーん。
f:id:Lynx-EyED:20150525214757j:plain
(実はDAC周りのピン設定がミスってて、SigmaDSPの設定を小細工しないと音が出ないなどの問題があり、修正版を実装依頼中の模様…)
主なデバイスはPIC32MX/SPI EEPROM/SigmaDSP/I2S DACといった構成。
PIC32MXがUSB-UART/USBスピーカーとして振る舞い、コンフィグデータのEEPROM書き込み、SigmaDSPへ音声データの送信を行います。

またDACとしてSSM2518を搭載しています。
しばらく遊べるおもちゃになりそうです。

*1:マイコンペリフェラルのような万能動作は期待できない。ブート前のワンショットシーケンサくらいに思ったほうがよいかも https://ez.analog.com/thread/43992