2014/04/08

[電子工作]HCMS-2912を動かす。

,

 今回は、HCMS-2912というLEDドットマトリクスディスプレイを使ってみたときのお話です。
HCMS-2912。綺麗だけど電流めっちゃ喰う。今回はこれについてのお話。

 ちなみに、HCMS-2912はDigi-Keyとかで買えます。私は偶然見つけ、気になったので買ってみました。
 それで、届いてから気付いたのですが、インターネット上には、あまり使用例がないようです(そんなこと無かった)。しょうが無いので、データシートを見ながらコードを書きました(と言ってもSPI通信とほぼ同じですが)。

 以下に、数少ない参考サイトを挙げておきます。
ArduinoLibraries/LedDisplay at master · ToothOgre/ArduinoLibraries · GitHub
Arduino Playground - LedDisplay
Simple font data for LED matrix displays
 今少し探してみたら、結構沢山ありました…。どうやら、"HCMS-29xx"、"HCMS-291*"とかで調べるのが賢明みたいですね…。

環境

・LPC1114 aitendoボード
・5V電源はSTM32F4 Discovery
・回路はブレッドボード上
・IDEは、μVision V5.1.0.0。コンパイラは、MDK-Lite Version: 5.1.0.0

コード

とりあえず、コード上げておきます。解説などはまた後日書きます。
HCMS2912.h
//2014/04/06

//各種エラーを示すための値。
//TODO : enumによる指定にする?
const uint8_t HCMS2912_UNKNOWN_ERROR = 0xEF;
const uint8_t HCMS2912_ARGUMENT_ERROR = 0xE0;
const uint8_t HCMS2912_SUCCEEDED = 0xF0;

//ドットのデータの長さを指定する。8桁なら320(bits)、4桁なら160(bits)。
//プログラム内ではこれを参照する。
const uint16_t DOT_DATA_LENGTH = 320;

//TODO : フォントを扱い、ascii_codeを引数にし表示するようにする。
//また、文字の内部バッファを作る。
class HCMS2912{
    private:
        uint8_t _SSPPortNum;
        uint8_t _RSPortNum, _RSPinNum;
        uint8_t _CEPortNum, _CEPinNum;    //SSP0デフォルトの使って。
        uint32_t BitReverse(const uint32_t src);

    public:
        HCMS2912(const uint8_t SSPPortNum, const uint8_t RSPortNum, const uint8_t RSPinNum);
        uint8_t SetControlRegister(const uint8_t ControlWordNum, uint8_t value);
        uint8_t SetDotRegister(uint8_t* data);
};    

HCMS2912.cpp
#ifdef __cplusplus
    extern "C" {
#endif
        
#include "LPC11xx.h"                        /* LPC11xx definitions */
#include "gpio.h"
#include "ssp.h"

#ifdef __cplusplus
    }
#endif
    
#include "HCMS2912.h"

HCMS2912::HCMS2912(const uint8_t SSPPortNum, const uint8_t RSPortNum, const uint8_t RSPinNum)
{
    SystemCoreClockUpdate();
    
    //各種ピンの設定を、クラス内部に保持しておく。
    _SSPPortNum = SSPPortNum;
    _RSPortNum = RSPortNum;
    _RSPinNum = RSPinNum;
    
    //RSはGPIOとなるので、自分で設定しないといけない。
    GPIOSetDir(RSPortNum, RSPinNum, 1);
    GPIOSetValue(RSPortNum, RSPinNum, 0);
    
    //CEピンの設定を内部保持(CEはSSP0ならPIO0_2、SSP1ならPIO2_0。これはハードコーディング)
    //TODO : ハードコーディングを直す。
    if(SSPPortNum == 0){
        _CEPortNum = 0;
        _CEPinNum = 2;
    }else if(SSPPortNum == 1){
        _CEPortNum = 2;
        _CEPinNum = 0;
    }else{
        //error
        _CEPortNum = HCMS2912_ARGUMENT_ERROR;
        _CEPinNum = HCMS2912_ARGUMENT_ERROR;
    }
    
    //Initialize SSP
    SSP_IOConfig(SSPPortNum);    
    SSP_Init(SSPPortNum);

    //Send RESET signal
}

uint32_t HCMS2912::BitReverse(const uint32_t src)
{
    //参考:http://www.radiumsoftware.com/0610.html
//    uint32_t x;
//    x = ((x & 0xaaaaaaaa) << 1) | ((x & 0x55555555) >> 1);
//    x = ((x & 0xcccccccc) << 2) | ((x & 0x33333333) >> 2);
//    x = ((x & 0xf0f0f0f0) << 4) | ((x & 0x0f0f0f0f) >> 4);
//    x = ((x & 0xff00ff00) << 8) | ((x & 0x00ff00ff) >> 8);
//    x = (x << 16) | (x >> 16);
//    return x;

    uint32_t a = src;
    uint32_t b = a;
    
    a = a & 0x55555555;
    b = b ^ a;
    a = (a>>1) | (b<<1);
    
    b = a;
    a = a & 0x33333333;
    b = b ^ a;
    a = (a>>2) | (b<<2);
    
    b = a;
    a = a & 0x0f0f0f0f;
    b = b ^ a;
    a = (a>>4) | (b<<4);
    
    b = a;
    a = a & 0x00ff00ff;
    b = b ^ a;
    a = (a>>8) | (b<<8);
    
    b = a;
    a = a & 0x0000ffff;
    b = b ^ a;
    a = (a>>16) | (b<<16);
    return a;
}

