PICの型番とアーキテクチャの対応

PICの各シリーズとビット数の対応表です。

8ビット
    PIC10,12,16,18
    PIC F1シリーズ
16ビット
    PIC24F,24H,24E
    dsPIC30F,33F,33E
32ビット
    PIC32MX


dsPICは、2003年に作られたもので、DSPの機能を持っている(積和演算が高速に出来る)。

PIC24はその後の2004年に開発されたもの。dsPICとの互換性が意識されているて、ハードウェアで乗算が可能。

PIC32は2008年に開発され、命令セットがMIPS32 Release 2 instruction setになっている。
高性能なので高いかと思いきや、28pinのDIPが250円ぐらいで売っている。

PIC32MX220F032B-I/SP のスペック

クロック        : 40MHz
プログラムメモリ: 32KB
RAM             : 8KB
USB             : 1ch 
I2C             : 2ch
JTAG付き



ここまで安価なら、みんなPIC32MXを使えばよいと思うのだけど、PIC16とかの本が多いのはなぜなんだろう… 過去の資産/互換性の問題があるからだけ?

あと、PIC32の命令セットがMIPSという事は、パタヘネ本の実習用で使えないかな?と思ったりもする。
この間買ったPICkit3で書き込みも出来るらしいので、時間が有ったら試してみたい。

面白い機能を持ったPIC

面白い機能を持ったPICを見つけたでメモしておきます。

16F1827

16F88の後継機種です。
PWM回路が4つ付いているので、複数のモータ制御が出来ます。
データシート状は、ECCP1,ECCP2,CCP3,CCP4モジュールと呼ばれています。
(CCPは、Capture/Compare/PWM moduleの略です)
各回路のデューティ比は、3つのタイマーから指定可能なので、3つモータを付けて、それぞれ別の回転数で駆動させるといった事も可能です。



10F320/322

8pinの小型な製品です。
PLD機能付きで、PIC内に小さなロジック回路を作ることが出来ます
この機能は、CONFIGURABLE LOGIC CELL(CLC)と呼ばれています。



採用するロジックは、3bitのロジックゲート選択レジスタ(LCxMODE)で指定でき、それぞれ以下のゲートになります。


出来る事が限られているので、活用の場面は限られますが、論理回路レベルの遅延で高速動作可能なので、ソフト制御では追いつかない場合に役に立ちそうです。

HEWが自動生成したiodefine.hの読み方(for C言語)

H8マイコンでI/O操作を行うためには、H8のハードウェアマニュアルで指定された番地に対して、メモリの読み書きをすれば操作出来ます。アセンブリだと特定番地に対しするアクセスは容易ですが、C言語の場合、通常は変数が使用するメモリ番地はコンパイラ/リンカが自動で割り振ってくれるので、通常プログラマが具体的な”メモリ番地”を指定する事が有りません。

ですが、I/O操作に限っては具体的な番地を指定したアクセスが必要となります。この為にHEWではiodefine.hというヘッダを自動生成してくれます。

本記事では、H8マイコンが持っているシリアル通信機能(SCI機能)を使用するときに、iodefine.hの定義をどうやって使うかと、動作の仕組みについて説明します。




H8/3694FでシリアルポートをアクセスするにはSCIという機能を使用し、SCIを操作するためのメモリアドレス(レジスタ)は,iodefine.hの以下の定義がされています。
これは、iodefine.hの最後のほうにあります。

#define SCI3    (*(volatile struct st_sci3  *)0xFFA8)   /* SCI3  Address*/



このdefineですが、ちょっと複雑なので分解して考えてみます。

まずは、キャスト演算子です。
キャスト演算子は、指定した値を別の型とみなしてほしい場合に使用します。
たとえば以下のコードはchar型の変数aを,intとみなして代入しています。

char a = 10;
int b = (int)a;




0xFFA8というのは16進数で表記した単なる数字なのですが、これをメモリ番地(アドレス)とみなしてほしい為にキャストを使用しています。以下のコードで、int *型のポインタ変数cがFF8A番地を指すことができます。

int *c = (int *)0xFFA8;



今回は、int型を指すわけではなく構造体を指したいので、以下のコードになります。(st_sci3構造体については後述します。)

(struct st_sci3  *)0xFFA8;



さらに、コンパイラによる最適化を抑制したいのでvolatileを付けます。

(volatile struct st_sci3  *)0xFFA8;


これで、C言語の文法の仕様を使って、メモリの特定番地を指す事ができました。


構造体のポインタ変数だとメンバを指すのにアロー演算子が必要なので、ソース中のコードが見づらくなります。これを解消するためにアドレス演算子「*」を使います。

(*(volatile struct st_sci3  *)0xFFA8)




上記の表記は長いので、defineで別名定義してしまいます。

#define SCI3    (*(volatile struct st_sci3  *)0xFFA8)   /* SCI3  Address*/




というわけで、先ほどのdefine文が出来上がりました。



次に、先ほど説明を省略したst_sci3構造体です。
これは、ちょっと長いですが以下の定義になっています。

struct st_sci3 {                                        /* struct SCI3  */
               union {                                  /* SMR          */
                     unsigned char BYTE;                /*  Byte Access */
                     struct {                           /*  Bit  Access */
                            unsigned char COM :1;       /*    COM       */
                            unsigned char CHR :1;       /*    CHR       */
                            unsigned char PE  :1;       /*    PE        */
                            unsigned char PM  :1;       /*    PM        */
                            unsigned char STOP:1;       /*    STOP      */
                            unsigned char MP  :1;       /*    MP        */
                            unsigned char CKS :2;       /*    CKS       */
                            }      BIT;                 /*              */
                     }          SMR;                    /*              */
               unsigned char    BRR;                    /* BRR          */
               union {                                  /* SCR3         */
                     unsigned char BYTE;                /*  Byte Access */
                     struct {                           /*  Bit  Access */
                            unsigned char TIE :1;       /*    TIE       */
                            unsigned char RIE :1;       /*    RIE       */
                            unsigned char TE  :1;       /*    TE        */
                            unsigned char RE  :1;       /*    RE        */
                            unsigned char MPIE:1;       /*    MPIE      */
                            unsigned char TEIE:1;       /*    TEIE      */
                            unsigned char CKE :2;       /*    CKE       */
                            }      BIT;                 /*              */
                     }          SCR3;                   /*              */
               unsigned char    TDR;                    /* TDR          */
               union {                                  /* SSR          */
                     unsigned char BYTE;                /*  Byte Access */
                     struct {                           /*  Bit  Access */
                            unsigned char TDRE:1;       /*    TDRE      */
                            unsigned char RDRF:1;       /*    RDRF      */
                            unsigned char OER :1;       /*    OER       */
                            unsigned char FER :1;       /*    FER       */
                            unsigned char PER :1;       /*    PER       */
                            unsigned char TEND:1;       /*    TEND      */
                            unsigned char MPBR:1;       /*    MPBR      */
                            unsigned char MPBT:1;       /*    MPBT      */
                            }      BIT;                 /*              */
                     }          SSR;                    /*              */
               unsigned char    RDR;                    /* RDR          */
};                                                      /*              */



これも、いきなり全体を見ると難しいので、順を追って説明します。

まずは大枠を見ると、これは構造体定義になっています。
構造体内に有る”union…”という定義まで一度に確認すると難しくなるので、これを一旦unsigned charに置き換えてみました。

struct st_sci3 {                                        /* struct SCI3  */
               unsigned char    XXX1;
               unsigned char    BRR;
               unsigned char    XXX2;
               unsigned char    TDR;
               unsigned char    XXX3;
               unsigned char    RDR;
};



置き換えると非常にシンプルになりました。これは単なる6byte文の構造体定義ですね。
先ほどのdefineで、無理やり0xFFA8を指していたので、この構造体によって0xFFA8~0xFFADまでのエリアが、メンバを使うことでアクセスできます。
たとえば以下のコードで0xFFA9番地に0xffを書き込むことができます。

SCI3.BRR = 0xff;



次に、省略したunionのところを見ていきます。
全部同じ形になっているので、最初のメンバを見ると、以下の形になっています。

union {                                  /* SMR          */
     unsigned char BYTE;                /*  Byte Access */
     struct {                           /*  Bit  Access */
            unsigned char COM :1;       /*    COM       */
            unsigned char CHR :1;       /*    CHR       */
            unsigned char PE  :1;       /*    PE        */
            unsigned char PM  :1;       /*    PM        */
            unsigned char STOP:1;       /*    STOP      */
            unsigned char MP  :1;       /*    MP        */
            unsigned char CKS :2;       /*    CKS       */
            }      BIT;                 /*              */
     }          SMR;                    /*              */



unionの中はBYTE, BITと、2つのメンバがあります。
これによって、同じ1byteの領域をBYTEとBITのどちらの名前を使ってもアクセスできるようになります。

BITは、データ型が構造体になっており、メンバをビットフィールドで定義されています.
ですので、たとえば以下の2つのコードはともに0xFFA8番地の最上位ビットに1を書き込んでいます。
(メンバSMRは,st_sci3構造体の最初のメンバなので0xFFA8を指すことになります)

SCI.SMR.BIT.COM  = 1;
SCI.SMR.BYTE    |= 0x80;


両者は同じ処理ですが、BIT指定のほうが特定ビットを変更していることが分かり易いです。

また、SMRレジスタの場合下位2ビットのCKSは、2bitで1つの意味を持つデータです。
なので”CKS :2;”と、最後の数字が2になります。


以上で、iodefine.hで定義されている#define文と構造体定義の見方の説明は終わりです。
他にも沢山の#define定義がありますが、同じように見ていけば理解できます。




補足:ビットフィールドの型指定について
ビットフィールドの場合、変数に指定されたデータ型は意味がないように見えますが、実際のところ意味はなく文法上の都合で書いてあるだけです。
ただし、符号には意味があります。bit単位でのアクセスの場合通常unsignedで指定することが多いですが、一応signedも定義は可能です。例えばsigned char d:3とした場合、符号付きの3bitなので-4~3がセットできます。負の数が指定された時にどのようなビット列がセットされるかは処理系に依存します(通常は2の補数表現です)。


※この記事は、前回書いた内容に対する補足です。
12ステップで作る組込みOS自作入門: 1stステップの作成結果

[HEW]コンパイル時,gcc -Wallのように全ての警告メッセージを表示させる方法

H8の統合開発環境であるHEWの話です。

C言語のコンパイラとして、例えばgccを指定する場合だと-Wallオプションを使用することで、未使用変数のチェックなどの数多くの警告を出してくれます。

一方、H8マイコン開発環境のHEWでは、デフォルトでは上記のような軽微な問題に対してメッセージを出してくれません。ですが、このふるまいはコンパイルオプションを変更する事で変えることが出来ます。



変更の手順は以下の通りです。

メニューバーより、ビルド->H8S,H8/300 Standard Toolchainを選択します。


オプション項目の欄から、インフォメーションメッセージを選択します。


“インフォメーションレベルメッセージの表示”のチェックボックスをONにします。下のオプションを見ると分かりますが、このチェックをONにすると”-message”オプションが追加されます。




ここで指定できるチェック項目は以下の様なものです(IDEのバージョンによっても変わるようです)。
特に理由が無ければ全て有効にしておくと、分かりにくいミスを事前に防げるので良いです。

0002 (I) No declarator
宣言子のない宣言があります。
 
0003 (I) Unreachable statement
実行されることのない文があります。
 
0004 (I) Constant as condition
if 文またはswitch 文の条件を示す式として、定数式を指定しています。
 
0005 (I) Precision lost
代入において、右辺の式の値を左辺の型に変換するときに、精度が失われる可能性があります。
 
0006 (I) Conversion in argument
関数の引数の式が、原型宣言で指定した引数の型に変換されます。
 
0008 (I) Conversion in return
リターン文の式が、関数の返す値の型に変換されます。
 
0010 (I) Elimination of needless expression
不要な式があります。
 
