EXPANSYSでNexus 5Xが安くなっていたので注文した

EXPANSYSで円高還元在庫一掃セールなるものをやっていて、Nexus 5X (16GB) が31,490円になっていたので注文した。32GBでも35,895円なので、本家Googleストアよりかなり安い。また、型番もLG-H791という国内モデルと同一なのでプラスエリアも問題なさそう。

今、僕が常日頃メインで使っているのはiPhone 6sで、動作確認用のAndroidとしてはまだNexus 5でも問題ないのだけれど、そろそろお買い得になってきたので購入しておこうかなと。Nexus端末はNexus Oneからかれこれ6年くらい使い続けているが、Androidの最新バージョンをいち早く試すことができて、バージョンダウン等も自由にできるので動作確認に最適だ。大きなデータを入れたりもしないので容量も16GBで充分。

SIMは毎月500MBまで無料で使える 0 SIM by So-net を入れる予定。通常はWiFiで使って、たまにLTE/3G回線でテストしたい時だけWiFiをオフにする。500MBも使わないので、だいたい無料範囲に収まっている。

しかし、数年前は新機種が発表されるとワクワクしたものだが、最近はAndorid、iPhoneの新しい機種が発表されてもワクワクするものが少なくなっている気がする。スマートフォンが成熟してきたのか、自分の歳のせいなのかどちらだろう。

2016/03/10追記:本日、Android Nの開発者プレビュー版が公開されたけど、Nexus 5は対象外とのこと。リプレイスするのにちょうど良いタイミングだったようだ。

2016/03/11追記:本日、Nexus 5Xが届いた。
結構早かったな。今までのQi充電器が使えず、USB Type-CなのでmicroUSB → Type-Cアダプタを買った。早速、Android Nにアップグレードして使っているが、Nexus 5より動作が少しもっさりしている印象。

#nexus5x

A photo posted by @weboo on


2016/05/20追記:Android N Preview3になってかなり快適になった。バックグラウンドプロセスの数を制限したり、アニメーション切ってもカクカクしてたのが無くなり、Nexus 5と遜色なく使えている。

Android Wear「LG G Watch」をキーホルダー化

発売日に入手して1週間で使わなくなってしまった「LG G Watch」なのだけど、今日ふと思い立ってキーホルダー化してみた。

作り方はアウトドア用品店やAmazonで売ってる「S-BINER」と100円ショップで売ってる両面マジックテープを組み合わせるだけ。S-BINERは#3というのがサイズ的に丁度いい。カラビナも100円ショップで売ってるもので済ませれば合計200円でできる。しかし、100円ショップのカラビナ だとかなり安っぽいので、ここはちゃんとしたものを買うのがお勧め。両面マジックテープはバンドサイズが22mmなので、幅20mmくらいだと丁度良い。

 

キーホルダー型ならバッグの持ち手に付けてもいいし、ジーンズのベルトループに付けても良い。これなら腕時計がちょっと苦手な人でもいけるのではないだろうか。ベルトループにぶら下げる時は、時計部分を上下逆さまにしたほうが見やすい。難点は、充電用のクレードルにそのまま置けなくなることなんだけど、マジックテープなので簡単に外せるのでそれほど手間ではない。

何で今頃こんなことを試しているかというと、4月に発売されるApple Watchは買わないことにしたからだ。バッテリーが1日しか持たないというのはウェアラブルなデバイスとしては致命的な気がする。僕がこのLG G Watchを使わなくなったのも電池が2日持たなかったからで、Nike Fuelband、Pebble Steel、Jawbone UP24といろいろ試してきたけど、結局今でも常時使っているのはバッテリーが持つPebble SteelとUP24だけだ。UP24についてはファームウェアのアップデートで2週間持つようになってかなり使い勝手が向上した。

ちょっと話がそれたが、このバッテリー問題が解決されるまで僕がApple Watchを買うことはないだろう。しかし、ウェアラブルの今後の可能性や課題について考えるには、実際にユーザとして日常的に使って自分なりに面白い使い方を考えてみる必要があると思っているので、LG G Watchを机の中から引っ張り出してきたというわけだ。