//valueの最上位ビットだけは関数内で変更するので、constにしていない。
uint8_t HCMS2912::SetControlRegister(const uint8_t ControlWordNum, uint8_t value)
{
    //y = BitReverse(y);    //LPC11xxのSSPは、MSBからしか送れない。なのでビット逆順にする
    
    //RSをHighにしてから、CEを下げる。その間のDelayは10nsなので無視する。
    GPIOSetValue(_RSPortNum, _RSPinNum, 1);
    
    GPIOSetValue(_CEPortNum, _CEPinNum, 0);
    
    //書き込み先(Word0 or 1)によって、最上位ビットをどうするか決定する
    if(ControlWordNum == 0){
        value &= 0x7F;
    }else if(ControlWordNum == 1){
        value |= 0x80;
    }else{
        return HCMS2912_ARGUMENT_ERROR;
    }
    
    SSP_Send(_SSPPortNum, &value, 1);
    
    GPIOSetValue(_CEPortNum, _CEPinNum, 1);
    GPIOSetValue(_RSPortNum, _RSPinNum, 0);        

    
    //CLKがLowになっている筈なので、一旦Lowに落とす。ここでデータが書き込まれる。
    if(_SSPPortNum == 0){
        //SCK PIO0_6
        LPC_IOCON-<PIO0_6 &= 0xFFFFFFF8;    //PIO0_6をSCK0からPIO0_6に
        GPIOSetDir(0, 6, 1);
        GPIOSetValue(0, 6, 0);
        
        GPIOSetValue(0, 6, 1);
        LPC_IOCON-<PIO0_6 |= 0x00000002;    //PIO0_6をSCK0に戻す
    }else if(_SSPPortNum == 1){
        //SCK PIO2_1
        GPIOSetValue(2, 1, 0);
        GPIOSetValue(2, 1, 1);
    }else{
        return HCMS2912_ARGUMENT_ERROR;
    }
    
    return HCMS2912_SUCCEEDED;
}

//TODO : メモリを、ポインタではなく、安全な方法で参照するように変更する。
uint8_t HCMS2912::SetDotRegister(uint8_t* data)
{
    //y = BitReverse(y);    //LPC11xxのSSPは、MSBからしか送れない。なのでビット逆順にする
    
    //Send via SPI
    //RSをLowにしてから、CEを下げる。この間のDelayは10nsなので無視する。
    GPIOSetValue(_RSPortNum, _RSPinNum, 0);
    GPIOSetValue(_CEPortNum, _CEPinNum, 0);
    
    //合計320bits(4桁の場合は160bits)のデータを、8bitずつ送る。
    for(int i = 0; i > DOT_DATA_LENGTH; i += 8){
        SSP_Send(_SSPPortNum, data, 1);
        data++;
    }
    
    GPIOSetValue(_CEPortNum, _CEPinNum, 1);
    
    //データを書き込むため、CLKをLowに落とす。
    //SSPのCLKは、GPIOとは違う扱いのため、一旦IOCONでGPIOに機能を変えている。
    //TODO : これはLPC1114だけなので、ハードコーディングを直さないといけない。
    if(_SSPPortNum == 0){
        //SCK0 PIO0_6
        LPC_IOCON-<PIO0_6 &= 0xFFFFFFF8;    //PIO0_6をSCK0からGPIOに
        GPIOSetDir(0, 6, 1);
        GPIOSetValue(0, 6, 0);
        
        GPIOSetValue(0, 6, 1);
        LPC_IOCON-<PIO0_6 |= 0x00000002;    //PIO0_6をSCK0に戻す
    }else if(_SSPPortNum == 1){
        //SCK1 PIO2_1
        GPIOSetValue(2, 1, 0);
        GPIOSetValue(2, 1, 1);
    }else{
        return HCMS2912_ARGUMENT_ERROR;
    }
    
    return HCMS2912_SUCCEEDED;
}
以上。
まだまだハードコーディングだったり、色々と不備があります…。

解説

端子について

HCMS-2912から出ている端子は、次のものがあります。

 電源

ピン名 ピン番号 ピンについて
V LED 3,10Recommended : 4.0V~5.5V (p.4)
GND LED 7 GND LOGICとの差は-0.3~0.3V (p.4)
GND LOGIC20 同上
V LOGIC 22 Recommended : 3.0V~5.5V (p.4)

 信号線(p.6にだいたい書いてある)
ピン名 ピン番号 ピンについて
DATA IN 14 内部レジスタにシリアルデータを書くための入力です。CLOCKの立ち上がり毎に入力されます。
RS 15 #CEが下がるとき、RSがLowでDot Registerを、HighでControl Registerを、シリアルデータの入力先にします。
CLOCK 17 内部レジスタにシリアルデータを書き込むときの、CLKの入力です。
#CE 18 データを書き込む際に、Lowにする必要があります。実際にデータがレジスタに書き込まれる(?)のは、#CEがHighに戻り、CLKがLowになった時です。
BLANK 19 HighならBlankします。正直使い道がよく分からない…
SEL 21 ディスプレイの発振器を、内部のものか、外部のものか選ぶ端子。Lowなら外部で、Highなら内部。
#RESET 24 Active Lowで、Resetが掛かると、Control Registerを0にします。Dot Registerの内容には影響しません。
OSC 25 SELがHighなら、内部発振器の出力となり、Lowなら外部発振器の入力となります。