0011 (I) Used before set symbol : "変数名"
値を設定せずに使用している変数”変数名”があります。
 
0012 (I) Unused variable "変数名"
使用していない変数”変数名”があります。
 
0015 (I) No return value
void 型以外の型を返す関数の中で、リターン文が値を返していないか、またはリターン文がありません。
 
0100 (I) Function "関数名" not optimized
関数”関数名”のサイズが大きすぎるため、最適化できません。
 
0200 (I) No prototype function
関数のプロトタイプ宣言がされていません。


12ステップで作る組込みOS自作入門: 1stステップの作成結果

読み始めた「12ステップで作る組込みOS自作入門」の本ですが、gccだと書籍の内容そのままで楽しくないので、H8の製造元であるルネサスが出しているIDEのHEWを使用して同じものを作ってみる事にします。

ターゲットのマイコンも,書籍ではH8/3069Fで説明していますが、H8/3694Fをターゲットに作成します。
このチップを使用する理由は、”たまたま手元にあったから”というだけです。
3069FはフラッシュROMが512Kbteなのに対して、3694Fのほうは32kByteしかないので途中で容量不足になりそうな気もしますが、出来るところまで作ってみて足りなくなったらその時に考える事にします。


また、プログラムは書籍に書かれている内容を参考にしつつ、基本的には自分で考えて作ることにします。
ですので一部引数の型が違っていたり、関数仕様は同じだけど中身のロジックが異なる場合も有ります。

というわけで、早速1stステップのプログラムを作成します。
読書メモのほうにも書きましたが、1stで作るのは以下の8ファイルです。

[読書メモ]12ステップで作る組込みOS自作入門

main.c     
    hello worldの本体
 
startup.s  
    スタートアップルーチン/ラベル_startが存在する
    アセンブラで記述されており、ここからmain()がコールされる
 
vector.c   
    割り込みベクタ
    今は、start()しかなく、これはstartup.sの_startラベルに対応している
 
lib.h/lib.c
    標準ライブラリ関数を入れるところ
    今はputs,putcしかない。
    putsputcを使って実装されている
    (なので、今のところputcだけがHW依存になっている)
    putcはserial.cの関数を使っている
 
serial.h/serial.c
    シリアルデバイスドライバ
    0xffffb0,ffffb8,ffffc0のアドレスを直指定で、データのr/wを行っている。
    (シリアルは3つあるらしくプログラムでは0xffffb8から8byte分を使っている)
    クロックを元に9600bpsを算出してるっぽい。
 
defines.h 
    NULLとかuint8,uint16などのdefine
 
ld.scr
    リンカスクリプト
    ここで、各処理が何番地にマッピングされるかを決めているらしい。
    割り込みベクタはCPUの仕様として0番地から始まるので、開始アドレスを決めている。
    ここは、まだ良く分からないけど3章で説明されるらしい...
 
Makefile
    普通のmakefile



HEWを使っていると自動生成してくれるモノもありますが、その辺りも含めてどんなコードになったかを順に見ていきます。



main.c


main関数の中身は同じです。

#include "serial.h"
#include "lib.h"
 
void main(void);
#ifdef __cplusplus
extern "C" {
void abort(void);
}
#endif
 
void main(void)
{
    serial_init();
    puts( "hello world\n" );
 
 
    // 無限ループ
    while( 1 ) ;
 
    return;
}
 
#ifdef __cplusplus
void abort(void)
{
 
}
#endif



書籍の内容と比べると、abort()関数が追加されていますが、これはHEWがプロジェクト作成時に自動生成したものです。
これはHEWのコンパイラがC++も対応しているのが理由で、#ifdef __cplusplusで囲まれているのを見ても分かりますが、C++コンパイラ用のコードです。今回はC言語で書くので無視して良いです。

startup.s

書籍ではスタートアップルーチンを自作してますが、HEWでは完全に自動生成なので、何もする必要がありません。
HEWではresetprg.cというファイルに記載されています。自動生成されたコードはC++コンパイラ対策のifdefなどが大量にあり見づらいので、C言語の場合に有効となるコードだけを抜粋します。

/***********************************************************************/
/*  FILE        :resetprg.c                                            */
/*  DATE        :Tue, Sep 11, 2012                                     */
/*  DESCRIPTION :Reset Program                                         */
/*  CPU TYPE    :H8/3694F                                              */
/*  This file is generated by Renesas Project Generator (Ver.4.16).    */
/***********************************************************************/
#include    <machine.h>
#include    <_h_c_lib.h>
#include    "typedefine.h"
#include    "stacksct.h"
 
extern void main(void);
__entry(vect=0) void PowerON_Reset(void);
 
#pragma section ResetPRG
 
__entry(vect=0) void PowerON_Reset(void)
{ 
     set_imask_ccr((_UBYTE)1);
    _INITSCT();
 
    HardwareSetup();                // Use Hardware Setup
    set_imask_ccr((_UBYTE)0);
 
    main();
 
    sleep();
}



まずプログラムがアセンブラではなく、C言語になっています。
関数名も_startではなくPowerON_Reset()と分かり易いです。

set_imask_ccrは割り込みの無効化処理で、割り込みを一時的に無効にして2つの関数をコールしています。
_INITSCT()はアセンブラで実装されているらしいのですが、まだ良く分かってないので一旦無視します。
HardwareSetup()はプログラマが中身を作る関数です。今回は空っぽのままなので何もしません。

その後main()を呼び、もしmainが終了した場合はCPUがスリープ状態に入ります。組み込みの場合main()の最後に無限ループを入れるのがセオリーですが、万が一戻ってきた場合でも対応出来る様になってます。関数定義の頭にある__entry(vect=0)というのは拡張構文で、これによって割り込みベクタへの登録も行っているようです。

__entryの意味は、ルネサス提供のコンパイラマニュアルで説明があります。

(b) ベクタテーブル生成機能
#pragma interrupt, #pragma indirect, #pragma entry および__interrupt, __indirect, 
__entry のvect 指定を用いて、自動的に関数のベクタテーブルを生成できます。



vector.c (改めintprg.c)

割り込みベクタもHEWが自動生成してくれています。名前はintprg.cとなっていましたが、多分INTerrupt PRoGramの略でしょう。

#include <machine.h>
#pragma section IntPRG
// vector 1 Reserved
 
// vector 2 Reserved
 
// vector 3 Reserved
 
// vector 4 Reserved
 
// vector 5 Reserved
 
// vector 6 Reserved
 
// vector 7 NMI
__interrupt(vect=7) void INT_NMI(void) {/* sleep(); */}
// vector 8 TRAP #0
__interrupt(vect=8) void INT_TRAP0(void) {/* sleep(); */}
// vector 9 TRAP #1
__interrupt(vect=9) void INT_TRAP1(void) {/* sleep(); */}
// vector 10 TRAP #2
__interrupt(vect=10) void INT_TRAP2(void) {/* sleep(); */}
// vector 11 TRAP #3
__interrupt(vect=11) void INT_TRAP3(void) {/* sleep(); */}
// vector 12 Address break
__interrupt(vect=12) void INT_ABRK(void) {/* sleep(); */}
// vector 13 SLEEP
__interrupt(vect=13) void INT_SLEEP(void) {/* sleep(); */}
// vector 14 IRQ0
__interrupt(vect=14) void INT_IRQ0(void) {/* sleep(); */}
// vector 15 IRQ1
__interrupt(vect=15) void INT_IRQ1(void) {/* sleep(); */}
// vector 16 IRQ2
__interrupt(vect=16) void INT_IRQ2(void) {/* sleep(); */}
// vector 17 IRQ3
__interrupt(vect=17) void INT_IRQ3(void) {/* sleep(); */}
// vector 18 WKP
__interrupt(vect=18) void INT_WKP(void) {/* sleep(); */}
// vector 19 Timer A Overflow
__interrupt(vect=19) void INT_TimerA(void) {/* sleep(); */}
// vector 20 Reserved
 
// vector 21 Timer W
__interrupt(vect=21) void INT_TimerW(void) {/* sleep(); */}
// vector 22 Timer V
__interrupt(vect=22) void INT_TimerV(void) {/* sleep(); */}
// vector 23 SCI3
__interrupt(vect=23) void INT_SCI3(void) {/* sleep(); */}
// vector 24 IIC2
__interrupt(vect=24) void INT_IIC2(void) {/* sleep(); */}
// vector 25 ADI
__interrupt(vect=25) void INT_ADI(void) {/* sleep(); */}


__interruptで諸々の割り込みハンドラの関数を登録しています。
全て何もしない関数になってます。

lib.h/lib.c

lib.h、lib.cの中身は書籍と同じです。特に書くべきことが無いので省略します。

serial.h/serial.c

serial.hも書籍と同じです。

serial.cはHEWがI/Oレジスタの定義用変数を用意してくれているので、中身が大きく変わります。
(といっても、行っている内容は同じですが…)

#include "serial.h"
#include "iodefine.h"
 
#define SCI_9600_BPS (64)
 
//***************************************************************************
// Function     : serial_init
//***************************************************************************
int serial_init( void )
{
    int i;
    IO.PMR1.BIT.TXD = 1;            // port1の役割を決める(シリアルとして使用)
 
    SCI3.SCR3.BYTE  = 0;
    SCI3.SMR.BYTE   = 0;            // all0で 8bit, N, 1になる
    SCI3.BRR        = SCI_9600_BPS; // 20MHzの場合は、64を指定で9600bpsになる
 
    // ちょっとスリープする
    for ( i = 0; i < 10000; i++ ) /* nop */;
 
    SCI3.SCR3.BYTE = 0x30;          // RxEnable and TxEnable
 
    SCI3.SSR.BYTE = 0x00;
}
 
//***************************************************************************
// Function     : serial_is_send_enable
//***************************************************************************
int serial_is_send_enable( void )
{
    if ( SCI3.SSR.BIT.TDRE == 1 ) {
        // Txがempty -> 送信可能
        return 0;
    }
 
    // 送信NG
    return 1;
}
 
//***************************************************************************
// Function     : serial_send_byte
//***************************************************************************
int serial_send_byte( unsigned char c )
{
    // 送信可能になるまで待つ
    while( 1 ) {
        // 送信可能かチェック
        if ( serial_is_send_enable() == 0 ) {
            break;
        }
    }
 
    // 1byte送信する
    SCI3.TDR = c;
 
    // TRREのビットを落として(1:not empty)、送信を要求する
    SCI3.SSR.BIT.TDRE = 1;
}


HEWが用意したiodefine.hというヘッダを使用しているため、書籍ではソースの先頭にあった膨大な定義は全て省略できました。コード中で使用しているSCI3構造体はiodefine.hで定義されているのですが、この説明をここで行うと長くなるので後で別記事に書きました。
 HEWが自動生成したiodefine.hの読み方

あと、書籍で使っているH8/3069FはSCIが3つありますが、3694Fにはシリアルが1個しかないので、引数のindexを削除しました。indexはポートを指定するのに使われていたものです。

defines.h

深い理由は有りませんが,deines.hは作ってません。
(後で作るかも)

ld.scr

リンカスクリプトですが、これもHEWが自動生成するので何もすることはありません。
HEWの場合はファイルではなく、コマンドライン引数で指定するらしいです。

これを確認するためには、以下の手順で操作します。
メニューより、ビルド->H8S,H8/300 Standard Toolchainを選択します。


最適化リンカタブの一番下に有るオプションに記載されています。


-noprelink
-rom=D=R
-nomessage
-list="$(CONFIGDIR)\$(PROJECTNAME).map"
-nooptimize
-start=PResetPRG,PIntPRG/0400,P,C,C$DSEC,C$BSEC,D/0800,B,R/0FB80,S/0FE80
-nologo
-output="$(CONFIGDIR)\$(PROJECTNAME).abs"
-end
-input="$(CONFIGDIR)\$(PROJECTNAME).abs"
-form=stype
-output="$(CONFIGDIR)\$(PROJECTNAME).mot"
-exit



