/**
 * \file i2c_subsystem.h
 *
 * \date 2012/07/16
 * \author: takemasa
 * \brief twiペリフェラルをマスターモードで使用する
 *
 */
#include <kernel.h>

#ifndef I2C_SUBSYSTEM_H_
#define I2C_SUBSYSTEM_H_

/**
 * \defgroup I2C_SUBSYSTEM  I2Cを使用するためのサブシステム
 * \details
 * i2c_subsystemは、LPC1768の内蔵I2Cペリフェラルを使用するための関数群である。この関数群はTOPPERS/ASP用に開発されており、CMSISの下位
 * ライブラリを使用して、割り込みを使ったポーリングなしの制御を実現している。タスクから呼び出された関数は割り込みハンドラとセマフォを使って
 * 通信しながら指定されたI2Cスレーブ・デバイスの制御を行う。また、関数群は排他制御されており、一つのi2Cペリフェラルを複数のタスクが同時に使用
 * しないよう保護されている。
 *
 * アプリケーションが使用するのは i2c_master_write(), i2c_master_read(), i2c_master_write_read() の三つの関数だけである。
 * この他にI2Cの初期化関数と割り込みISRがあるが、これらは TOPPERS/ASP のコンフィギュレーション・ファイルに記述されており、アプリケーション・
 * プログラマが直接呼び出してはならない。
 *
 * I2Cx ペリフェラルを使用する場合には、アプリケーションのコンフィギュレーションファイルから、i2cx_m.cfgファイルを読み込んでおく。
 * 例えば、I2C1を使いたいのであれば、i2c1_m.cfg ファイルを読み込む。i2c0_m.cfg から i2c2_m.cfg までのファイルがあり、
 * どのファイルをどの組み合わせでどの順番で読み込んでもかまわない。
 *
 * I2Cxペリフェラルの初期化は、cfgファイルによって記述されたイニシャライザが行う。また、割り込みISRもcfgファイルによって登録
 * される。このほか、ペリフェラル電源のオン、クロックの設定もイニシャライザ内部で完結している。
 *
 * I2Cxペリフェラルへのピンの割り当ては、アプリケーションで行う。これに関しては例題、例えば 801_i2c_pcf8570プロジェクトを参照のこと。
 *
 * なお、I2Cサブシステムは、イニシャライザ内部でCMSISの   SystemCoreClockUpdate() 関数を使用してCPUのクロック周波数を
 * 測定している。この関数が常に正しく動作するのはCPUが内部RCオシレータを使用する場合と、RTCの32768Hzクロックを使用する場合のみである。
 * 外部クリスタルを使ったメインオシレータを使用する場合は、クリスタルの共振周波数とCMSIS内部のクロック設定値をあわせてCMSISを再ビルド
 * しなければならない。
 */
/*@{*/

#define I2C_ERR_WRONGPARAM      0x4000
#define I2C_ERR_TOOLONGBUFFER   0x2000
#define I2C_ERR_TIMEOUT     0x1000

/**
 * \brief i2cマスターモードの割り込みサービスルーチン
 * \param exinf i2cペリフェラルの番号。i2c0なら、0
 * \details
 * この間数は、i2cをマスターモードとして使う際の割り込みサービスルーチン本体である。 i2c_master_read()等の関数と強調しながら
 * 動作する。データ転送が終わると、あらかじめ設定されたコールバックを呼び出してタスクに通知する。
 *
 * exinfには、コンフィギュレーションファイルのATT_ISRから値を与える
 */
void i2c0_master_handler(void);


/**
 * \brief i2cマスターモード動作用の初期化を行う
 * \param exinf ペリフェラル番号を渡す. TWI0なら0。
 * \details
 * この関数は i2c0_master_handler() が i2c_master_read() 等の関数と同期するためのセマフォの設定を行う。
 * 呼び出しは明示的に行わず、コンフィギュレーションファイルからATT_INIを使ってシステムに登録する。
 *
 */
void i2c_master_initialize(VP_INT exinf);