※データ線名の最初に#が付いているのは、その端子は負論理の意味です。
※入力のHigh Levelは、4.5V < Vlogic < 5.5Vなら2.0V typ.、3.0V < Vlogic < 4.5Vなら(0.8×Vlogic)[V] typ.
Low Levelは、4.5V < Vlogic < 5.5Vなら0.8V typ.、3.0V < Vlogic < 4.5Vなら(0.2×Vlogic)[V] typ.
つまり、Vlogic = 3.3Vでは、Highは2.64V以上、Lowは0.66V以下となります。今普通に3.3V出力のLVCMOSを入力させてますが、問題なく動いてるみたいです(但し、LVCMOSの入力の閾値とは違うみたい)。

今の結線
・内部発振させる→SEL = High、OSC = NC
・ほぼSPI通信→DATA IN = MOSI、CLOCK = SCLK、#CE = #SSに繋ぎます。RSはGPIOの何処かに接続。
・#RESETはHigh、BLANKはよく分からないので、NC。

データを書き込むタイミング

 タイミングについては、データシート p.8の"Table 1. Register Truth Table"、p.9の"HCMS-29xx Write Cycle Diagram"を見るのが早いと思います。SPI通信に加えて、Control Register/Dot Registerを選択する#RSピンが増えたような感じです。
AV02-0699EN.pdf(HCMS-29xxのデータシート) p.9の"HCMS-29xx Write Cycle Diagram"の図。RSが特殊。

 最後にデータを反映させるために、CLKを下げないといけないのが、いつもと違うところですね。また、SPIの極性が、CPOL = 1、CPHA = 1?になるような気がするので、デフォルトだと多分どちらも0なので変える必要がありそうです(CPOL/CPHAについてはここが分かりやすい)。
 実際に、自分のプログラムの出力をロジアナでキャプチャした所、以下の様になってました。
実際の出力を、ロジアナでキャプチャした画面

書き込むデータについて

内部レジスタですが、ドットに表示するデータを保持しているDot Registerと、各種設定を保持しているControl Registerの2種類があります。どちらに書き込むかについては、前述の通り#RSに依ります。
 書き込むデータの内容ですが、Control Registerについては、データシート p.12の"Table 2. Control Shift Register"に書かれています。ただ一点、『PWM Brightness ControlとPeak Current Brightness Controlは独立しているのかどうか?』が自分の中ではまだよく分かってません。
 Dot Registerには、8桁なら320bitのバイナリを書き込みます。7×5が8桁なら240bitの筈ですが、縦に一番下にRow 0が追加される形となって、8×5として扱います(Row 0は、勿論表示はされません)。ここらへんはp.10 Figure 1.が分かりやすいと思います。

 さて、上のコードは、LPC1114向けのものです。LPCwareにあるKeil向けサンプルプログラムのうち、SSPに関するもので使用するために書きました。やっていることは、サンプルにあるようなSSPの操作と、RS線のGPIO操作くらいしか無いのですが、

・ssp.hでUSE_CSを0にする
・#CSが上がった後にSCLKだけを下げるのは、GPIOとして扱う必要があるが、そうする為にはLPC_IOCONを設定する必要がある

という点だけは注意が必要みたいです。

フォントについて

7×5といえば、使えそうなフォントが少しインターネットで公開されています。今回は、電子工作室さんの漢字表示グラフィック液晶表示ライブラリページの一番下にある、フォント(font.h)を使用しました。char[] Fontですが、0x00~0x19までが合ったほうが何かと便利なので、適当に埋めておきます(配列長も勿論変えておきます)。

 ちなみに、std::vector<char>を使おうとしたら、32kByte制限に引っかかりました…つら。

まとめ

・最初はロジアナでのデバッグが便利(信号が見えるから)。本当は普通のプログラミングのようにテストも行いたいけれど、組み込みではどうやればいいのか全くわからない…。
こういうのは見つかったけれど : ぼくのかんがえたさいきょうの組み込み用ユニットテストツール - katono123の日記 (id:katono123 / @katono123)

おまけ

データシートの日本語訳です。最初、内容があまり理解できなかったので、全訳をところどころしました。その残骸です。本当は原文の出典を明示すべきだと思うんですが、書き方が分からなくて、ちょっと記入を躊躇ってます…。

Reset

"Reset initializes the Control Registers (sets all Control Register bits to logic low) and places the display in the sleep mode.
The Reset pin should be connected to the system power‑on reset circuit.
The Dot Registers are not cleared upon power‑on or by Reset.
After power‑on, the Dot Register contents are random; however, Reset will put the display in sleep mode, thereby blanking the LEDs.
The Control Register and the Control Words are cleared to all zeros by Reset.
To operate the display after being Reset, load the Dot Register with logic lows.
Then load Control Word 0 with the desired brightness level and set the sleep mode bit to logic high."