色々なオプションが指定されていますが、-startオプションで各領域の先頭アドレスが記載されています。一旦*.absというバイナリを生成した上で、モトローラSフォーレコードフォーマットの*.motファイルを作ってるようです。

*.absというのは聞いたことがない拡張子ですが、エディタで中身を見たらELFフォーマットのバイナリでした。ELFは書籍の5stステップで説明があります。


Makefile

これもIDEによる自動生成です。
リンカについては、前述のリンカオプションでだいたい説明しました。

ビルドオプションのコンパイラタブでは、以下のオプションが定義されていました。

-cpu=300HN
-object="$(CONFIGDIR)\$(FILELEAF).obj"
-outcode=sjis
-debug
-nolist
-chgincpath
-nologo



gccでは-Wallオプションですべての警告を表示させていますが、HEWでは表示されない警告も有ります。HEWでも-Wallと同等のことを行うことも可能ですが、方法は改めて説明します。
-> [HEW]コンパイル時,gcc -Wallのように全ての警告メッセージを表示させる方法


あと、H8に詳しい人から教えてもらったのですが、H8マイコンについて知りたい場合は、
以下の本が良いらしいです。
4274079643
C言語でH8マイコンを使いこなす
著者が、H8の製造元であるルネサスの方で、しかも講師をしている人なので内容も分かりやすく深いところまで書かれています。読む上でC言語の知識は必要ですが、本記事を見ている(OS自作に興味がある)人はその辺は問題ないでしょうから、手元に置いておく事をお勧めします。

ここまで作った分のソース(HEWのプロジェクトファイル)です。
ダウンロード: kozos_1st.zip

変数の特定ビットだけを0に落とす時に、条件式を簡単に書く

※本記事の例はC言語ですが、java,C#などのビット操作が出来る言語に共通した話です。

まずは、ビット操作の基本的な考え方です。
たとえばcharがたの変数dataから、5bit目だけ0に落としたい場合を考えます。

この場合のコードをシンプルに書くと、以下のようになります

char data = xxx;
char ans  = data & 0xDF;



これは、以下の論理式演算(ビット単位のand)を行って、特定ビットを落としています。

        (data)  xxxx xxxx
and     (0xdf)  1101 1111
--------------------------
                xx0x xxxx



というわけで、落としたいビット以外が1になった値と”&”を取ればOKです。



..ですが、5bit目を落とすために書いた値が0xdfというのは、直観的にわかりづらく、可読性に劣ります

このような場合は、ビット単位の否定演算子である”~”と組み合わせて書くと分かり易いです。

char data = xxx;
char ans  = data & ~(0x20);	/* 5bit目だけを落とす */



0x20であれば、5bit目だけが1であることが直ぐにわかるので見やすいです。


逆に特定ビットだけを立てたい時はというと、これはビット単位でorを取ればよいだけなので特に問題ないです。

char data = xxx;
char ans  = data | 0x20;	/* 5bit目だけを立てる */






–補足–
通常のアプリの場合はこれでおしまいですが、マイコンの場合は例外的な場合もあります。
マイコンの場合は、I/Oのアクセスがメモリ空間に割り当てられている、メモリマップドIOになっている場合が多いです。

この場合、I/Oを操作するメモリは、一部Write Onlyになっている場合があります。

たとえばH8マイコンではポート入出力を指定するI/OにPCRレジスタというものがあります。このレジスタのアクセスは”W”(書き込みのみ)という仕様であることが明記されています。


このような場合は、すべてのビットを明示的に指定する必要があります(他のビットは現状維持としたい場合は、前に値をセットした際に、その値を別の変数などで覚えておきます)。

マイコンで使わないI/Oピンを,出力モードにすべき理由

PICなどのワンチップマイコンを使ってプログラムを作る際、場合よっては全ポートを使用しない場合もあるかと思います。

未使用のI/Oポートがある場合、該当のピンをinputとoutputのどちらにするかという疑問がありました。
どちらでも問題ないかと思っていたのですが、出力にしておいたほうが良いらしいです。


理由ですが、出力にしておくと、ピンの先を何も接続していないオープンな状態でも良くなります。

でも、入力ピンにする場合は、ピンの先をプルアップorプルダウンする必要があります。
これは、入力をオープンにすると、ノイズによる動作の危険があるためです。

回路上、使わないピンをすべてプルアップorプルダウンしてあれば入力にしたまま放っておいても構わないのですが、通常は配線が面倒なので何も接続していない事も多いかと思います。
このような回路構成の場合、面倒でも使わないI/Oピンは明示的に出力モードにすべきです。

C#でAmazonのMWSを使用して,マケプレの出品情報を取得する

Amazonでは、Marketplace WebService API(Amazon MWS)を使用することで、マーケットプレースに出品されている商品の出品情報を取得する事が出来ます。
今回は、VisualStudioよりC#を使用して、マケプレの出品情報を取得するプログラムを作成してみます。
(phpで同じことをしたい場合はこちらの記事を参考にしてください)

Amazonマーケットプレイス徹底活用

サンプルプログラムの実効結果

今回のサンプルプログラムによって、以下の様なデータを取得できます。
結果が長いので一部省略しています。


=============================================================================
Status : Success
ASIN  : 4478312141
------------------------------------------------
コンディション   :中古品 良い
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :93 (高評価率:95-97%)
出品数           :2
総額             :\1110(送料:\250)
------------------------------------------------
コンディション   :中古品 非常に良い
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :842 (高評価率:98-100%)
出品数           :1
総額             :\1110(送料:\250)
------------------------------------------------
コンディション   :中古品 良い
出荷元           :FBA
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :15683 (高評価率:95-97%)
出品数           :4
総額             :\1155(送料:\0)
 
...中略...
 
=============================================================================
Status : Success
ASIN  : 4797330058
------------------------------------------------
コンディション   :中古品 非常に良い
出荷元           :出品者
国内より発送     :Unknown
発送日数(最大)   :0-2 days
フィードバック数 :6 (高評価率:98-100%)
出品数           :1
総額             :\675(送料:\250)
------------------------------------------------
コンディション   :中古品 良い
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :356918 (高評価率:95-97%)
出品数           :4
総額             :\675(送料:\250)
...
hit any key



一回のAPI呼び出しで、プログラム内にハードコーディングした2つのASINの出品情報を取得しています。

Amazon MWS APIの概要


Amazon MWSのAPIについて、基本的な情報は以下の記事を参考にしてください。

APIによる商品情報取得
Amazon MWSで商品の情報を取得する « nanoblog

APIの呼び出し回数の制限
Amazon MWSのAPIリクエスト制限の仕組み « nanoblog

MWSの商品APIをコールした時の実行結果例(xmlの生データ)
Amazon MWS商品APIの実行結果例 « nanoblog


商品情報の取得には、GetLowestOfferListingsForASINのAPIを使用します。
このAPIの仕様はAmazonのサイトにも記載されていますが、呼び出し頻度に上限があり20回/分を超えるとエラーになります。また商品情報の取得は、API呼び出し一回で最大20ASINまで指定可能です。

マーケットプレースでは、1つの商品に対して複数の出品(多い時は100件以上)が有りますが、APIで取れるのは価格が低いほうから10件程度のようです。この制限は、APIのパラメータを工夫することで後続のデータを取得する事も可能です。


データの取得には、Amazonから提供されているクライアントライブラリを使用しています。
クライアントライブラリはdll形式になっており、このdllはAmazonから提供されているソースをビルドすれば入手できます。

ですので、VisualStudioさえあればdllは誰でも用意できるのですが、dllを作るのが面倒な人の為にビルド済みのdllを置いておきます。
ダウンロード:MarketplaceWebServiceProducts_dll.zip

また、Amazon MWSのAPIを使用するには、マーケットプレースに大口出品者として登録している必要があります(大口出品者でないとAPI呼び出しに必要なIDが手に入りません)。



API呼び出しのサンプルプログラム

それでは、サンプルのプログラムです。
200行以上有りますが、ほとんどはshowResponse()メソッドで、これは取得したデータを画面に出力する処理なので、実質はMain()メソッドの50行程度です。

using System;
using System.Xml.Serialization;
using System.Collections.Generic;
using MarketplaceWebServiceProducts;
using MarketplaceWebServiceProducts.Mock;
using MarketplaceWebServiceProducts.Model;
 
public class MwsTest {
    private static string accessKeyId     = "xxxx";		// 設定してください!!
    private static string secretAccessKey = "xxxx";		// 設定してください!!
    private static string merchantId      = "xxxx";		// 設定してください!!
    private static string marketplaceId   = "xxxx";		// 設定してください!!
 