/**
 * \brief I2C マスター書き込み関数
 * \param peripheral マイコンのI2Cペリフェラルの番号。0,1,2のいずれか
 * \param slave 7bitで表すI2Cペリフェラルの番号。bit0:6のみ使い、bit7以上は0にすること。
 * \param write_data ペリフェラルに書き込むデータ・バイト列
 * \param write_count ペリフェラルに書き込むデータの長さ。単位はバイト。
 * \return エラーがなければ0
 * \details
 * 引数 peripheral を使って、アドレス slave のI2Cデバイスに対する書き込みを行う関数。

 * この関数はブロッキング関数である。つまり、読み込みを開始すると、その終了まで待って
 * 帰ってくる。
 *
 * また、複数のタスクが同時にこの関数を呼んだ場合には、うち一つだけが関数を実行し、他のタスクは
 * 待ち状態になる。
 *
 * 返り値はプロトコルの処理ステータスである I2C_SETUP_STATUS_XXX と、I2C ステータス
 * レジスタの最後の値である I2C_I2STAT_M_XXXX がビット論理和された状態になっている。
 * それぞれの詳細は lpc17xx_i2c.h を参照。
 * 正常終了ならオール0である。
 *
 */
int i2c_master_write( int peripheral, int slave, unsigned char write_data[], int write_count );

/**
 * \brief I2C マスター読み込み関数
 * \param peripheral マイコンのI2Cペリフェラルの番号。0,1,2のいずれか
 * \param slave 7bitで表すI2Cペリフェラルの番号。bit0:6のみ使い、bit7以上は0にすること。
 * \param read_data ペリフェラルから読み込むデータ・バッファ
 * \param read_count ペリフェラルから読み込むデータの長さ。単位はバイト。
 * \return エラーがなければ0。処理がタイムアウトならば処理ステータス
 * \details
 * 引数 peripheral を使って、アドレス slave のI2Cデバイスからの読み込みを行う関数。

 * この関数はブロッキング関数である。つまり、読み込みを開始すると、その終了まで待って
 * 帰ってくる。
 *
 * また、複数のタスクが同時にこの関数を呼んだ場合には、うち一つだけが関数を実行し、他のタスクは
 * 待ち状態になる。
 *
 * 返り値はプロトコルの処理ステータスである I2C_SETUP_STATUS_XXX と、I2C ステータス
 * レジスタの最後の値である I2C_I2STAT_M_XXXX がビット論理和された状態になっている。
 * それぞれの詳細は lpc17xx_i2c.h を参照。
 * 正常終了ならオール0である。
 *
 */
int i2c_master_read( int peripheral, int slave, unsigned char read_data[], int read_count);

/**
 * \brief I2C マスター書き込み読み込み関数
 * \param peripheral マイコンのI2Cペリフェラルの番号。0,1,2のいずれか
 * \param slave 7bitで表すI2Cペリフェラルの番号。bit0:6のみ使い、bit7以上は0にすること。
 * \param write_data ペリフェラルに書き込むデータ・バイト列
 * \param write_count ペリフェラルに書き込むデータの長さ。単位はバイト。
 * \param read_data ペリフェラルから読み込むデータ・バッファ
 * \param read_count ペリフェラルから読み込むデータの長さ。単位はバイト。
 * \return エラーがなければ0。
 * \details
 * 引数 peripheral を使って、アドレス slave のI2Cデバイスに対する書き込みを行う関数。
 *
 * この間数は、まず slave に対して write_data バッファから write_count 個のデータを
 * 書き込む。続いて I2C の repeated start を使って同じ slave に対する read_count個の
 * 読み出しを行う。
 *
 * この関数はブロッキング関数である。つまり、読み込みを開始すると、その終了まで待って
 * 帰ってくる。
 *
 * また、複数のタスクが同時にこの関数を呼んだ場合には、うち一つだけが関数を実行し、他のタスクは
 * 待ち状態になる。
 * 返り値はプロトコルの処理ステータスである I2C_SETUP_STATUS_XXX と、I2C ステータス
 * レジスタの最後の値である I2C_I2STAT_M_XXXX がビット論理和された状態になっている。
 * それぞれの詳細は lpc17xx_i2c.h を参照。
 * 正常終了ならオール0である。
 *
 */
int i2c_master_write_read( int peripheral, int slave, unsigned char write_data[], int write_count, unsigned char read_data[], int read_count );

/*@}*/

#endif /* I2C_SUBSYSTEM_H_ */