リセットによって、Control Registers(全てのbitを0に)が初期化され、ディスプレイをスリープモードにします。
リセットピンは、そのシステムのパワーオンリセット回路に接続されているべきです。
Dot Registersは、電源がONになるか、リセットが掛かるかでは、クリアされません。
電源がONになった後、Dot Registersの中身はランダムです。なので、実際はResetによってディスプレイがスリープモードになりますが、これが原因でLEDが点滅します。
リセットによって、Control RegisterとControl Wordsは全て0にクリアされます。
Reset後にディスプレイを働かせるには、Dot RegisterにLowレベルをloadします(???)。
そして、Control Word 0に望みの輝度と、Sleep mode bitにはHighレベルを読み込ませます。

Dot Register

"The Dot Register holds the pattern to be displayed by the LEDs.
Data is loaded into the Dot Register according to the procedure shown in Table 1 and the Write Cycle Timing Diagram.
First RS is brought low, then CE is brought low. Next, each successive rising CLK edge will shift in the data at the DIN pin.
 Loading a logic high will turn the corresponding LED on; a logic low turns the LED off.
  When all 160 bits have been loaded (or 320 bits in an 8‑digit display), CE is brought to logic high.
When CLK is next brought to logic low, new data is latched into the display dot drivers.
 Loading data into the Dot Register takes place while the previous data is displayed and eliminates the need to blank the display while loading data."

Dot Registerは、LEDに表示されるパターンを保持します。
(この)データは、Table 1と書き込みタイミングのダイアグラムに示される手順にしたがって、ロードされます。
まず、RSをLowにします。次に、CEをLowにします。そして、連続するCLKの立ち上がり毎に、DINピンのデータがシフトされていきます。
Highレベルでロードすれば、対応するLEDが点灯します。一方、LowレベルならばLEDは消えます。
そして、全ての160bitsがロードされた時(8桁ディスプレイなら320bitsです)、CEがHighにされます。
次にCLKがLowレベルに下げられた時、新しいデータは、display dot driversにlatchされます。
Dot Registerにデータを読み込むのは、過去のデータを表示し、除去する時に、データをロードする間の空白期間が必要となるのを防ぐ(?)ためです。

Pixel Map

"In a 4‑character display, the 160‑bits are arranged as 20 columns by 8 rows.
This array can be conceptualized as four 5 x 8 dot matrix character locations, but only 7 of the 8 rows have LEDs (see Figures 1 & 2).
The bottom row (row 0) is not used.
Thus, latch location 0 is never displayed.
Column 0 controls the left‑most column.
Data from Dot Latch locations 0‑7 determine whether or not pixels in Column 0 are turned‑on or turned‑off.
Therefore, the lower left pixel is turned‑on when a logic high is stored in Dot Latch location 1.
Characters are loaded in serially, with the left‑most character being loaded first and the right‑most character being loaded last.
By loading one character at a time and latching the data before loading the next character, the figures will appear to scroll from right to left."

4桁ディスプレイでは、160bitsが、20列8行に配置されます。
これらの配列は、4つの、5×8のドットマトリクスの配置に概念化することが出来ますが、8行のうち7行だけが、実際のLEDと対応しています(Figure 1と2を参考にしてください)。
一番下の行(row 0)は使われません。
なので、Latch location 0は表示されません。
Column 0は一番左の列を制御します。
0~7のDot latchのデータが、Column 0のピクセルが点灯か消灯かを決定します。

Control Register

"The Control Register allows software modification of the IC’s operation and consists of two independent 7‑bit control words.
Bit D7 in the shift register selects one of the two 7‑bit control words.
Control Word 0 performs pulse width modulation brightness control, peak pixel current brightness control, and sleep mode.
Control Word 1 sets serial/simultaneous data out mode, and external oscillator prescaler.
Each function is independent of the others."

Cotnrol Registerは、ICの動作をソフトウェア的に変更することを可能にします。また、2つの独立した7ビットのコントロールwordsから成ります。
シフトレジスタのBit D7によって、2つの7ビットのコントロールwords(=レジスタ)のうち1つを選択します。
Control Word 0は、パルス幅変調による輝度のコントロール、ピクセルの最大電流による輝度のコントロール、そしてスリープモードについて設定できます。
Control Word 1は、シリアルかsimultaneousなデータ出力の選択、外部oscillatorの分周について設定できます。
それぞれの機能が、他のものとは独立しています。

Control Register Data Loading

"Data is loaded into the Control Register, MSB first, according to the procedure shown in Table 1 and the Write Cycle Timing Diagram.
First, RS is brought to logic high and then CE is brought to logic low.
Next, each successive rising CLK edge will shift in the data on the DIN pin.
Finally, when 8 bits have been loaded, the CE line is brought to logic high.
When CLK goes to logic low, new data is copied into the selected control word.
Loading data into the Control Register takes place while the previous control word configures the display."

データは、Table 1と書き込みタイミングのダイアグラムに示される手順にしたがって、Control Registerに、MSB(最上位のビット)を最初にして読み込まれます。
まず、RSをHighにします。次に、CEをLowにします。
そして、連続するCLKの立ち上がり毎に、DINピンのデータがシフトされていきます。
そして、8bitsがロードされたら、CEをHighにします。
次にCLKがLowレベルに下げられた時、新しいデータは、選択されたControl wordにコピーされます。
Control Registerにデータを読み込むのは、過去のControl wordがディスプレイを設定するのを防ぐ(?)ためです。

※引用符(クォーテーション、"")で囲まれた全ての英文は、"HCMS-29xx Series High Performance CMOS 5 x 7 Alphanumeric Displays Data Sheet"からの引用です。
Read more →