    public static void Main(string [] args) {
 
        MarketplaceWebServiceProductsConfig config = new MarketplaceWebServiceProductsConfig();
        config.ServiceURL = "https://mws.amazonservices.jp/Products/2011-10-01";
 
        //-------------------------------------
        // WebService情報オブジェクトを取得
        //-------------------------------------
        MarketplaceWebServiceProductsClient service = new MarketplaceWebServiceProductsClient(
                         "nanoappli.com_sample", "1.0.0.0", accessKeyId, secretAccessKey, config);
 
 
        //-------------------------------
        // リクエストパラメータのセット
        //-------------------------------
        GetLowestOfferListingsForASINRequest request = new GetLowestOfferListingsForASINRequest();
 
        ASINListType asinList = new ASINListType();
        asinList.ASIN = new List<string>();
        asinList.ASIN.Add( "4478312141" );
        asinList.ASIN.Add( "4797330058" );
 
        request.ASINList      = asinList;
        request.SellerId      = merchantId;
        request.MarketplaceId = marketplaceId;
 
        //-------------------------------
        // MWSリクエストAPIの実行
        //-------------------------------
        GetLowestOfferListingsForASINResponse response = null;
        try {
            response = service.GetLowestOfferListingsForASIN(request);
        } 
        catch (MarketplaceWebServiceProductsException ex) 
        {
            Console.WriteLine("Caught Exception: " + ex.Message);
            Console.WriteLine("Response Status Code: " + ex.StatusCode);
            Console.WriteLine("Error Code: " + ex.ErrorCode);
            Console.WriteLine("Error Type: " + ex.ErrorType);
            Console.WriteLine("Request ID: " + ex.RequestId);
            Console.WriteLine("XML: " + ex.XML);
            Console.WriteLine("ResponseHeaderMetadata: " + ex.ResponseHeaderMetadata);
        }
 
        showResponse( response );
 
        Console.WriteLine("hit any key");
        Console.ReadKey();
    }
 
 
    //****************************************************************************
    // Function     : showResponse
    // Description  : Webサービス実行結果の表示
    // Params       : response WebAPI実行結果
    //****************************************************************************
    public static void showResponse( GetLowestOfferListingsForASINResponse response ) {         
 
        List<GetLowestOfferListingsForASINResult> resultList = response.GetLowestOfferListingsForASINResult;
        foreach (GetLowestOfferListingsForASINResult getLowestOfferListingsForASINResult in resultList) {
            Console.WriteLine ("=============================================================================");
            if (getLowestOfferListingsForASINResult.IsSetstatus()) {
                Console.WriteLine("Status : {0}",  getLowestOfferListingsForASINResult.status);
            } 
 
            //----------------
            // 商品の情報
            //----------------
            if (getLowestOfferListingsForASINResult.IsSetASIN()) {
                Console.WriteLine("ASIN  : {0}",  getLowestOfferListingsForASINResult.ASIN);
            } 
 
            if (getLowestOfferListingsForASINResult.IsSetProduct()) {
                Product  product = getLowestOfferListingsForASINResult.Product;
 
                if (product.IsSetSalesRankings()){
                    SalesRankList  salesRankings = product.SalesRankings;
                    List<SalesRankType> salesRankList = salesRankings.SalesRank;
                    foreach (SalesRankType salesRank in salesRankList) {
                        Console.WriteLine("                        SalesRank");
                        if (salesRank.IsSetProductCategoryId())
                        {
                            Console.WriteLine("カテゴリID :{0}", salesRank.ProductCategoryId);
                        }
                        if (salesRank.IsSetRank())
                        {
                            Console.WriteLine("ランク :{0}", salesRank.Rank);
                        }
                    }
                }
 
 
                if (product.IsSetLowestOfferListings()) {
                    LowestOfferListingList  lowestOfferListings = product.LowestOfferListings;
                    List<LowestOfferListingType> lowestOfferListingList = lowestOfferListings.LowestOfferListing;
 
                    //-----------------------------------------
                    // 取得した全出品情報を表示するまで繰り返し
                    //-----------------------------------------
                    foreach (LowestOfferListingType lowestOfferListing in lowestOfferListingList) {
                        Console.WriteLine("------------------------------------------------");
 
                        if (lowestOfferListing.IsSetQualifiers()) {
                            QualifiersType  qualifiers = lowestOfferListing.Qualifiers;
                            if (qualifiers.IsSetItemCondition()) {
                                String condName    = getConditionName( qualifiers.ItemCondition );
                                String subCondName = "";
                                if (qualifiers.IsSetItemSubcondition()) {
                                    subCondName = getItemSubconditionName( qualifiers.ItemSubcondition );
                                }
                                Console.WriteLine("コンディション   :{0} {1}", condName, subCondName );
 
                            }
 
                            if (qualifiers.IsSetFulfillmentChannel()) {
                                Console.WriteLine("出荷元           :{0}", qualifiers.FulfillmentChannel);
                            }
                            if (qualifiers.IsSetShipsDomestically()) {
                                Console.WriteLine("国内より発送     :{0}", qualifiers.ShipsDomestically);
                            }
                            if (qualifiers.IsSetShippingTime() && qualifiers.ShippingTime.IsSetMax()) {
                                Console.WriteLine("発送日数(最大)   :{0}", qualifiers.ShippingTime.Max);
                            }
                            if (lowestOfferListing.IsSetSellerFeedbackCount()) {
                                Console.Write("フィードバック数 :{0}", lowestOfferListing.SellerFeedbackCount);
                                if (qualifiers.IsSetSellerPositiveFeedbackRating()) {
                                    Console.Write(" (高評価:{0})", qualifiers.SellerPositiveFeedbackRating);
                                }
                                Console.WriteLine("");
                            }
 
 
                        }
                        if (lowestOfferListing.IsSetNumberOfOfferListingsConsidered()) {
                            Console.WriteLine( "出品数           :{0}", lowestOfferListing.NumberOfOfferListingsConsidered);
                        }
 
                        //------------------
                        // 価格情報
                        //------------------
                        if (lowestOfferListing.IsSetPrice()) {
                            PriceType  price1 = lowestOfferListing.Price;
                            if (price1.IsSetLandedPrice()) {
                                Console.Write( "総額             :" + getPriceName( price1.LandedPrice ) );
                            }
 
                            if (price1.IsSetShipping()) {
                                Console.WriteLine( "(送料:" + getPriceName( price1.Shipping ) + ")" );
                            }
                        }
                    }
                }
 
 
            }
 
            if (getLowestOfferListingsForASINResult.IsSetError()) {
                Console.WriteLine( "エラーが発生しました" );
                Error  error = getLowestOfferListingsForASINResult.Error;
                if (error.IsSetType()) {
                    Console.WriteLine("Type: {0}", error.Type);
                }
                if (error.IsSetCode()) {
                    Console.WriteLine("Code: {0}", error.Code);
                }
                if (error.IsSetMessage()) {
                    Console.WriteLine("Message: {0}", error.Message);
                }
            }
        }
 
    }
 
 
    //****************************************************************************
    // Function     : getConditionName
    // Description  : コンディション名(日本語)を取得する
    //****************************************************************************
    private static string getConditionName( string inStr ) {
        switch( inStr ) {
            case "New":
                return "新品";
            case "Used":
                return "中古品";
            case "Collectible":
                return "コレクター品";
            case "Refurbished":
                return "再生品";
            default:
                return inStr;
        }
    }
 
    //****************************************************************************
    // Function     : getItemSubconditionName
    // Description  : サブコンディション名(日本語)を取得する
    //****************************************************************************
    private static string getItemSubconditionName( string inStr ) {
        switch( inStr ) {
            case "New":
                return "新品";
            case "Mint":
                return "ほぼ新品";
            case "Very Good":
            case "VeryGood":
                return "非常に良い";
            case "Good":
                return "良い";
            default:
                return inStr;
        }
    }
 
    //****************************************************************************
    // Function     : getFulfillmentChannelName
    // Description  : 出荷元(日本語)を取得する
    //****************************************************************************
    private static string getFulfillmentChannelName( string inStr ) {
        switch( inStr ) {
            case "Amazon":
                return "FBA";
            case "Merchant":
                return "出品者";
            default:
                return inStr;
        }
    }
 
 
    //****************************************************************************
    // Function     : getPriceName
    // Description  : 価格(通貨単位付き)を取得する
    //****************************************************************************
    private static string getPriceName( MoneyType inData ) {
        string outStr = "";
 
        // 通貨単位のセット
        if ( inData.IsSetCurrencyCode() ) {
            switch ( inData.CurrencyCode ) {
                case "JPY":
                    outStr += "\\";
                    break;
                case "USD":
                    outStr += "$";
                    break;
                default:
                    outStr += "(" + inData.CurrencyCode + ")";
                    break;
            }
        }
 
        // 金額のセット
        if ( inData.IsSetAmount()) {
            outStr += String.Format( "{0:0}", inData.Amount );
        }
 
        return outStr;
    }
}



DLLでは、各APIメソッド毎にクラスが用意されており、出品情報の取得に使用するクラスはGetLowestOfferListingsForASINRequestです。API仕様と見比べると”APIの名称+Request”がクラス名になっていることが分かります。

requestオブジェクトは、検索条件を指定するためのプロパティがありますので、適宜設定していきます。
必須パラメータを設定し忘れると、API呼び出し時にエラーとなります。

その後、WebServiceを管理するためのオブジェクトであるMarketplaceWebServiceProductsClientクラスのインスタンスを生成します。serviceオブジェクトのメソッドに、先ほど作ったrequestを引数として渡す事でAPI呼び出しが行われます。

API呼び出しの結果は、戻り値のresponseオブジェクトより取得します。
応答データには結果値が省略可能な項目も有あります。実際にデータが取れたかはIsSetXXXX()メソッドで確認可能なので、一旦確認した上でデータを取り出します。

取得データは原則として英語なので、サンプルプログラムでは、getConditionName()等のアクセサを使用して日本語に変換しています。

自分でプロジェクトを作るには…


このサンプルプログラムを、プロジェクト作成のところから自分で全部したい場合は、以下の手順で作業します。

プロジェクトを新規作成します。

メニューバーの”プロジェクト->参照の追加”よりMarketplaceWebServiceProducts.dllを参照設定します。


前述のコードをコピー&ペーストします。

コード先頭にある以下のIDを設定します。
セットする値の取得方法はこちらの記事を参照してください。

    private static string accessKeyId     = "xxxx";		// 設定してください!!
    private static string secretAccessKey = "xxxx";		// 設定してください!!
    private static string merchantId      = "xxxx";		// 設定してください!!
    private static string marketplaceId   = "xxxx";		// 設定してください!!




設定が面倒な場合は、プロジェクトファイルごと用意したので、ダウンロードした上で適当に改造してみてください。このプロジェクトファイルはVisual Stdio 2010の環境で.NetFramework 4.0を使用して作成しています。
ダウンロード:AmazonMwsSample.zip


工事担任者DD1種のテキストを購入

工事担任者のDD1種を受験申し込みしてみたので、テキストを購入しました。
書店で見ると、工事担任者向けのテキストは幾つかありますが、よさげなのはリックテレコムとオーム社の2冊です。

4897978807
リックテレコム: 工事担任者 DD1種標準テキスト 改訂版


4274211568
オーム社: 工事担任者DD第1種徹底研究 (LICENCE BOOKS)

評判をネットで調べた感じだとリックテレコムのテキストを勧める人が多いけど、本屋でチェックしてみたところオーム社のほうが良いのでこの本を購入しました。

リックテレコムは絵が多く、電気が初めてな人には分かりかもしれないけど、理解度を確認するための問題が少ないです。一方、オーム社のほうは、各節単位で問題が1~2問用意されているので、自分が理解できてるか把握しやすい。
特に計算問題系だと、見てるだけだと分かった気になるけど、実際手を動かして計算してみると解けないことも多いです。なので個人的には、各節単位で小問が小刻みに出てきてくれるのは結構重要です。

図はリックテレコムのほうが多いので、絵で見て理解したいタイプの人には良いのかも。問題集を同時に買って、問題を解きながらテキストを読んでいくタイプの人にはこちらを選ぶのもお勧めです。



あと、DD一種の試験範囲を纏めておきました。
公式のWebにも同じ内容がありますが、全試験の一覧になっており分かり辛かったので必要分だけを整理しました。pdf版も作ったので、一枚印刷しておいて、勉強が終わった項目を都度マーカーで塗りつぶしていくと、どこまで終わったかが俯瞰で分かるので達成感が得られて良いです。
工事担任者DD一種 試験範囲.zip







それぞれの書籍の目次です。
4897978807
リックテレコム: 工事担任者 DD1種標準テキスト 改訂版

第 I 編     電気通信技術の基礎
    1.電気回路
    2.電子回路
    3.論理回路
    4.伝送理論
    5.伝送技術
 
第 II 編    端末設備の接続のための技術及び理論
    1.端末設備の技術
    2.ネットワークの技術
    3.情報セキュリティの技術
    4.接続工事の技術
 
第 III 編   端末設備の接続に関する法規
    1.電気通信事業法
    2.工事担任者規則、技術基準適合認定等規則
    3.端末設備等規則
    4.有線電気通信法、有線電気通信設備令
    5.不正アクセス禁止法、電子署名法




4274211568
オーム社: 工事担任者DD第1種徹底研究 (LICENCE BOOKS)

I編  電気通信技術の基礎
 1章  電気工学の基礎
  1-1  直流回路I(オームの法則と電気抵抗)
  1-2  直流回路II(キルヒホッフの法則等)
  1-3  直流回路III(電力・電力量と発熱量)
  1-4  静電界およびコンデンサ
  1-5  静磁界と電流による磁界
  1-6  誘導起電力および磁気回路
  1-7  交流の波形
  1-8  交流回路
  1-9  交流電力
  1-10  半導体の原理と性質
  1-11  ダイオードの活用
  1-12  トランジスタの基礎
  1-13  トランジスタ増幅回路
  1-14  その他の主な半導体素子
  1-15  論理回路
  1-16  論理式(ブール代数)とベン図
 2章  電気通信の基礎
  2-1  伝送量の求め方
  2-2  線路の伝送特性
  2-3  伝送路の雑音とひずみ
  2-4  漏話現象
  2-5  変調方式の種類I(変調と復調)
  2-6  変調方式の種類II(PCM)
  2-7  ケーブルの種類と特徴I(メタリックケーブル)
  2-8  ケーブルの種類と特徴II(光ファイバケーブル)
  2-9  多重伝送方式