corega の USB シリアルケーブルを Mac OS X でも使えるようにする

最近、自分が関わっている某プロジェクトで使うために、USBシリアルケーブルを買ってきました。ヨドバシカメラで一番安かった corega の CG-USBRS232R という製品なんですが、家に帰ってきてから Mac に対応してないことに気づきました…

というわけで、以下 Mac でも使えるようにしたのでメモ。

調べてみると、この製品は Prolific 社の PL2303 というチップが使われていることが分かりました。幸いなことに OS X 用のドライバを公開してくれているので、下記のドライバを試してみました。

md_PL2303_MacOSX10.6_dmg_v1.4.0.zip

解凍してインストールしましたが、当然ながらチップが同じだけで日本メーカーのものは認識してくれません。

これを認識させるには、
/System/Library/Extensions/ProlificUsbSerial.kext/Contents/Info.plist
を編集して、以下の記述を追加します。

<key>07aa_002a</key>
<dict>
        <key>CFBundleIdentifier</key>
        <string>com.prolific.driver.PL2303</string>
        <key>IOClass</key>
        <string>com_prolific_driver_PL2303</string>
        <key>IOProviderClass</key>
        <string>IOUSBInterface</string>
        <key>bConfigurationValue</key>
        <integer>1</integer>
        <key>bInterfaceNumber</key>
        <integer>0</integer>
        <key>idProduct</key>
        <integer>42</integer>
        <key>idVendor</key>
        <integer>1962</integer>
</dict>
次に kext キャッシュを削除するために以下のコマンドを実行して再起動。
sudo touch /System/Library/Extensions

USBシリアルケーブルを挿すと無事、目的のブツに繋がるようになりました。

% screen /dev/tty.usbserial 115200

Texas Instruments X-Loader 1.4.4ss (Mar  8 2011 - 08:51:11)
Beagle xM
Reading boot sector
Loading u-boot.bin from mmc


U-Boot 2010.03 (Feb 20 2011 - 20:15:58)

OMAP3630/3730-GP ES2.1, CPU-OPP2, L3-165MHz, 
OMAP3 Beagle board + LPDDR/NAND
I2C:   ready
DRAM:  512 MB
NAND:  0 MiB

Nexus Sの部品を香港から取り寄せて修理した話

車にひかれて破壊された Nexus S を修理しました。

自分の不注意が原因のため、当然ながら保証対象外でメーカーに送ってもかなりの高額になりそうだったので、まずサードパーティの修理業者を当たってみました。スマートフォンの修理業者はいくつかあって、だいたい液晶修理は1万3千円〜1万6千円くらいで対応してくれるようです。で、Webサイトから問い合わせてみたら、反応はこんな感じでした。

  • アンドロイドドクター → 流通量が少なく無理ですとの回答(Nexus Oneなら対応可)
  • SMART → 問い合わせを受け付けましたメールのみで、返事なし

これは駄目だと思い、パーツを入手して自分で修理することにしました。早速、eBayでNexus S用の有機ELモジュールを出品しているのをみつけて落札。香港からの発送で送料込みで$140ほどでした。日本で修理してもらったらもっとかかるので、まぁ悪くない金額だと思います。実は、バックパネルも傷だらけなんですが、NFCのアンテナが入っているおかげで$55もするのでこちらは我慢してそのまま使うことにしました。

待つこと約5日間、Hong Kong Post→日本郵便経由で商品が無事に到着したので、iFixitを参考に分解しました。

次に仮組みをして動作確認します。キター!
正常に表示されているようです。タッチパネルもちゃんと使えます。

でも、ここで問題発生。自分のNexus Sは発表されてすぐに注文したので初期ロット品です。それに対してこちらの有機ELモジュールはより新しいものらしく、ねじ穴の位置と電源ボタンの位置が微妙に違います。。

そこで、マザーボードが載るフレームだけ以前のものを利用することにし、さらにボタン部分とフレームを分解しました。