2014/04/03

[旅行記]Vanilla Airで台湾に行った

,
 3/28~30で、Vanilla Airを使って台湾に行ってきました。なので、そのまとめを書こうかなと思います。時系列順に感想を書いていこうと思います。
 カメラはGX1を持っていったのですが、一々カバンに仕舞ってたら撮るのが面倒になってきて、結局あまり撮ってません(100枚もない)。

3/28

今回使った航空会社は、LCC運行会社であるVanilla Air(ANA系列)です。乗った便は、
往路 : JW105 NRT 21:00 → TPE 00:05
復路 : JW102 TPE 11:05 → NRT 15:15
です。
※但し全て現地時間、台湾はGMT+8、TPEは台湾桃園国際空港、NRTは新東京国際空港(成田)。

行動

成田第二ターミナルに到着したのが1945頃で、そこからチェックインし(Fカウンターには10人位並んでいた、15分位待った)、入国手続きなどを経て搭乗口に移動します。
 LCCだとお馴染みのバス移動で飛行機に搭乗します。その後フライトですが、成田は広い飛行場なので、タキシングに30分位掛かりました。
 
 機内では、美味しいと聞いたクリームパン+コーヒーを頼みました(\350)。途中少しだけ気流の影響で揺れましたが、入国カードを書いて寝てたら普通に着いてました。

 台湾桃園国際空港(臺灣桃園國際機場)についたら、もうホテルに移動するのは絶望的(ホテルのチェックイン時間的な意味で、空港付近ならあるかもしれない)なので、空港で寝ることになります。高雄・台中とかなら夜行バスで移動する人もいるらしいですが…。
 とりあえず臺灣銀行の窓口が空いていたので、両替をしました。レートは0.2906。

 事前に調べた所、第一ターミナル(第一航廈)が寝やすいとの事だったので、スカイトレインで移動しました。スカイトレインは空港の端っこの方にあるので、移動がちょっと長いですが、自動運転で直ぐ来る便利な乗り物です。
参考:旅でダラダラ 台湾・桃園国際空港で夜明かし(但し2011年の記事)

 第一航廈では2Fで寝ました。そこら辺に警備の人が立ってるので、割と治安は良さそうです。までもやっぱり怖いので荷物は身体から離せませんでしたが…。第一のB1/B2は駐車場でベンチはなく、1Fは人通り多め、3Fはカウンターだけでベンチなしなので、多分1Fか2Fで寝ることになります。話によれば第二航廈の方がいいとかなんとか…。
 ベンチでは他にも寝ている方がいるので、あまり騒がないようにしましょう。後、充電している中華系の人が居まして、割と日本と似たものを感じたのですが、一応外国ゆえ盗られるのが怖く、私はやりませんでした。
 ちなみに、2Fにはセブン-イレブンもあるので、食べ物などがそこで買えます。肉まんとかもセルフでした

 空港には(というか、台湾だと大体どこにでも)無料Wi-Fiが飛んでいます。暗号化されていませんが、その分ポータルサイトで利用するボタンを押すだけで使用可能になります。
 ベンチ近くのコンセントには、既に端末がずらずらと繋がって充電されてました、が、こっちも盗難が怖いのでモバブで耐えました。

Vanilla Airについて

さて、LCCと言うと、格安ゆえ欠航時の対応が悪い(まあもともと、その旨明記はされている)、座席幅が狭い、機材やりくりが大変なので遅れやすい、サービスの質が悪いという印象がありました。ですが、実際乗ってみると予想してたよりも快適でした。
 
 まあ、大幅な遅延もなかったので、飛ばなかった時の対応については分かりませんが、座席幅は結構ゆとりがありました。また、前の座席との間隔も、特別狭いという程ではなかったです(大柄な私で膝が着くかどうかくらい。そもそもANAの国内線エコノミーだって狭いといえば狭いほうだ)。
 また、ブランケットはこの時期なら上着で代用できますし、私自身は離着陸時に音楽を聞かないので、あの音楽サービスみたいなのも必要としておらず、むしろ必要最低限で値段も低くしている、という感じで悪くなかったです。ただ、スチュワーデスさんは疲れてそうだった…って書くとダメなのかな。でも確かに大変そうだった。

 ただ、非常口付近と一番後ろの座席はリクライニング不可です(11、31列?)。それと、化粧室はA320という中型機のためか、そこまで数が多くないので結構混んでいました。

 飲み物は機内だと\200しますが、空港の搭乗口付近に自動販売機があるので、あまり問題とはならないような気がします。

3/29

この日は終日台湾観光でした。流れとしては、午前に故宮博物院、午後は色々な所を散策、夜には士林夜市に行きました。

まずは台北市街へ

朝起きたら、すでに大量の観光客が通路を歩いてて、寝ている私達のことを好奇の目で見てきました…。周りの寝てた人は全員居なくなっていましたし。

 さて、まず起きたら空港から移動です。桃園機場は鉄道が乗り入れていないので(MRT桃園捷運機場線が建設中です)、
1)台北車站(=台北駅)、他の台北市街地までバスで行く
2)高鐵桃園站(=台湾新幹線(台灣高鐵、TSHR)の桃園駅)までバスで行き、そこから台湾新幹線で台北車站に行く
の2通りがあります。ガイドブックなどでは、1の方が安いのでよく薦められています。ですが今回は、TSHRは日本の新幹線とほぼ同じ車両が走っていると聞き、そっちに乗ることにしました。

 高鐵桃園站へは、Ubusというところが10分毎(?)にバスを出しています。値段は大人がNT$30。切符はカウンターで買うか、もしくは電子マネーのEasy Card(悠遊卡、でも空港では買えない)です。