II編  端末設備の接続のための技術および理論
 1章  端末設備の技術
  1-1  DSL技術の概要
  1-2  PPPoEによる通信シーケンス
  1-3  IP電話システム
  1-4  OSI参照モデル
  1-5  LAN
  1-6  LAN間接続
  1-7  イーサネットLANの種類
  1-8  無線LAN
  1-9  電磁波妨害・雷害対策
 2章  ネットワークの技術
  2-1  データ伝送技術I(伝送方式等)
  2-2  データ伝送技術II(伝送品質等)
  2-3  同期方式
  2-4  誤り制御方式
  2-5  データ伝送制御手順(HDLC手順)
  2-6  ATMネットワーク交換方式
  2-7  ブロードバンドアクセスの技術
  2-8  IPネットワーク
  2-9  IPの概要
  2-10  IPv4(IPバージョン4)アドレスの概要
  2-11  IPv6(IPバージョン6)アドレスの概要
  2-12  IPルーティング
  2-13  TCPとUDP
  2-14  ICMPとping
  2-15  アプリケーションプログラム
  2-16  VoIP関連プロトコル
  2-17  IP電話の音声品質
  2-18  VPN(仮想私設網)
 3章  情報セキュリティの技術
  3-1  情報セキュリティの脅威
  3-2  暗号化技術
  3-3  電子認証技術とデジタル署名技術
  3-4  セキュリティ・プロトコル
  3-5  端末設備とネットワークのセキュリティ
  3-6  無線LANのセキュリティ
  3-7  情報セキュリティ管理
 4章  接続工事の技術
  4-1  UTPケーブルによる接続
  4-2  光ファイバの接続
  4-3  LANの配線工事
  4-4  LAN配線工事
  4-5  JIS X 5150構内情報配線システム
  4-6  工程管理の基本
  4-7  アロー形ネットワーク工程表の読み方
  4-8  安全管理
  4-9  品質管理
III編  端末設備の接続に関する法規
 1章  電気通信事業法および施行規則
  1-1  総則
  1-2  電気通信事業
  1-3  電気通信設備
  1-4  端末設備の接続等
 2章  工担者規則,認定等規則
  2-1  工事担任者に関する規則
  2-2  端末機器の技術基準適合認定等に関する規則
 3章  端末設備等規則
  3-1  用語の定義と責任の分界
  3-2  安全性等
  3-3  電波を使用する端末設備
  3-4  アナログ電話端末
  3-5  移動電話端末
  3-6  専用通信回線設備等端末
 4章  有線電気通信法関連
  4-1  有線電気通信法
  4-2  有線電気通信設備令および施行令I(用語の定義等)
  4-3  有線電気通信設備令および施行令II(架空電線等)
  4-4  有線電気通信設備令および施行令III(屋内配線等)
 5章  関連法規
  5-1  不正アクセス行為の禁止等に関する法律
  5-2  電子署名および認証業務に関する法律

[javascript]スクロールバーなどを含めたウィンドウのサイズを知る方法

備忘録としてのメモ。


window.open()で指定する幅と高さの解釈はブラウザによって異なり、ウィンドウ内部領域と見なすものもあれば、スクロールバーなどの枠を含めたウィンドウ全体の大きさと見なすモノも有る。

枠の中の実サイズを知りたい場合、innerWidth/Heightが使える場合はそれを使用すると簡単

resizeToはウィンドウ内部のサイズを指定するが、offsetWidth/Heightはスクロールバーなどの枠を含めたウィンドウ全体の大きさを返すので、その差でinnerWitdh/Heightを求める。

window.resizeTo()はChromeだと使用できない。

outerWidth/outerHeightプロパティはReadOnlyなので値のセットは出来ない(resizeTo/resizeByメソッドを使用する)


スクロールバーなどの枠を含めた、ウィンドウのサイズを知る関数

function getWindowSize() {
    var wW, wH;
    if (window.outerWidth) {
    	// outerWidth,outerHeightが使える時は、簡単
        wW = window.outerWidth;
        wH = window.outerHeight;
        return { width: wW, height: wH };
    }
 
 
    var cW = document.body.offsetWidth;
    var cH = document.body.offsetHeight;
 
    // 一旦適当な大きさにしてからoffsetWidthとの差を調べて、枠のサイズを求める
    window.resizeTo(500,500);
    var barsW = 500 - document.body.offsetWidth;
    var barsH = 500 - document.body.offsetHeight;
 
	// 元のサイズに戻す
    wW = barsW + cW;
    wH = barsH + cH;
    window.resizeTo(wW,wH);
 
    return { width: wW, height: wH };
}