あとは組み直して完了。前から見る分には完全復活を遂げました。

※作業に関しては、やはりコツみたいなものがあって、一回やってみないと変なところに力を加えてしまって壊してしまう可能性は多々あります。この記事を見て壊してしまっても私は責任を取れませんのであしからず。

さようなら、Nexus S

帰宅途中で道路に落としてしまったようです。発見した時には、こんな無残な姿になっていました。短い間だったけど、適切な画面サイズと手になじむ形状で Nexus S はとても良い端末でした。

あぁ…

IS01 で compcache (ramzswap) を有効にする(2)

昨日の compcache 有効化 kernel ですが、busyboxが必要とか微妙だったので改良しました。今度のものは、以下のイメージ以外は何も必要ありません。

» ubi-compcache-0.2.img

また、ro.compcache.size にて確保するサイズを指定できるようにしたので、好きな値を /system/build.prop にて設定することができます。自分は以下のように32MBに設定して使っています。何も記述しなかった場合は、compcacheのデフォルト値が使われます。

ro.compcache.size=32768

カーネルのソースコードは、github に置いてあります。

https://github.com/weboo/kernel-is01

IS01 で compcache (ramzswap) を有効にする(1)

※2011/02/15追記:改良版をこちらで公開しています

IS01 は CPU こそ 1GHz の Snapdragon が載っているのですが、メモリが256MBと最近の端末にしては少なめです。そこで自分は、本体に swap ファイルを作成して使っていたのですが、やはりフラッシュメモリの消耗が気になるので compcache に切り替えることにしました。

compcache は、一定量のメモリを swap 領域として利用し、そこに圧縮して格納することで少ないメモリを効率的に活用するための仕組みです。SHARPのサイトで公開されているIS01のソースコードに compcache の機能を追加したものを以下に置いておきます。

» ubi-compcache.img

この kernel に入れ替えるだけで、32MB の compcache 機能が有効になります(/system/xbin などPATHの通ったところに busybox が必要)。また、偉大な先人に習って、insmod有効化、NANDロック解除、Deckard無効化もしてあります。

# rzscontrol /dev/block/ramzswap0 -s
DiskSize:          32768 kB
NumReads:           4358
NumWrites:         10339
FailedReads:           0
FailedWrites:          0
InvalidIO:             0
NotifyFree:            0
ZeroPages:           763
GoodCompress:         63 %
NoCompress:           23 %
PagesStored:        7425
PagesUsed:          3234
OrigDataSize:      29700 kB
ComprDataSize:     12630 kB
MemUsedTotal:      12936 kB

# 最近、組み込みAndroidの本を買いました。Kernelの移植方法やドライバの作り方などが分かりやすく解説されていて、これはおすすめ。

基礎から学ぶ 組み込みAndroid
坂本 俊之 出村 成和 渡邊 昌之
シーアンドアール研究所
売り上げランキング: 3485

1.2GHz Kernel + color fix for Nexus S

Nexus S 用の1.2GHzクロックアップと色補正済みの Kernel が安定して使えているので、ここに置いておきます。Recovoery Managerから適用して使ってください。

snsmod-1200c-01.26.zip

Quadrant ベンチマークの結果は下のような感じです。Nexus S だと 2D,3Dグラフィックの部分がエラーで落ちてしまうので、その部分は除かれています。実際は余裕でスコア2000を超えそうです。ここは、早く Quadrant の開発元に直してもらいたいところ。

と問題が解決して喜んでいたのですが、衝撃の事実に気づいてしまいました。先日 Bar Android に行って、@adamrockerさん、@koyhogeさんの Nexus S を見せてもらったのですが、ディスプレイは緑がかってませんでした。どうも個体差のようです。海外でも同様の症状を訴えている人はいるものの、あまり賛同するコメントもありません(参考)。自分の周りのNSユーザに同様の色合いが多いのは、外れロットに当たってしまったようです…

とはいえ、自分で解決できたので今回はよしとします。ソースが公開されていないとこうはいきませんから。