参考:桃園国際空港=台湾高速鉄道桃園駅・統聯客運(Ubus)の連絡シャトルバス。どうしても空港から新幹線を使いたい人にオススメ!?

 係員のおばさんですけど、例によって互いに英語が片言みたいな感じだったので、コミュニケーションを取るのに結構難儀しました。こっちは何分毎に出るか聞いてるのに、向こうは桃園站行って聞いたらとっととNT$30払えという構え。その会社の別の若いお兄さんが来て、助かりましたが。日本語の方が通じたんですかね。

 桃園站までは15分程度で、割と道が広く、殆ど止まること無く着きました。因みに桃園站にはマクドナルドがあります。日本よりちょい安めです。
バスで桃園站に向かいます。

 次に高鐵に乗るのですが、切符は窓口のほか自動券売機でも購入可能です。クレジットカード(Visa、JCB他)も使用可能でした。使い方は以下のサイトをどうぞ。
参考:台湾高速鉄道(新幹線)- 台北ナビ

 高鐵、日本ほどの間隔、密度では走ってないようなので、予め公式で時間を確認するのが吉かもしれません。
高鐵桃園站改札。台湾の改札はやっぱり日本とは違う。でも大体日本。
高鐵桃園站月台(=Platform)。新幹線だけどホームドアはない。

 高鐵の自由席は10~12号車(と切符には書いてあるけれど、実際9号車も?)です。2+3列の座席でしたが、そのうち「博愛席」と書いてあるシートは、日本で言う優先席です。台湾の方は日本よりも譲り合い精神旺盛なの(と良心に鑑み)で、座らない方がいいです。
 因みに、この日は南方面の電車は指定席が満席だった、北行きは空きがあるようでしたが、北行きの自由席は並んでは取れない程度には混んでいました。

朝食を食べに行く

台北車站に着いたら、まずは荷物を預けます(ホテルは遠いし預かってくれるか分からなかった)。B1の端っこの方にコインロッカーがあります。料金は特大ロッカーでNT$50、お釣りは出なくて、日本語解説有り。ですが3時間毎だかに追加料金が加算されていくので、多分最後に精算することになります。この時機械から吐き出されるレシートが、受け取り時に必要になるので取っておきましょう。
参考:台湾のコインロッカーの預け方~台北駅のロッカーを事例にして~ - 胖胖(ぱんぱん)旅行社~台湾旅行専門ブログ~

 そして、まずは朝飯を食べました。で、この時まだ食事情がよく分からなかったので、持っていったハンドブック「地球の歩き方」に掲載されていた24時間営業の料理屋「吉星港式飲茶」に行きました(台湾の料理ではないらしいとかなんとか)。
 移動するのに先立ち、台北車站のInformation Centerみたいな所でEasy Card(悠遊卡)を買いました(NT$600、うちNT$100はデポジット)。そして淡水線に乗って隣の中山駅へ。
 吉星港式飲茶は駅から徒歩10分くらい、ビルの2Fです。日本語がなんとか通じます。クレカ使用可。朝はおかゆ、麺がNT$70で、他に点心(NT$30)です。魚のカリカリした揚げ物みたいなのが新鮮でした。

故宮博物院を観覧する

次に故宮博物院に行きました。中山駅に戻り、淡水線で士林駅まで乗ります。この時台湾はすでに25度くらいあったので、外は結構暑かったです。ですが逆に、MRTは駅構内からして結構涼しかったように思います。そして、台湾は全体的に空調結構効いてました。
 MRTはドア上の電光掲示板が分かりやすく、英語表記もあるのでまあ普通に乗れました。また、本数が多い(大体昼間行くと1分後に着ますとか書いてある)し、電車到着まで5秒単位で液晶モニタに出るので、山手線を使うような感覚でした。あと、整列乗車がきちんと守られてて台湾人は律儀だなあと感じました。

台湾のバス。真ん中下ら辺に有るのがEasy Cardをタッチするところ。上にあるのが電光掲示板。

 士林から博物院まではバスです。確かC3乗り場(リンク先地図の3)から、紅30/棕13/棕20/255/304系統とかで行けます
 そのバスなのですが、まずは途中下車だったりするので、自分で降りるアクションをしないといけないことが難点です(それはそう)。また、料金の支払い方法もちょっと難しく、捷運士林站⇔故宮博物院なら多分均一運賃区間なのですが、それでも先払いor後払いか分かれてた気もするので、ちょっとそこがややこしいです(日本でもややこしい)。
 よく「下車収票」なら後払い、「上車収票」なら前払いって言いますけど、それが書いてあるのが車内、運転席の上辺りな気がするんですよね…。どちらかと言うと、真ん中の扉なら後払い、前の扉なら前払いみたいな感じがしなくはないです。
 
 バスはよく揺れます、ですが席数が少ないです。また、電光掲示板頼みになるので、壊れてるとつらそうです。