コードは,Getting the width/height of the entire browser in IE?を元に一部改変
(http://stackoverflow.com/questions/1045050/getting-the-width-height-of-the-entire-browser-in-ie/4355458#4355458)


PHPでAmazonのMWSを使用して,マケプレの出品情報を取得する

PHPでASINを指定して、Amazon.co.jpのサイトより、マーケットプレースに出品されている商品の情報を取得するサンプルのプログラムです。
データの取得にはAmazon Marketplace WebService(MWS)を使用しています。

Amazonから提供されているクライアントライブラリはサンプルコードが添付されているのですが、
内容が冗長で分かり辛いので書き直しました。



実行手順:
下記のサイトより、クライアントライブラリをダウンロードします。(タイトル右のボタンをクリック)
商品API セクション クライアントライブラリ – PHP – バージョン 2011-10-01


ダウンロードしたzipファイルを展開します。

Test.phpをダウンロードし、srcフォルダの下に置きます。
Test.zip


Test.phpの先頭4行に有るdefineを書き換えます。
セットする値はこちらの記事を参照してください。


windowsの場合,php.iniを編集します。

コマンドラインより”php Test.php”を実行します。
※APIの呼び出し上限は,20回/分です。



Amazonマーケットプレイス徹底活用

プログラムを実行すると、以下の様な結果が表示されます。

=====================================================================
Status :Success
ASIN   :4478312141
------------------------------------------------
コンディション   :中古品(良い)
出荷元           :FBA
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :15535 (高評価:95-97%)
出品数           :4
総額             :\1155 (送料:\0)
------------------------------------------------
コンディション   :中古品(Acceptable)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :1 (高評価:98-100%)
出品数           :1
総額             :\1155 (送料:\250)
------------------------------------------------
コンディション   :中古品(Acceptable)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :3037 (高評価:90-94%)
出品数           :1
総額             :\1155 (送料:\250)
------------------------------------------------
コンディション   :中古品(非常に良い)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :842 (高評価:98-100%)
出品数           :1
総額             :\1155 (送料:\250)
------------------------------------------------
コンディション   :中古品(良い)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :829 (高評価:98-100%)
出品数           :3
総額             :\1157 (送料:\250)
------------------------------------------------
...中略...
 
=====================================================================
Status :Success
ASIN   :4797330058
------------------------------------------------
コンディション   :中古品(良い)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :356695 (高評価:95-97%)
出品数           :4
総額             :\675 (送料:\250)
------------------------------------------------
コンディション   :中古品(非常に良い)
出荷元           :出品者
国内より発送     :Unknown
発送日数(最大)   :0-2 days
フィードバック数 :6 (高評価:98-100%)
出品数           :1
総額             :\675 (送料:\250)
------------------------------------------------
コンディション   :中古品(非常に良い)
出荷元           :出品者
国内より発送     :True
発送日数(最大)   :0-2 days
フィードバック数 :0 (高評価:Just Launched)
出品数           :1
総額             :\781 (送料:\250)





ちょっと長いですが、サンプルコードの中身です。
コードのライセンスはApache Licence 2.0なので、自由に改造してください。
(コードを引用する場合は本ページへのリンクを張っていただけると有難いです)

<?php
define('AWS_ACCESS_KEY_ID',     '値をセットしてください!!');
define('AWS_SECRET_ACCESS_KEY', '値をセットしてください!!');  
define('MERCHANT_ID',           '値をセットしてください!!');
define('MARKETPLACE_ID',        '値をセットしてください!!');
set_include_path( get_include_path() . PATH_SEPARATOR . 'MarketplaceWebServiceProducts/.' );    
 
 
// メイン処理の実行
main();
 
//****************************************************************************
// Function     : main
// Description  : メイン処理
//****************************************************************************
function main() {
 
    //--------------------------------
    // Webサービス情報の取得
    //--------------------------------
    $service = getService();
    //単体テスト用(MarketplaceWebServiceProducts/Mockのxmlファイルを使用)
    //$service = new MarketplaceWebServiceProducts_Mock();
 
 
    //-------------------------------
    // リクエストパラメータのセット
    //-------------------------------
    $asinList = new MarketplaceWebServiceProducts_Model_ASINListType();
    $asinList->setASIN( array( '4478312141', '4797330058' ) );
 
    $request = new MarketplaceWebServiceProducts_Model_GetLowestOfferListingsForASINRequest();
    $request->setSellerId( MERCHANT_ID );
    $request->setMarketplaceId( MARKETPLACE_ID );
    $request->setASINList( $asinList );
 
 
    //-------------------------------
    // MWSリクエストAPIの実行
    //-------------------------------
    try {
        $response = $service->getLowestOfferListingsForASIN($request);
    } catch (MarketplaceWebServiceProducts_Exception $ex) {
        echo("Caught Exception: "       . $ex->getMessage()    . "\n");
        echo("Response Status Code: "   . $ex->getStatusCode() . "\n");
        echo("Error Code: "             . $ex->getErrorCode() . "\n");
        echo("Error Type: "             . $ex->getErrorType() . "\n");
        echo("Request ID: "             . $ex->getRequestId() . "\n");
        echo("XML: "                    . $ex->getXML() . "\n");
        echo("ResponseHeaderMetadata: " . $ex->getResponseHeaderMetadata() . "\n");
    }
 
    //-------------------------------
    // API応答情報を表示する
    //-------------------------------
    showResponse( $response );
}
 
 
 
//****************************************************************************
// Function     : getService
// Description  : Webサービス情報の取得
// Return       : MarketplaceWebServiceProducts_Client  サービス情報
//****************************************************************************
function getService() {
 
    //---------------------------------
    // クラスのオートローディングを行う
    //---------------------------------
    function __autoload($className){
        $filePath = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
        $includePaths = explode(PATH_SEPARATOR, get_include_path());
        foreach($includePaths as $includePath){
            if(file_exists($includePath . DIRECTORY_SEPARATOR . $filePath)){
                require_once $filePath;
                return;
            }
        }
    }
 
    // Web APIのエンドポイント(japan)
    $serviceUrl = "https://mws.amazonservices.jp/Products/2011-10-01";
 
    // proxy/retryの設定
    $config = array (
       'ServiceURL'    => $serviceUrl,
       'ProxyHost'     => null,
       'ProxyPort'     => -1,
       'MaxErrorRetry' => 3,
    );
 
    // Webサービスオブジェクトを生成
    $service = new MarketplaceWebServiceProducts_Client(
                AWS_ACCESS_KEY_ID,
                AWS_SECRET_ACCESS_KEY,
                'nanoappli.com_SampleApp',
                '1.0.0.0',
                $config);
 
    return $service;
}
 
 
 
//****************************************************************************
// Function     : showResponse
// Description  : Webサービス実行結果の表示
// Params       : $response WebAPI実行結果
//****************************************************************************
function showResponse( $response ) {
    $getLowestOfferListingsForASINResultList = $response->getGetLowestOfferListingsForASINResult();
 
    //--------------------------------------
    // 全てのASIN情報を表示するまで繰り返し
    //--------------------------------------
    foreach ($getLowestOfferListingsForASINResultList as $getLowestOfferListingsForASINResult) {
        echo ("=============================================================================\n");
 
        // 検索結果
        if ($getLowestOfferListingsForASINResult->isSetStatus()) {
            echo( "Status :" . $getLowestOfferListingsForASINResult->getStatus() . "\n");
        }
 
 
        //----------------
        // 商品の情報
        //----------------
        if ($getLowestOfferListingsForASINResult->isSetASIN()) {
            echo( "ASIN   :" . $getLowestOfferListingsForASINResult->getASIN() . "\n");
        }
        if ($getLowestOfferListingsForASINResult->isSetProduct()) { 
            $product = $getLowestOfferListingsForASINResult->getProduct();          
            if ($product->isSetSalesRankings()) { 
                $salesRankings = $product->getSalesRankings();
                $salesRankList = $salesRankings->getSalesRank();
                foreach ($salesRankList as $salesRank) {
                    if ($salesRank->isSetProductCategoryId()) {
                        echo("カテゴリID :" . $salesRank->getProductCategoryId() . "\n");
                    }
                    if ($salesRank->isSetRank()) {
                        echo("ランク :" . $salesRank->getRank() . "\n");
                    }
                }
            } 
 
            //-------------------
            // 出品情報
            //-------------------
            if ($product->isSetLowestOfferListings()) { 
                $lowestOfferListings = $product->getLowestOfferListings();
                $lowestOfferListingList = $lowestOfferListings->getLowestOfferListing();
 
                //-----------------------------------------
                // 取得した全出品情報を表示するまで繰り返し
                //-----------------------------------------
                foreach ($lowestOfferListingList as $lowestOfferListing) {
                    echo( "------------------------------------------------\n" );
 
                    //------------------
                    // 商品の状態
                    //------------------
                    if ($lowestOfferListing->isSetQualifiers()) { 
                        $qualifiers = $lowestOfferListing->getQualifiers();
                        if ($qualifiers->isSetItemCondition()) {
                            $condName    = getConditionName( $qualifiers->getItemCondition() );
                            $subCondName = "";
                            if ($qualifiers->isSetItemSubcondition()) {
                                $subCondName = "(" . getItemSubconditionName( $qualifiers->getItemSubcondition() ) . ")";
                            }
                            echo("コンディション   :" . $condName . $subCondName . "\n" );
                        }
 
 
                        if ($qualifiers->isSetFulfillmentChannel()) {
                            $name = getFulfillmentChannelName( $qualifiers->getFulfillmentChannel() );
                            echo("出荷元           :" . $name . "\n");
                        }
                        if ($qualifiers->isSetShipsDomestically()) {
                            echo("国内より発送     :" . $qualifiers->getShipsDomestically() . "\n");
                        }
                        if ($qualifiers->isSetShippingTime()) { 
                            $shippingTime = $qualifiers->getShippingTime();
                            if ($shippingTime->isSetMax()) {
                                echo("発送日数(最大)   :" . $shippingTime->getMax() . "\n");
                            }
                        } 
 
                        if ($lowestOfferListing->isSetSellerFeedbackCount()) {
                            echo("フィードバック数 :" . $lowestOfferListing->getSellerFeedbackCount() );
 
                            if ($qualifiers->isSetSellerPositiveFeedbackRating()) {
                                echo(" (高評価:" . $qualifiers->getSellerPositiveFeedbackRating() . ")");
                            }
                            echo ( "\n" );
                        }
                    }
                    if ($lowestOfferListing->isSetNumberOfOfferListingsConsidered()) {
                        echo("出品数           :" . $lowestOfferListing->getNumberOfOfferListingsConsidered() . "\n");
                    }
 
                    //------------------
                    // 価格情報
                    //------------------
                    if ($lowestOfferListing->isSetPrice()) { 
                        $price1 = $lowestOfferListing->getPrice();
                        if ($price1->isSetLandedPrice()) { 
                            echo("総額             :" . getPriceName( $price1->getLandedPrice() ) );
 
                        } 
                        if ($price1->isSetShipping()) { 
                            echo(" (送料:" . getPriceName( $price1->getShipping() ) . ")" );
                        } 
                        echo ( "\n" );
                    } 
                }
            } 
        } 
 
        if ($getLowestOfferListingsForASINResult->isSetError()) { 
            echo("エラーが発生しました\n");
            $error = $getLowestOfferListingsForASINResult->getError();
            if ($error->isSetType()) {
                echo("Type:" . $error->getType() . "\n");
            }
            if ($error->isSetCode()) {
                echo("Code:" . $error->getCode() . "\n");
            }
            if ($error->isSetMessage()) {
                echo("Message:" . $error->getMessage() . "\n");
            }
        } 
    }
}
 
 
//****************************************************************************
// Function     : getConditionName
// Description  : コンディション名(日本語)を取得する
//****************************************************************************
function getConditionName( $inStr ) {
    switch( $inStr ) {
        case "New":
            return "新品";
            break;
        case "Used":
            return "中古品";
            break;
        case "Collectible":
            return "コレクター品";
            break;
        case "Refurbished":
            return "再生品";
            break;
        default:
            return $inStr;
            break;
    }
}
 
 
//****************************************************************************
// Function     : getItemSubconditionName
// Description  : サブコンディション名(日本語)を取得する
//****************************************************************************
function getItemSubconditionName( $inStr ) {
    switch( $inStr ) {
        case "New":
            return "新品";
            break;
        case "Mint":
            return "ほぼ新品";
            break;
        case "Very Good":
        case "VeryGood":
            return "非常に良い";
            break;
        case "Good":
            return "良い";
            break;
        default:
            return $inStr;
            break;
    }
}
 
 
//****************************************************************************
// Function     : getFulfillmentChannelName
// Description  : 出荷元(日本語)を取得する
//****************************************************************************
function getFulfillmentChannelName( $inStr ) {
    switch( $inStr ) {
        case "Amazon":
            return "FBA";
            break;
        case "Merchant":
            return "出品者";
            break;
        default:
            return $inStr;
            break;
    }
}
 
 
//****************************************************************************
// Function     : getPriceName
// Description  : 価格(通貨単位付き)を取得する
//****************************************************************************
function getPriceName( $inData ) {
    $outStr = "";
 
    // 通貨単位のセット
    if ( $inData->isSetCurrencyCode() ) {
        switch ( $inData->getCurrencyCode() ) {
            case "JPY":
                $outStr .= "\\";
                break;
            case "USD":
                $outStr .= "$";
                break;
            default:
                $outStr .= "(" . $inData->getCurrencyCode() . ")";
                break;
        }
    }
 
    // 金額のセット
    if ($inData->isSetAmount()) {
        $outStr .= sprintf( "%.0lf", $inData->getAmount() );
    }
 
    return $outStr;
}

[AmazonMWS]Required parameter MarketplaceId not found エラー時の対応方法

エラーメッセージ例

Notice: Undefined offset: 1 in src\MarketplaceWebServiceProducts\Client.php on line 710
Caught Exception: Required parameter MarketplaceId not found
Response Status Code: 400
Error Code: MissingParameter
Error Type: Unknown
Request ID: 417e2eee-ce39-44d8-b1b6-b634863ef53e
XML: <?xml version="1.0"?>
<ErrorResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
    <Error>
        <Type>Sender</Type>
        <Code>MissingParameter</Code>
        <Message>
            Required parameter MarketplaceId not found
        </Message>
        <Detail/>
    </Error>
    <RequestID>xxxx</RequestID>
</ErrorResponse>
ResponseHeaderMetadata: RequestId: xxx, ResponseContext: xxx




原因は、リクエストパラメータにMarketplaceIdがセットされていない事です。



MarketplaceIdのセットは、xxxSample.phpの先頭付近にある定義を以下のように変更します。
修正前

 $request = new MarketplaceWebServiceProducts_Model_GetLowestOfferListingsForASINRequest();
 $request->setSellerId(MERCHANT_ID);
 // object or array of parameters
 invokeGetLowestOfferListingsForASIN($service, $request);



修正後

 $request = new MarketplaceWebServiceProducts_Model_GetLowestOfferListingsForASINRequest();
 $request->setSellerId(MERCHANT_ID);
 
 // object or array of parameters
 $asinList = new MarketplaceWebServiceProducts_Model_ASINListType();
 $asinList->setASIN( '43892404' );
 $request->setASINList( $asinList );
 
 $request->setMarketplaceId( MARKETPLACE_ID );                  //  追加
 
 invokeGetLowestOfferListingsForASIN($service, $request);



パラメータエラーについては、以下の記事も参考にしてください。
「Required parameter ASINList not found」エラーが発生する。

Raspberry Piの資料リンク集

Socのデータシート(SoCというのは、CPU+周辺回路を1チップにしたもの)
CPUはARM1176JZF-Sを使用していて、UART,SPI,GPIO,PCMオーディオ,PWM,SPI,Timer,USB,I2C辺りが使用可能。
BCM2835 ARM peripherals

詳細なドキュメントは、入手不可(守秘義務契約が必要)
FAQs | Raspberry Pi

But I demand the documentation for the chip. Give it to me!

To get the full SoC documentation you would need to sign an NDA with Broadcom, who make the chip and sell it to us. But you would also need to provide a business model and estimate of how many chips you are going to sell.


ハードウェアの回路図
Raspberry-Pi-Schematics-R1.0.pdf

Raspberry PiでFreeBSDを動作させるためのU-Boot
FreeBSD on Raspberry Pi: baby steps ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, step 2 ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, step 3 ≪ FreeBSD developer’s notebook
U-Boot on Raspberry Pi, step 4: DWC OTG, Control transactions
U-Boot on Raspberry Pi, step 5: More USB stuff ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, step 6: It lives! ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, step 7: cleanup ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, step 8: SDHC support ≪ FreeBSD developer’s notebook
U-Boot for Raspberry Pi, the last step ≪ FreeBSD developer’s notebook
FreeBSD/Pi setup HowTo ≪ FreeBSD developer’s notebook

ブートストラップについての説明
Raspberry Pi • View topic – Raspberry Pi boot process

Raspberry Piを使ったシンクライアント
start [BerryTerminal]

GPIOポートのピンアサインと仕様
3.3V駆動で5Vトレラントではない
RPi Low-level peripherals – eLinux.org

Raspberry PiでLチカ
Tutorial: How to use your Raspberry Pi like an Arduino | Limina.Log

Raspberry PiとArduinoがSPI通信
Raspberry Pi + Arduino + SPI | MitchTech

トラブルシューティング
R-Pi Troubleshooting – eLinux.org

amazon.ukから買うと£39.99にて販売中らしい(在庫有り)。
Raspberry Pi Model B: Amazon.co.uk: Computers & Accessories

[AmazonMWS]「Required parameter ASINList not found」エラーが発生する。

GetLowestOfferListngsForASINSample.php実行時のエラーメッセージ例
(見やすくするために改行を入れてます)

> php GetLowestOfferListngsForASINSample.php
 
PHP Notice:  Undefined offset: 1 in src\MarketplaceWebServiceProducts\Client.php on line 710
 
Notice: Undefined offset: 1 in src\MarketplaceWebServiceProducts\Client.php on line 710
Caught Exception: Required parameter ASINList not found
Response Status Code: 400
Error Code: MissingParameter
Error Type: Unknown
Request ID: xxxx
XML: <?xml version="1.0"?>
<ErrorResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
    <Error>
        <Type>Sender</Type>
        <Code>MissingParameter</Code>
        <Message>
            Required parameter ASINList not found
        </Message>
        <Detail/>
    </Error>
    <RequestID>xxx</RequestID>
</ErrorResponse>
ResponseHeaderMetadata: xxx





原因は、パラメータに検索対象となるASINを指定していない為です。


対処法は、GetLowestOfferListngsForASINSample.phpの先頭付近にある以下の記述に…

 $request = new MarketplaceWebServiceProducts_Model_GetLowestOfferListingsForASINRequest();
 $request->setSellerId(MERCHANT_ID);
 // object or array of parameters
 invokeGetLowestOfferListingsForASIN($service, $request);



setASINList()を追加します。

 $request = new MarketplaceWebServiceProducts_Model_GetLowestOfferListingsForASINRequest();
 $request->setSellerId(MERCHANT_ID);
 // object or array of parameters
 
 $asinList = new MarketplaceWebServiceProducts_Model_ASINListType();     // <======= 追加
 $asinList->setASIN( '43892404' );                                       // <======= 追加
 $request->setASINList( $asinList );                                     // <======= 追加
 
 invokeGetLowestOfferListingsForASIN($service, $request);



複数のASINを渡したい場合は以下のようにarrayで指定します。
APIドキュメントを見ると分かりますが、指定できるのは最大20個です。

$asinList->setASIN( array( '43892404', '475981339X' ) );





各リクエストに対して何のパラメータが指定できるかは、src\MarketplaceWebServiceProducts\ModelフォルダのxxxRequest.phpを参照すると分かります。
grepをかけると一目瞭然ですね。

src\MarketplaceWebServiceProducts\Model>grep "function.*set" GetLowestOfferListingsForASINRequest.php
    public function setSellerId($value)
    public function setMarketplaceId($value)
    public function setASINList($value)
    public function setItemCondition($value)
    public function setExcludeMe($value)





毎回調べるのは面倒なので、全ファイルgrepした結果を置いときます。

src\MarketplaceWebServiceProducts\Model>grep "function.*set" *Request.php
 
GetCompetitivePricingForASINRequest.php:   public function setSellerId($value)
GetCompetitivePricingForASINRequest.php:   public function setMarketplaceId($value)
GetCompetitivePricingForASINRequest.php:   public function setASINList($value)
 
GetCompetitivePricingForSKURequest.php:    public function setSellerId($value)
GetCompetitivePricingForSKURequest.php:    public function setMarketplaceId($value)
GetCompetitivePricingForSKURequest.php:    public function setSellerSKUList($value)
 
GetLowestOfferListingsForASINRequest.php:  public function setSellerId($value)
GetLowestOfferListingsForASINRequest.php:  public function setMarketplaceId($value)
GetLowestOfferListingsForASINRequest.php:  public function setASINList($value)
GetLowestOfferListingsForASINRequest.php:  public function setItemCondition($value)
GetLowestOfferListingsForASINRequest.php:  public function setExcludeMe($value)
 
GetLowestOfferListingsForSKURequest.php:   public function setSellerId($value)
GetLowestOfferListingsForSKURequest.php:   public function setMarketplaceId($value)
GetLowestOfferListingsForSKURequest.php:   public function setSellerSKUList($value)
GetLowestOfferListingsForSKURequest.php:   public function setItemCondition($value)
GetLowestOfferListingsForSKURequest.php:   public function setExcludeMe($value)
 
GetMatchingProductForIdRequest.php:        public function setSellerId($value)
GetMatchingProductForIdRequest.php:        public function setMarketplaceId($value)
GetMatchingProductForIdRequest.php:        public function setIdType($value)
GetMatchingProductForIdRequest.php:        public function setIdList($value)
 
GetMatchingProductRequest.php:             public function setSellerId($value)
GetMatchingProductRequest.php:             public function setMarketplaceId($value)
GetMatchingProductRequest.php:             public function setASINList($value)
 
GetMyPriceForASINRequest.php:              public function setSellerId($value)
GetMyPriceForASINRequest.php:              public function setMarketplaceId($value)
GetMyPriceForASINRequest.php:              public function setASINList($value)
 
GetMyPriceForSKURequest.php:               public function setSellerId($value)
GetMyPriceForSKURequest.php:               public function setMarketplaceId($value)
GetMyPriceForSKURequest.php:               public function setSellerSKUList($value)
 
GetProductCategoriesForASINRequest.php:    public function setSellerId($value)
GetProductCategoriesForASINRequest.php:    public function setMarketplaceId($value)
GetProductCategoriesForASINRequest.php:    public function setASIN($value)
GetProductCategoriesForSKURequest.php:     public function setSellerId($value)
GetProductCategoriesForSKURequest.php:     public function setMarketplaceId($value)
GetProductCategoriesForSKURequest.php:     public function setSellerSKU($value)
 
GetServiceStatusRequest.php:               public function setSellerId($value)
 
ListMatchingProductsRequest.php:           public function setSellerId($value)
ListMatchingProductsRequest.php:           public function setMarketplaceId($value)
ListMatchingProductsRequest.php:           public function setQuery($value)
ListMatchingProductsRequest.php:           public function setQueryContextId($value)


[AmazonMWS] Client.php on line 710で”Undefined offset: 1″エラー時の対処

エラーメッセージ

PHP Notice:  Undefined offset: 1 in ...\src\MarketplaceWebServiceProducts\Client.php on line 710




このエラーが出る時は、おそらくユーザのID設定が行われていません。



ID設定は以下のファイルで行います。

src\MarketplaceWebServiceProducts\Samples\.config.inc.php




ファイルの先頭に6つdefine文があるので、この6つを埋めていきます。

   /************************************************************************
    * REQUIRED
    * 
    * Access Key ID and Secret Acess Key ID, obtained from:
    * http://aws.amazon.com
    ***********************************************************************/
    define('AWS_ACCESS_KEY_ID', '<Your Access Key ID>');
    define('AWS_SECRET_ACCESS_KEY', '<Your Secret Key>');  
 
   /************************************************************************
    * REQUIRED
    * 
    * All MWS requests must contain a User-Agent header. The application
    * name and version defined below are used in creating this value.
    ***********************************************************************/
    define('APPLICATION_NAME', '<Your Application Name>');
    define('APPLICATION_VERSION', '<Your Application Version or Build Number>');
 
   /************************************************************************
    * REQUIRED
    * 
    * All MWS requests must contain the seller's merchant ID and
    * marketplace ID.
    ***********************************************************************/
    define ('MERCHANT_ID', '<Your Merchant Id>');
    define ('MARKETPLACE_ID', '<Your Marketplace Id>');




まず、アプリケーション設定を行います。
これは、適当でOKです。

変更前

    define('APPLICATION_NAME', '<Your Application Name>');
    define('APPLICATION_VERSION', '<Your Application Version or Build Number>');



修正後

    define('APPLICATION_NAME',    'TestApp');
    define('APPLICATION_VERSION', '1.0.0.0');




次に,ユーザIDの設定を行います。

    define('AWS_ACCESS_KEY_ID', '<Your Access Key ID>');
    define('AWS_SECRET_ACCESS_KEY', '<Your Secret Key>');  
    define('MERCHANT_ID', '<Your Merchant Id>');
    define('MARKETPLACE_ID', '<Your Marketplace Id>');



このIDはアマゾンマーケットプレースに大口出品者として登録されていないと取得できません。

IDの取得方法は、以下の記事を参考にしてください。
(最後の画像に出品者IDとマーケットプレイスIDしか映ってませんが、その下に2つIDが出てます)
Amazonマーケットプレース用アプリの使用時に必要な準備作業(出品者向け)

こんな感じのページが出るので、4つのIDを控えます。



取得した4つのIDを、先ほどのdefineに設定します。

    define('AWS_ACCESS_KEY_ID',     '<Your Access Key ID>');        // AWSアクセスキーI
    define('AWS_SECRET_ACCESS_KEY', '<Your Secret Key>');           // 秘密キー
    define('MERCHANT_ID',           '<Your Merchant Id>');          // 出品者ID
    define('MARKETPLACE_ID',        '<Your Marketplace Id>');       // マーケットプレイスID


[AmazonMWS] PHP Notice: Undefined variable: serviceUrl in… エラーが出る時の対処

エラーメッセージ

PHP Notice:  Undefined variable: serviceUrl in ...\amazon-mws-v20111001-php-2012-07-01._V144471503_
\src\MarketplaceWebServiceProducts\Samples\GetLowestOfferListingsForASINSample.php on line 43




このエラーは、実行したサンプルプログラムの$serviceUrl変数を定義していないために発生します。


対処法は、サンプルプログラムの先頭付近に以下の定義があるので…

/************************************************************************
 * Instantiate Implementation of MarketplaceWebServiceProducts
 * 
 * AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY constants 
 * are defined in the .config.inc.php located in the same 
 * directory as this sample
 ***********************************************************************/
// United States:
//$serviceUrl = "https://mws.amazonservices.com/Products/2011-10-01";
// Europe
//$serviceUrl = "https://mws-eu.amazonservices.com/Products/2011-10-01";
// Japan
//$serviceUrl = "https://mws.amazonservices.jp/Products/2011-10-01";
// China
//$serviceUrl = "https://mws.amazonservices.com.cn/Products/2011-10-01";
// Canada
//$serviceUrl = "https://mws.amazonservices.ca/Products/2011-10-01";



日本で使用する場合は、以下のコメントを外します。

変更前

//$serviceUrl = "https://mws.amazonservices.jp/Products/2011-10-01";



修正後

$serviceUrl = "https://mws.amazonservices.jp/Products/2011-10-01";


[AmazonMWS] Caught Exception: Unable to establish connection… エラーが出る時の対処

エラーメッセージ

Caught Exception: Unable to establish connection to host mws.amazonservices.jp 
Unable to find the socket transport "ssl" - did you forget to enable it when you configured PHP?




このエラーは、Client.phpで定義されているMarketplaceWebServiceProducts_Clientクラスの_httpPost()メソッドで出力されています。

具体的には、_httpPost()メソッドのfsockopenで例外が発生しています。

if ($socket = @fsockopen($scheme . $url['host'], $port, $errno, $errstr, 10)) {





理由は、phpの環境がSSLに対応できていないからです。
対処法はOSによって異なります。

Windowsの場合は、phpインストールフォルダに有るphp.iniを編集する必要があります。

変更前

;extension=php_openssl.dll



修正後

extension=php_openssl.dll




Linux等、Unix系の場合は、インストール時のconfigureで”–with-openssl”オプションをつけます。

./configure --with-openssl ...


[Crystal Reports]特定の条件の時に,ラベルを非表示にする方法

Crystal Reportsで帳票出力を行う際、印字データの前後に接頭語や接尾語として固定文字をつける場合があります(例えば名称の後に”様”をつける等)。

固定文字を常に印字する場合は、ラベルとしてテキストオブジェクトを貼り付ければよいのですが、データがない場合は固定文字を出したく無い場合も有ります。

対処療法として、プログラムから”印字データ+固定文字”を渡してあげるという逃げ道も有りますがプログラム的に美しくないので出来れば避けたいです。


このような場合、条件付印字を行う事で対応できます。

例えば以下の帳票で、PostalCodeに値がセットされた時に限り”〒”マークを表示させてみます。



表示条件を指定するコントロールを右クリックして、オブジェクトの書式設定を選択します。


ダイアログの”非表示”の右にあるボタンをクリックします。


式ワークショップウィンドウが表示されます。



右下の入力欄に、以下の条件式を入力し、保存して閉じるボタンをクリックします。

if IsNull( {RepAddressLabel.PostalCode} ) or 
   {RepAddressLabel.PostalCode} = ""      then
    true
else 
    false




今回のサンプルではデータセット名がRepAddressLabelだったので、{RepAddressLabel.PostalCode}となっています。比較対象の項目は、各自読み替えてください。
ここで指定する式は「非表示条件」なので、値がtrueの場合に表示されません。

プログラムから渡された値にNULLがこない事が確実な場合は、下記の条件式でもOKです。

if {RepAddressLabel.PostalCode} = ""  then
    true
else 
    false




先ほどクリックしたボタンの色が変わっているのを確認し、OKボタンをクリックします。
“非表示”の左にあるチェックボックスは、外したままにしてください。


これで、郵便番号(PostalCode)に値がセットされていた時に限り、〒マークが出るようになりました。



余談ですが、if文ではなくIIF()関数を使う場合は、Crystal Reportsの不具合でIIF()第一引数にIsNull()を使用時正しく認識してくれないバグががあるようです(このバグが発生するのは、Crystal Reportsのver8か10の時で、しかも条件式にの内容に依るらしいです…)。
ですので、この条件式は常にif文で書いた方が確実です。

[H8マイコン]アセンブラでシリアルポートにHello World

H8マイコンで、シリアル(SCI)でHello Worldを出力するプログラムです。
HEWに付属のアセンブラでコンパイル可能です。

H8でシリアル通信を行うためには決められた手順(プロトコル)でレジスタを操作する必要があります。
プロトコルの詳細については,以下の記事を参考にしてください。
[読書メモ]12ステップで作る組込みOS自作入門: 2ndステップ シリアル通信



;------------------------------------------------------------------------
;   FILE        : HelloWorld.src
;   PROGRAM     : シリアルポートにHello Worldする
;               : プロトコルは"9600bps, 8bit, Parity:None, StopBit:1"
;------------------------------------------------------------------------
        .cpu        300HN
        .export     _main
        .section    P,CODE,ALIGN=2
 
; for H83694f
PMR1    .equ        H'FFE0
 
SMR     .equ        H'FFA8
BRR     .equ        H'FFA9
SCR3    .equ        H'FFAA
TDR     .equ        H'FFAB
SSR     .equ        H'FFAC
RDR     .equ        H'FFAD
 
;------------------------------------------------------
;   メイン処理
;------------------------------------------------------
_main:
        ; シリアルコントローラの初期化
        JSR     @scr_init
 
        ; メッセージの送信
        JSR     @send_message
 
loop:
        BRA     loop
        rts
 
 
 
;------------------------------------------------------
; メッセージをシリアルに送信する
;------------------------------------------------------
send_message:
        ; 出力メッセージの先頭アドレスをセット
        MOV.L   #Msg, ER4
 
send_message_L1:
 
        ;送信可能になるまで待つ(このサブルーチンは結果をR5Lにセットしてくれる...)
        JSR     @is_serial_send_enable  
        CMP     #0, R5L
        BNE     main_L1
 
 
        ; 1byte送信
        MOV.B   @ER4,   R0L
        MOV.B   R0L,   @TDR ; "印字すべき文字=ER4の差し先" とする
 
        BCLR.B  #H'7,   @SSR    ;TDREのフラグを落として(0:not empty)、送信要求する
 
send_message_L2:
        JSR     @is_serial_send_enable  
        CMP     #0, R5L
        BNE     main_L2
 
        ; 表示対象の文字を1文字進める
        INC.L   #1, ER4
        ; ヌル文字まで来てなければ繰り返し
        MOV.B   @ER4, R0L
        CMP.B   #H'00, R0L
        BNE     main_L1
 
        RTS
 
 
;------------------------------------------------------
; シリアルの初期化
;------------------------------------------------------
scr_init:
        BSET.B  #1,     @PMR1
        ;シリアルモードを設定
        MOV.B   #H'00,  R0L
        MOV.B   R0L,    @SCR3
 
        MOV.B   #H'00,  R0L
        MOV.B   R0L,    @SMR    ; All0で 8bit, N, 1になる
 
        MOV.B   #D'64,  R0L
        MOV.B   R0L,    @BRR    ; 通信速度。20MHzの場合は64 (0x40)
 
        ; 通信速度をセット後は、一定期間スリープが必要
        ; 余裕を見て0.1sec待っている
        MOV.L   #D'250000, ER5
L1:     DEC.L   #1, ER5
        NOP
        BNE     L1
 
        BSET.B  #4,     @SCR3   ; RxEnable
        BSET.B  #5,     @SCR3   ; TxEnable
 
        MOV.B   #H'00,  R0L
        MOV.B   R0L,    @SSR
 
        RTS
 
 
;------------------------------------------------------
; シリアルに書き込み可能かチェック
;------------------------------------------------------
is_serial_send_enable:
        MOV.B   @SSR,   R0L
        AND.B   #H'80,  R0L     ; 0x80: SSR.TDRE
        CMP     #H'80,  R0L
        BNE     is_serial_send_enable_L1    ; bitが立ってなければジャンプ
 
        ; 1->EmptyなのでOK
        MOV.B   #0,     R5L
        BRA     is_serial_send_enable_L2
 
is_serial_send_enable_L1:
        ; 0->NG
        MOV.B   #1,     R5L
is_serial_send_enable_L2:
        RTS
 
;出力するメッセージ
Msg:    .sdataz     "Hello world"
 
        .end




4877832394
12ステップで作る組込みOS自作入門

[読書メモ]12ステップで作る組込みOS自作入門: 2ndステップ シリアル通信

書籍”12ステップで作る組込みOS自作入門 “の読書メモです。


2ndステップのお話は、1stステップで作ったプログラムのうちserial.cの説明がメイン。
H8マイコンのシリアル通信仕様は、ルネサスのドキュメントが確かな資料となる。

シリアルについては、以下の「H8/3069R ハードウェアマニュアル」に記載されているので、これを見ながら確認すると分かりやすい(13-1章のSCIに書かれている)。
http://documentation.renesas.com/doc/products/mpumcu/rjj09b0165_h83069rf.pdf
ここで使うシリアル通信はマニュアル上”SCI”と呼ばれている。


シリアル通信

H8はメモリマップドI/Oなので、シリアルの制御は特定のメモリ番地を操作する事で行うことが出来る。
具体的に何番地に割り当たっているかは、以下のようになっている。H8/3069Rはシリアルが3チャンネル有るので、レジスタも3つある。

ch addr     名称                          略称 R/W     初期値
-- -------- ----------------------------- ---- ------- ------
0  H'FFFB0  シリアルモードレジスタ        SMR  R/W     H'00
   H'FFFB1  ビットレートレジスタ          BRR  R/W     H'FF
   H'FFFB2  シリアルコントロールレジスタ  SCR  R/W     H'00
   H'FFFB3  トランスミットデータレジスタ  TDR  R/W     H'FF
   H'FFFB4  シリアルステータスレジスタ    SSR  R/(W)*2 H'84
   H'FFFB5  レシーブデータレジスタ        RDR  R       H'00
   H'FFFB6  スマートカードモードレジスタ  SCMR R/W     H'F2
 
1  H'FFFB8  シリアルモードレジスタ        SMR  R/W     H'00
   H'FFFB9  ビットレートレジスタ          BRR  R/W     H'FF
   H'FFFBA  シリアルコントロールレジスタ  SCR  R/W     H'00
   H'FFFBB  トランスミットデータレジスタ  TDR  R/W     H'FF
   H'FFFBC  シリアルステータスレジスタ    SSR  R/(W)*2 H'84
   H'FFFBD  レシーブデータレジスタ        RDR  R       H'00
   H'FFFBE  スマートカードモードレジスタ  SCMR R/W     H'F2
 
2  H'FFFC0  シリアルモードレジスタ        SMR  R/W     H'00
   H'FFFC1  ビットレートレジスタ          BRR  R/W     H'FF
   H'FFFC2  シリアルコントロールレジスタ  SCR  R/W     H'00
   H'FFFC3  トランスミットデータレジスタ  TDR  R/W     H'FF
   H'FFFC4  シリアルステータスレジスタ    SSR  R/(W)*2 H'84
   H'FFFC5  レシーブデータレジスタ        RDR  R       H'00
   H'FFFC6  スマートカードモードレジスタ  SCMR R/W     H'F2


この番地は、同じH8マイコンでも型番によって異なる。またH8/3069Rは3つのSCIを持っているけど1つしかないチップもあったりする。

I/Oにマップされたメモリ空間はCPUからすれば単なるメモリなのだけど、一般的にレジスタという呼び方をする。ここで言う”レジスタ”は、H8が持っている汎用レジスタ(ER0~ER7)とは意味が違うので注意が必要

SCIの通信モードには、調歩同期式モードとクロック同期式モードがあるが、ここではクロック同期式で通信する。

また、CPU的にはデータ送受信が行えるかのタイミングを、外部割り込みの形で取得することも取得可能だけど割り込み方式は使用せず、データ書き込みが可能かを一定周期で監視する方式を利用する。


シリアルデバイスの初期化や通信には、これらのメモリを操作していくころになるけど、どうやって初期化すればよいかの手順(プロトコル)は仕様書に記載されている。初期化手順を書くと、以下のようになる。

SCRのTE,REビットを0クリアする
 
SCRのCHK1,CHK0ビットを設定する(0,0で内部クロック使用)
 
SMRに送受信フォーマットを設定する
 
BRRに通信速度を設定する
 
一定時間スリープする
    (もしBRRで9600bpsを指定した場合は、1/9600秒以上ウェイト)
 
SCRのTE,REビットを1にセット
 
通信状態を割り込みで通知して欲しい場合は,SCRのRIE,TIE,TEIE,MPIEビットをセット



また、クロック同期式でのデータ送信は、以下の手順で行う。

SSRのTDREビットが1である事を確認する
 
TDRに送信するデータを書き込む
 
SSRのTDREビットを0にセットする


TDREを0にセット後、H8マイコンがそのデータを処理したら、マイコン側がTDREを1にセットしてくれる。最初に1である事を確認しているが、この確認を忘れてしまうとデータ欠落の可能性が発生する。


SCR,SSR等のI/O制御用レジスタは、メモリ上の各ビットに以下のような意味を持たされている。

SCR
    bit7    TIE     
    bit6    RIE
    bit5    TE
    bit4    RE
    bit3    MPIE
    bit2    TEIE
    bit1    CKE1
    bit0    CKE0
SSR 
    bit7    TDRE
    bit6    RDRF
    bit5    ORER
    bit4    FER/ERS
    bit3    PER
    bit2    TEND
    bit1    MPB
    bit0    MPBT
 
BRR
    通信速度(bps)を表す値(クロック同期モードの場合)
    以下の式で求まるNをBRRレジスタにセットする
        N = ( 周波数 / 8 * 2^(2n -1) * B ) * 1000000 - 1
            B:通信したいビットレート(bps)
            n:ボーレートジェネレータ入力クロック(詳細はHWマニュアル参照)
    ※20MHzで9600bpsだと、64をセットする。




C言語で、I/Oに紐づいたメモリを操作する時は、以下のようにポインタ変数に番地を直接指定する。

char *smr = (char *)0xffffb0;
char *brr = (char *)0xffffb1;
char *scr = (char *)0xffffb2;




さらに、以下のように変数にvolatile指定が必要になる。

volatile char *smr = (volatile char *)0xffffb0;
volatile char *brr = (volatile char *)0xffffb1;
volatile char *scr = (volatile char *)0xffffb2;
 
scr = 0x00;     /* 初期化開始                         */
smr = 0;        /* 8bit ノンパリティ, ストップビット1 */
brr = 64;       /* 20MHz動作時、9600bpsを意味する     */
scr = 0x30;     /* RxEnable, TxEnable                 */



volatileというのは、コンパイラに対して最適化をしないよう依頼する指示となる。
上記のコードはSCIの初期化処理になるが、普通のC言語のプログラムとしてみると変数scrに0x00をセットした後、0x30をセットしているので、最初の0x00は無駄に見える。

だけど、コンパイラの最適化処理が走ると、その無駄を検出して実行ファイルから”scr = 0x00;”を削除してしまう場合がある。

コンパイラから見ると一見無駄に見えるかもしれないけど、シリアル制御のプロトコル上は意味がある処理なので、最適化を抑制するためにvolatileが必須となる。この辺の考えかたは普通のアプリとは異なり、組み込み向け特有の発想になる。



…上記シリアル通信を行うC言語でのプログラムは1stステップで提示されてましたが、動作を理解するためにアセンブラで書いてみました。
コードはH8/3069R向けではなく、H8-3694F向けに書いたのでI/Oのマッピングが異なっています。
 → [H8マイコン]アセンブラでシリアルポートにHello World


数値出力

2ndステップでは、以下の標準ライブラリ関数を自作してlib.cに追加している。

memset, memcpy, memcmp, strlen, strcpy, strcmp, strncmp



いづれもメモリ操作系の関数なので、C言語で簡単に書くことが出来る。(アセンブラでも書ける)

これらの関数は、ほかにサブ関数を呼ぶ必要が無いもので、こういう関数コールの末尾になるものを”リーフ関数”と呼ぶ。


あと、データの出力にprintf()が欲しいところだけど、printfは実装が面倒なので、簡易版のputxval()関数を定義している。これは指定された値をputs()を使って16進出力してくれる。columnパラメータでは表示幅の指定が行える。

int putxval( unsigned long value, int column );




スタートアップ

C言語の入門書だとmain()関数から処理が始まる事になっているけど、実際はその前にスタートアップルーチンから始まる。

start() -> main()



スタートアップルーチンはアセンブラでかかれることも多くcrt.sという名前を付けることが多い。
crtはC RunTime の略。

H8の場合スタートアップルーチンは、割り込みベクタの0番目に関数を登録する事で実行される。

割り込みベクタの0番目はリセットベクタというもので、リセットが掛かった時に行われる割り込み処理になる。

4877832394
12ステップで作る組込みOS自作入門