Nexus S の低電圧化 Kernel

昨日の 1.3GHz はさすがに不安定でした。現在は 1.2GHz に若干落として常用しています。ベンチマークでもほぼクロックが増えた分の性能向上が見られます。


左:1.0GHz,右:1.2GHz

さて、今日は低電圧化をしてみます。といっても消費電力の多くはディスプレイなのでバッテリーの持ちが劇的に良くなることはないと思いますが、クロックアップした際の CPU ダメージを軽減させるためには効果的なのではないかと。

arch/arm/mach-s5pv210/cpu-freq.c
--- a/arch/arm/mach-s5pv210/cpu-freq.c
+++ b/arch/arm/mach-s5pv210/cpu-freq.c
@@ -65,28 +65,28 @@ struct s5pv210_dvs_conf {
        unsigned long       int_volt;   /* uV */
 };
 
-const unsigned long arm_volt_max = 1350000;
-const unsigned long int_volt_max = 1250000;
+const unsigned long arm_volt_max = 1200000;
+const unsigned long int_volt_max = 1100000;
 
 static struct s5pv210_dvs_conf dvs_conf[] = {
        [L0] = {
-               .arm_volt   = 1250000,
+               .arm_volt   = 1200000,
                .int_volt   = 1100000,
        },
        [L1] = {
-               .arm_volt   = 1200000,
+               .arm_volt   = 1100000,
                .int_volt   = 1100000,
        },
        [L2] = {
-               .arm_volt   = 1050000,
-               .int_volt   = 1100000,
+               .arm_volt   = 1000000,
+               .int_volt   = 1000000,
        },
        [L3] = {
                .arm_volt   = 950000,
-               .int_volt   = 1100000,
+               .int_volt   = 1000000,
        },
        [L4] = {

とりあえず、色合い調整済みかつ標準1GHzクロックで低電圧化したものをここに置いておきます。

Fastboot用
sns-01.20_boot.img
Recovery Manager用
snsmod-01.22.zip

Nexus S を 1.3GHz にクロックアップする

最近は、早起きして早朝に Nexus S のチューニングを進めているわけですが、今日は CPU Frequency Table に手を加えてしてクロックアップをしてみました。

まずは標準の 1.0GHz から 1.3GHz へのクロックアップを行います。こちらは、Galaxy S でも実績のある数値なので特に問題はないと思うのですが、下手したら確実に壊れます。この patch を元に壊して私は責任をとれませんのであしからず。

やってることは大したことはなくて、cpu_frequency_table に設定を追加しているだけです。ポイントは、その値に応じて供給電圧を変化させなければならない点です。逆にこの供給電圧を標準より下げることで、バッテリーの消費を減らすことができるようになります。コスタリカ産の Celeron 300A をクロックアップして動かしていた時代が思い出されます。

差分は以下の通りです。

arch/arm/mach-s5pv210/cpu-freq.c
--- a/arch/arm/mach-s5pv210/cpu-freq.c
+++ b/arch/arm/mach-s5pv210/cpu-freq.c
@@ -52,11 +52,12 @@ static DEFINE_MUTEX(set_freq_lock);
 
 /* frequency */
 static struct cpufreq_frequency_table freq_table[] = {
-       {L0, 1000*1000},
-       {L1, 800*1000},
-       {L2, 400*1000},
-       {L3, 200*1000},
-       {L4, 100*1000},
+       {L0, 1300*1000},
+       {L1, 1000*1000},
+       {L2, 800*1000},
+       {L3, 400*1000},
+       {L4, 200*1000},
+       {L5, 100*1000},
        {0, CPUFREQ_TABLE_END},
 };
 
@@ -70,46 +71,63 @@ const unsigned long int_volt_max = 1250000;
 
 static struct s5pv210_dvs_conf dvs_conf[] = {
        [L0] = {
-               .arm_volt   = 1250000,
-                .int_volt   = 1100000,
+               .arm_volt   = 1300000,
+                .int_volt   = 1200000,
        },
        [L1] = {
-               .arm_volt   = 1200000,
+               .arm_volt   = 1250000,
                .int_volt   = 1100000,
        },
        [L2] = {
-               .arm_volt   = 1050000,
+               .arm_volt   = 1200000,
                .int_volt   = 1100000,
        },
        [L3] = {
-               .arm_volt   = 950000,
+               .arm_volt   = 1050000,
                .int_volt   = 1100000,
        },
        [L4] = {
                .arm_volt   = 950000,
+               .int_volt   = 1100000,
+       },
+       [L5] = {
+               .arm_volt   = 950000,
                .int_volt   = 1000000,
        },
 };
 
-static u32 clkdiv_val[5][11] = {
+static u32 clkdiv_val[6][11] = {
        /*{ APLL, A2M, HCLK_MSYS, PCLK_MSYS,
         * HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS, ONEDRAM,
         * MFC, G3D }
         */
-       /* L0 : [1000/200/200/100][166/83][133/66][200/200] */
+       /* L0 : [1300/200/200/100][166/83][133/66][200/200] */
+       {0, 6, 6, 1, 3, 1, 4, 1, 3, 0, 0},
+       /* L1 : [1000/200/200/100][166/83][133/66][200/200] */
        {0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
-       /* L1 : [800/200/200/100][166/83][133/66][200/200] */
+       /* L2 : [800/200/200/100][166/83][133/66][200/200] */
        {0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
-       /* L2 : [400/200/200/100][166/83][133/66][200/200] */
+       /* L3 : [400/200/200/100][166/83][133/66][200/200] */
        {1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
-       /* L3 : [200/200/200/100][166/83][133/66][200/200] */
+       /* L4 : [200/200/200/100][166/83][133/66][200/200] */
        {3, 3, 0, 1, 3, 1, 4, 1, 3, 0, 0},
-       /* L4 : [100/100/100/100][83/83][66/66][100/100] */
+       /* L5 : [100/100/100/100][83/83][66/66][100/100] */
        {7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
 };
 
 static struct s3c_freq clk_info[] = {
-       [L0] = {        /* L0: 1GHz */
+       [L0] = {        /* L0: 1.3GHz */
+               .fclk       = 1300000,
+               .armclk     = 1000000,
+               .hclk_tns   = 0,
+               .hclk       = 133000,
+               .pclk       = 66000,
+               .hclk_msys  = 200000,
+               .pclk_msys  = 100000,
+               .hclk_dsys  = 166750,
+               .pclk_dsys  = 83375,
+       },
+       [L1] = {        /* L1: 1GHz */
                .fclk       = 1000000,
                .armclk     = 1000000,
                .hclk_tns   = 0,
@@ -120,7 +138,7 @@ static struct s3c_freq clk_info[] = {
                .hclk_dsys  = 166750,
                .pclk_dsys  = 83375,
        },
-       [L1] = {        /* L1: 800MHz */
+       [L2] = {        /* L2: 800MHz */
                .fclk       = 800000,
                .armclk     = 800000,
                .hclk_tns   = 0,
@@ -131,7 +149,7 @@ static struct s3c_freq clk_info[] = {
                .hclk_dsys  = 166750,
                .pclk_dsys  = 83375,
        },
-       [L2] = {        /* L2: 400MHz */
+       [L3] = {        /* L3: 400MHz */
                .fclk       = 800000,
                .armclk     = 400000,
                .hclk_tns   = 0,
@@ -142,7 +160,7 @@ static struct s3c_freq clk_info[] = {
                .hclk_dsys  = 166750,
                .pclk_dsys  = 83375,
        },
-       [L3] = {        /* L3: 200MHz */
+       [L4] = {        /* L4: 200MHz */
                .fclk       = 800000,
                .armclk     = 200000,
                .hclk_tns   = 0,
@@ -153,7 +171,7 @@ static struct s3c_freq clk_info[] = {
                .hclk_dsys  = 166750,
                .pclk_dsys  = 83375,
        },
-       [L4] = {        /* L4: 100MHz */
+       [L5] = {        /* L5: 100MHz */
                .fclk       = 800000,
                .armclk     = 100000,
                .hclk_tns   = 0,
@@ -269,6 +287,9 @@ static void s5pv210_cpufreq_clksrcs_MPLL2APLL(unsigned int index,
         * 2-1. Set PMS values
         */
        if (index == L0)
+               /* APLL FOUT becomes 1300 Mhz */
+               __raw_writel(PLL45XX_APLL_VAL_1300, S5P_APLL_CON);
+       else if (index == L1)
                /* APLL FOUT becomes 1000 Mhz */
                __raw_writel(PLL45XX_APLL_VAL_1000, S5P_APLL_CON);
        else
@@ -478,7 +499,7 @@ static int s5pv210_cpufreq_target(struct cpufreq_policy *policy,
                s5pv210_cpufreq_clksrcs_APLL2MPLL(index, bus_speed_changing);
 
        /* ARM MCS value changed */
-       if (index <= L2) {
+       if (index <= L3) {
                reg = __raw_readl(S5P_ARM_MCS_CON);
                reg &= ~0x3;
                reg |= 0x1;
@@ -508,7 +529,7 @@ static int s5pv210_cpufreq_target(struct cpufreq_policy *policy,
        } while (reg & 0xff);
 
        /* ARM MCS value changed */
-       if (index > L2) {
+       if (index > L3) {
                reg = __raw_readl(S5P_ARM_MCS_CON);
                reg &= ~0x3;
                reg |= 0x3;
@@ -543,7 +564,7 @@ static int s5pv210_cpufreq_target(struct cpufreq_policy *policy,
 
        /*
         * Adjust DMC1 refresh ratio according to the rate of hclk_msys
-        * (L0~L3: 200 <-> L4: 100)
+        * (L0~L4: 200 <-> L5: 100)
         * If DMC1 clock gets slower (by original clock speed * n),
         * then, the refresh rate should decrease
         * (by original refresh count * n) (n : clock rate)
@@ -603,9 +624,9 @@ static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
 
        if (level == CPUFREQ_TABLE_END) { /* Not found */
                pr_err("[%s:%d] clock speed does not match: "
-                               "%d. Using L1 of 800MHz.\n",
+                               "%d. Using L2 of 800MHz.\n",
                                __FILE__, __LINE__, rate);
-               level = L1;
+               level = L2;
        }
 
        memcpy(&s3c_freqs.old, &clk_info[level],
@@ -656,9 +677,9 @@ static int __init s5pv210_cpufreq_driver_init(struct cpufreq_policy *policy)
 
        if (level == CPUFREQ_TABLE_END) { /* Not found */
                pr_err("[%s:%d] clock speed does not match: "
-                               "%d. Using L1 of 800MHz.\n",
+                               "%d. Using L2 of 800MHz.\n",
                                __FILE__, __LINE__, rate);
-               level = L1;
+               level = L2;
        }
 
        backup_dmc0_reg = __raw_readl(S5P_VA_DMC0 + 0x30) & 0xFFFF;
arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
--- a/arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
+++ b/arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
@@ -29,6 +29,7 @@ enum perf_level {
        L2,
        L3,
        L4,
+       L5,
 };
 
 #define SLEEP_FREQ      (800 * 1000) /* Use 800MHz when entering sleep */
arch/arm/plat-s5p/include/plat/pll.h
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -21,6 +21,7 @@
 
 #include 
 
+#define PLL45XX_APLL_VAL_1300  ((1 << 31) | (444 << 16) | (4 << 8) | (0))
 #define PLL45XX_APLL_VAL_1000  ((1 << 31) | (125 << 16) | (3 << 8) | (1))
 #define PLL45XX_APLL_VAL_800   ((1 << 31) | (100 << 16) | (3 << 8) | (1))
 

今日一日この設定で動かして様子を見て問題なさそうであれば、次回は電圧を下げてバッテリーの持ちを改善したいと思います。