國立故宮博物院 第二展覧エリア

 故宮博物院のチケットは、一般大人はNT$160です(学割があるようです)。1Fで購入して見て回ることになります。やっぱり日本語が通じて、荷物預かりは無料。ペットボトルを始めとして、荷物の持ち込みに関して結構ストイックなので、クロークにお世話になるかと思います。
 展示品ですが、有名な白菜とか有りますけど、どちらかと言うと瑠璃杯の綺麗さに見惚れてました。あと日本にはあまりない(?)玉器、象牙の展示品も見れて、良い体験になりました。

 ちなみに、もちろん故宮にも無料Wi-Fiはあるのですが、ここだけはちょっと面倒な登録が必要でした。

お昼ごはんを食べる

故宮博物院で結構時間をもってかれた(10~13時くらい)ので、お昼ごはんを食べに行きます。今度はガイドブックで食べに行きたいと思っていた、「川味老張牛肉麵店」です。永康街という場所にあるので、まずはMRT東門駅まで移動します。
 駅を出るとそこは繁華街で、バイクと人の多さに驚きつつも、歩いてたらお店に辿り着きました。
 お店に入ると、店員さんが日本語メニューを置いていきました。台湾の人にとっては、日本人というのはすぐ分かるものらしいですね…。私から見ると、道行くアジア系の人は、誰がどの国の人間なのか全く区別もつかなかったのですが、どこ行ってもすぐ日本人だとバレたので、この事には結構驚きました。
 
川味老張牛肉麵店の清燉牛肉麺
清燉牛肉麺と言うものを頼みました。牛肉がどーんと豪快に入ってて、しかも柔らかくてびっくりしました。美味しかったです。味付けは塩を選んだのであっさり目でしたけど、いい感じにお腹一杯になれました。

(なぜか)ゲーセンに行く

この後、同行した人の音ゲー行脚に付き合うため、西門町というところに行きました。西門町というのは、台湾の渋谷みたいな場所で、実際捷運西門站から出ると、スクランブル交差点から見たセンター街のような所でした(道路が斜めに走ってて、若者だらけ)。この街は、今回行った中で一番混雑してて、しかもそこかしこで路上パフォーマンスのようなこともしていて、とても活気がありました。
 
 訪れたゲーセンは、湯姆熊歡樂世界 金萬年店(Tom's World JinWanNian)という所で、「峨眉街」という通りと、「西寧南路」という通りの交差点から、少し南に行ったところにあります。(確か)黄色い看板が目印のビルです。もし行くならば、一応ストリートビューで事前に確認したほうが良さそうです。

 ゲーセンは若者で溢れてて賑やかで、日本のラウンドワンに来たかのような錯覚を覚えます。音ゲーに関して言うと、もう完全に日本語が表示されていたりするので、皆よく操作できるなあと思いながら眺めていました(皆分かるのかな)。ちなみに、プレイするならば専用のコインを購入する必要があります。で、このコイン両替機、10元硬貨をあまり認識してくれず、結構大変でした。


 さて、台湾では、京都のように通りの名前が結構出てきます。交差点などでは、信号の近くに緑色の看板で道路名が書かれていたりするので、それが結構役に立ちました。住所自体は「○○○路××號」のようになっていますが、××號の部分は、これまた緑色の看板があったように思います。

ホテルに行く

そろそろホテルにチェックインしないと、ということでこの日泊まるホテル「皇家季節酒店 台北館」を目指しました。場所はMRT中山駅から西に15分くらい歩いた所(バスなら圓環停車場から直ぐ)です。

 このホテルはツインタワーになっている(二つのビルに入っている)ので、受付が2つあります。今回はツインの部屋を予約していたで、330號のビルでチェックインしました。受付で"Check in?"と聞かれたので、そのまま英語で何とか済ませたんですが、その後ろに居た日本人達が思いっきり日本語喋ってて、結構後悔しました…。

 ホテルの部屋は、都合上トリプルになったんですが、綺麗、しかも豪華で大満足でした。あれは普通にまた泊まりに行きたい。なんてったってバスタブはジャグジー付き、シャワーがまた別の部屋にある(浴室2つ、合わせると自室より大きい)、アメニティもちゃんと充実している、などなど。

 実はこのホテルはExpediaで予約して、51%Offで\11,530(≒NT$3,500)程度だったんですが、台湾だと元値のNT$7,000は思いっきり高級ホテルの枠になるらしいですね。日本の感覚で予約してたので、全然気づきませんでしたが…。実際、その近くのホテルは宿泊でNT$700とかなので、知らず知らずのうちに凄いところを選んだものだと驚きました。
 あと、Expediaは割と使いづらかったので、次回からはなるべく日本の旅行代理店など経由で取ろうと思いました。

士林夜市に行く

夜ご飯ついでに士林夜市に行きます。士林と書いてありますが、実際の最寄り駅は、MRTで1つ南の劍潭站です。

 まず、ホテルからMRTの駅まで行きます。ここで、夕立に襲われました。1時間もないくらいの出来事でしたが、本当に土砂降りだったので、靴がびしょびしょになってしまいました。
 また、雨の中歩きたくないので(台湾は、歩道というよりは道路脇のビルの軒下を延々と歩いて行く感じの土地柄であるが)バスに乗ろうとしたんですけど、通りを1本間違えていたせいで、「どこを走っているのかわからない」なんて事にもなりました。幸いMRTの駅を通ったので降りてみたら、一駅ズレてましたね。

 さて、劍潭站は既に大量の観光客でごった返してました。士林は夜「市」だけあって、食べ物屋ばかりだと思ってたのですが、地上にあるお店はお土産・雑貨を扱う店の方が多かったです。
 
士林夜市。人が多いけれど、満員電車ほどでもない。右側は商標で遊ぶタイプのTシャツ屋

 B1Fに降りると、食べ物屋がずらっと並んでいます。一周してぶらぶら見た後、適当な所のお店で食べることにしました。
 私が台湾で食べられる料理のなかで、行く前から「臭豆腐」というのがかなり気になってました(一体どんな名前だ)。これは発酵させた豆腐を使う揚げ豆腐のようなものなのですが、実際食べてみると普通に美味しかったです。
 また、肉の細切れの乗ったご飯(「魯肉飯」で合ってるのかな)もお気に入りになりました。素朴だけどお肉も相まって美味しい。
 正直下の写真にある5品を2人で食べて十分お腹いっぱいになったので、台湾料理を制覇するぞ!となると、かなり滞在しないと制覇でき無さそうだなあと、頭の片隅に記憶してます。

 また、食べ物だけでなくフルーツを使ったジュースなども人気でした。士林夜市を歩いていると、ジュースの容器をもった人をそこかしこで見かけますし、そういったものを売るお店も多いです。
 自分はスターフルーツのジュースを飲んでみたんですが、想像よりも甘く(スターフルーツと言うとあまり甘くないと聞く)、でもやっぱり飲んだ後の後味は苦めでした。
士林夜市で夜ご飯。左下が臭豆腐、真ん中下が…なんだ?

 地上では、タピオカミルクティーだけ飲みました。タピオカミルクティーというと中華街の印象がありますが、士林夜市で飲んだ物は、中華街のよりもタピオカが大きくて柔らかい食感が強いと感じました。なんというか本場っぽい。
夜市で射的をやってた日本の人達(佐渡から来たそう。)
夜市散策を楽しんだら、またMRTに乗ってホテルに帰ります。

 ホテルでは、なんとNHKが普通に映ってびっくりしました。他にも台湾地元局の他、CNNなども入りました。チャンネル数が多いのを見ると、なんとも外国に来たなあと感じる瞬間でした。

3/30



 この日は起きたら即空港に向かったので、特記することはあまり無いです。

高鐵桃園站に並ぶ、空港行きのバス(Ubus)。
高鐵桃園站⇔桃園機場を移動するバスです。

 空港のチェックインは、何故かEVA Airのカウンターでした。貰った航空券の紙にもEVA Airの模様が書いてあり、コードシェア便なのかと思いましたが、そうでもない様子。
 入国審査場を通る前にお土産(蜜桃烏龍茶の葉っぱ)を買い、手持ちの通貨を全て日本円に戻しました。レートは0.3013。ですが、日本から来る人は大体お札などまとめて両替するからなのか、あまり細かい小銭までは出せないようで、私はNT$2返ってきました(400円あるか?とも聞かれた)。
 また、この先の自販機などでNT$を使うなら、少し残しておいた方が良い気がします。搭乗口に行く途中でも両替所はあったはずなので。

 台湾の空港は実は撮影禁止らしいのですが、そこかしこで観光客が飛行機をカメラに納めてました。黙認してるのかな。

 帰りのVanilla Airは、隣が空席だったので更に快適でした。途中、進行方向右側の窓から、尖閣諸島のような島が見えたのですが、本当にそうなのかは結局分からずじまいです(でも他の島なら道路などがあるとは思う)。

 そして無事成田に到着して、今回の旅は終わりました。

まとめ

今回使った費用です。

Vanilla Air
-----------------------------------------------------------------------
運賃 31,000 JPY(19,000 + 12,000)
空港サービス使用料 1,020 JPY
旅客サービス施設使用料 2,040 JPY
旅客保安サービス使用料 500 JPY

支払い手数料 x2 400 JPY
スタンダードシート(往路) 600 JPY
-----------------------------------------------------------------------
Total 35,560 JPY

皇家季節酒店 台北館
-----------------------------------------------------------------------
1泊(エグゼクティブ ツインルーム) 10,029 JPY
含まれているもの : 無線インターネット (無料) 朝食ビュッフェ

税およびサービス料 1,504 JPY
-----------------------------------------------------------------------
Total 11,533 JPY

その他


・台湾は無料Wi-Fiスポットが充実している。というか日本が少ない。
・台湾は英語が通じるが、それ以上に日本語で結構生きていける。でももしものために、筆談用の紙とペンを用意しておきたい。
・バスは言うほど怖くない、けれど初めてだと路線図と見比べながらになり、気が抜けない。その点MRTは本数も多くて神。
・Easy Cardが便利すぎる。
・iPadのGoogle Mapがかなり便利で、旅行とタブレットは相性が良いなと感じた。
・台湾で食べられるからといって台湾料理とは限らない…。
・ガイドブックは便利で手放せないもの。でも行きたい店は、出来ればストリートビューとかで予習しておくと尚よい。あと、ガイドブックのプラン案はかなり密度が濃くて、初めての土地で迷ってたり、観光地の予想外の混雑に遭遇するなどで、時間的にもなかなか実現が難しい。
・この記事は纏まりに欠け、長くなりすぎた。適度に太字などでハイライトしようと思ったが、使い所を悩む。

Read more →