/*********************************************************************************
 * PROJECT: MiMic
 * --------------------------------------------------------------------------------
 *
 * This file is part of MiMic
 * Copyright (C)2011 Ryo Iizuka
 *
 * MiMic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by　the Free Software Foundation, either version 3 of the　License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * For further information please contact.
 *	http://nyatla.jp/
 *	<airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
 *
 *********************************************************************************/
/**
 * @file
 * このファイルは、ルートモジュールにあるヘッダファイルを集積します。
 * 基本的な型の定義も行います。
 */
#ifndef NyLPC_stdlib_h
#define NyLPC_stdlib_h
#include "NyLPC_config.h"

/**
 *　環境定数です。WIN32環境でコンパイルすることを示します。
 */
#define NyLPC_ARCH_WIN32 1
/**
 *　環境定数です。FREERTOS環境でコンパイルすることを示します。
 */
#define NyLPC_ARCH_FREERTOS 2

/**
 * 環境定数です。アーキテクチャを選択します。NyLPC_ARCH_WIN32は、デバック用の定数です。
 * 通常は、NyLPC_ARCH_FREERTOSを使用します。
 */
#ifdef WIN_DEBUG
	#define NyLPC_ARCH NyLPC_ARCH_WIN32
#else
	#define NyLPC_ARCH NyLPC_ARCH_FREERTOS
#endif

#if NyLPC_ARCH==NyLPC_ARCH_FREERTOS
	#include "FreeRTOS.h"
	#include "semphr.h"
	#include "task.h"
#elif NyLPC_ARCH==NyLPC_ARCH_WIN32
#else
#error Bad NyLPC_ARCH!
#endif

#include <string.h>
/**********************************************************************
 *
 * ASSERT/ABORT
 *
 **********************************************************************/

/**
 * 引数チェック専用のASSERT構文です。
 * デバック時のみ有効です。
 */
#define NyLPC_ArgAssert(e) if(!(e)){NyLPC_assertHook(NULL,-1);};

/**
 * ASSERTマクロです。
 * デバック時のみ有効です。
 */
#define NyLPC_Assert(e) if(!(e)){NyLPC_assertHook(NULL,-1);};

/**
 * デバック用のフックマクロです。
 * デバック時のみ有効です。
 */
#define NyAR_DebugHook() {NyLPC_debugHook(__FILE__,__LINE__);};

/**
 * Abortマクロです。プログラムを異常終了するときのエントリポイントになります。
 * デバック時/リリース時のどちらでも有効です。
 */
#define NyLPC_Abort() {NyLPC_abortHook(__FILE__,__LINE__);};	//もうだめ

/**
 * Abortマクロです。eが偽の時に、異常終了します。
 * デバック時/リリース時のどちらでも有効です。
 * @param e
 * 評価式です。
 */
#define NyLPC_AbortIfNot(e) if(!(e)){NyLPC_abortHook(__FILE__,__LINE__);};

/**
 * 警告表示用のマクロです。デバックに使います。
 * デバック時のみ有効です。
 */
#define NyLPC_Warning() {NyLPC_debugHook(__FILE__,__LINE__);};

/**
 * 警告表示用のマクロです。eが偽の時に、警告を出します。
 * デバック時のみ有効です。
 * @param e
 * 評価式です。
 */
#define NyLPC_WarningIfNot(e) if(!(e)){NyLPC_debugHook(__FILE__,__LINE__);};

/*
 * トレースマクロです。デバックに使います。
 * 内部変数に、最後にコールされたファイル名と、行番号を保存します。
 * デバック時のみ有効です。
 */
#define NyLPC_Trace() {NyLPC_debugHook(__FILE__,__LINE__);};

/**
 * アサートマクロが使う関数です。
 * @param m
 * __FILE__を指定します。
 * @param l
 * __LINE__を指定します。
 */
void NyLPC_assertHook(const char* m,int l);
 /**
  * Abortマクロが使う関数です。
  * @param m
  * __FILE__を指定します。
  * @param l
  * __LINE__を指定します。
  */
void NyLPC_abortHook(const char* m,int l);
/**
 * Debugマクロが使う関数です。
 * @param m
 * __FILE__を指定します。
 * @param l
 * __LINE__を指定します。
 */
void NyLPC_debugHook(const char* m,int l);

/**
 * デバック用のステータス変数です。
 * アサートを検出した回数を保存します。
 */
extern unsigned int NyLPC_assert_counter;
/**
 * デバック用のステータス変数です。
 * アサートを検出した回数を保存します。
 */
extern unsigned int NyLPC_abort_counter;
/**
 * デバック用のステータス変数です。
 * アサートを検出した回数を保存します。
 */
extern unsigned int NyLPC_debug_counter;

/**
 * GOTO方式のエラーハンドラを記述するためのマクロです。
 * @param l
 * 指定ラベルへジャンプします。
 */
#if NyLPC_ARCH==NyLPC_ARCH_FREERTOS
	#define NyLPC_OnErrorGoto(l) goto l
#elif NyLPC_ARCH==NyLPC_ARCH_WIN32
	#define NyLPC_OnErrorGoto(l) printf("%s:%d\n",__FILE__,__LINE__); goto l;
#else
#error Bad NyLPC_ARCH!
#endif



/**********************************************************************
 *
 * Basic type
 *
 **********************************************************************/

/**
 * 処理系依存の真偽値型です。
 */
#if NyLPC_ARCH==NyLPC_ARCH_FREERTOS
	typedef portBASE_TYPE NyLPC_TBool;
#elif NyLPC_ARCH==NyLPC_ARCH_WIN32
	typedef int NyLPC_TBool;
#else
#error Bad NyLPC_ARCH!
#endif
/**
 * TRUEを表します。この値は、ifで評価したときに真を返すことを保障します。
 */
#define NyLPC_TBool_TRUE (0==0)
/**
 * FALSEを表します。この値は、ifで評価したときに偽を返すことを保障します。
 */
#define NyLPC_TBool_FALSE (0!=0)

/**
 * ｳｪｰｲを表します。この値は、NyLPC_TBool_FALSEと同じです。
 */
#define NyLPC_TBool_VEII NyLPC_TBool_FALSE



/**
 * 8bit長のバイト文字の型です。
 */
typedef char NyLPC_TChar;
/**
 * 符号有り8bit型です。
 */
typedef char NyLPC_TInt8;
/**
 * 符号有り16bit型です。
 */
typedef short NyLPC_TInt16;
/**
 * 符号有り32bit型です。
 */
typedef long NyLPC_TInt32;

//----------------------------------------------------------------------
//　NyLPC_TUInt8
//----------------------------------------------------------------------

/**
 * 符号無し8bit型です。
 */
typedef unsigned char NyLPC_TUInt8;

/**
 * ビット操作関数です。bfのビット番号bに、1をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt8_setBit(bf,b) NyLPC_TUInt32_setBit(bf,b)
/**
 * ビット操作関数です。bfのビット番号bに、0をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt8_unsetBit(bf,b) NyLPC_TUInt32_unsetBit(bf,b)
/**
 * ビット判定関数です。bfのビット番号bが1であるかを確認します。
 * @bf
 * 判定する変数です。
 * @b
 * 判定するビット番号です。
 * @return
 * ビットが1なら真を返します。
 */
#define NyLPC_TUInt8_isBitOn(bf,b) NyLPC_TUInt32_isBitOn(bf,b)

/**
 * 8bit長のTRUE値です。
 */
#define NyLPC_TUInt8_TRUE NyLPC_TBool_TRUE
/**
 * 8bit長のFALSE値です。
 */
#define NyLPC_TUInt8_FALSE NyLPC_TBool_FALSE
/**
 * 8bit長のFALSEをNyLPC_TBoolへ変換します。
 * @param a
 * 変換する変数です。
 * @return
 * 変換した値です。
 */
#define NyLPC_TUInt8_castto_TBool(a) ((a)?NyLPC_TBool_TRUE:NyLPC_TBool_FALSE)

//----------------------------------------------------------------------
// NyLPC_TUInt16
//----------------------------------------------------------------------

/**
 * 符号無し16bit型です。
 */
typedef unsigned short NyLPC_TUInt16;

/**
 * INTMAX
 */
#define NyLPC_TUInt16_MAX 0xFFFF

/**
 * ビット操作関数です。bfのビット番号bに、1をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt16_setBit(bf,b) NyLPC_TUInt32_setBit(bf,b)
/**
 * ビット操作関数です。bfのビット番号bに、0をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt16_unsetBit(bf,b) NyLPC_TUInt32_unsetBit(bf,b)
/**
 * ビット判定関数です。bfのビット番号bが1であるかを確認します。
 * @bf
 * 判定する変数です。
 * @b
 * 判定するビット番号です。
 * @return
 * ビットが1なら真を返します。
 */
#define NyLPC_TUInt16_isBitOn(bf,b) NyLPC_TUInt32_isBitOn(bf,b)

/**
 * バイトオーダーを入れ替えます。
 * @param n
 * 変換もとの変数です。
 * @return
 * 入れ替えた16ビット値を返します。
 *
 */
#define NyLPC_TUInt16_BSWAP(n) (((((NyLPC_TUInt16)(n))<< 8)&0xff00)|((((NyLPC_TUInt16)(n))>> 8)&0x00ff))



/**
 * バイトオーダーを入れ替えます。
 * NyLPC_TUInt16_BSWAPとの違いは、関数であることです。
 * @param n
 * 変換もとの変数です。
 * @return
 * 入れ替えた16ビット値を返します。
 */
NyLPC_TUInt16 NyLPC_TUInt16_bswap(NyLPC_TUInt16 n);
/**
 * 16bit長のTRUE値です。
 */
#define NyLPC_TUInt16_TRUE NyLPC_TBool_TRUE
/**
 * 16bit長のFALSE値です。
 */
#define NyLPC_TUInt16_FALSE NyLPC_TBool_FALSE
/**
 * 16bit長のFALSEをNyLPC_TBoolへ変換します。
 * @param a
 * 変換する変数です。
 * @return
 * 変換した値です。
 */
#define NyLPC_TUInt16_castto_TBool(a) ((a)?NyLPC_TBool_TRUE:NyLPC_TBool_FALSE)

//----------------------------------------------------------------------

/**
 * 符号無し32bit型です。
 */
typedef unsigned long NyLPC_TUInt32;
/**
 * ビット操作関数です。bfのビット番号bに、1をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt32_setBit(bf,b) bf=(bf|b)
/**
 * ビット操作関数です。bfのビット番号bに、0をセットします。
 * @bf
 * 操作対象の変数です。
 * @b
 * 操作するビット番号です。
 */
#define NyLPC_TUInt32_unsetBit(bf,b) bf=(bf&(~b))
/**
 * ビット判定関数です。bfのビット番号bが1であるかを確認します。
 * @bf
 * 判定する変数です。
 * @b
 * 判定するビット番号です。
 * @return
 * ビットが1なら真を返します。
 */
#define NyLPC_TUInt32_isBitOn(bf,b) ((bf&b)==(b))

/**
 * バイトオーダーを入れ替えます。
 * @param n
 * 変換もとの変数です。
 * @return
 * 入れ替えた32ビット値を返します。
 *
 */
#define NyLPC_TUInt32_BSWAP(n) (((((NyLPC_TUInt32)(n))<<24)&0xff000000)|((((NyLPC_TUInt32)(n))<< 8)&0x00ff0000)|((((NyLPC_TUInt32)(n))>> 8)&0x0000ff00)|((((NyLPC_TUInt32)(n))>>24)&0x000000ff))
/**
 * バイトオーダーを入れ替えます。
 * NyLPC_TUInt32_BSWAPとの違いは、関数であることです。
 * @param n
 * 変換もとの変数です。
 * @return
 * 入れ替えた32ビット値を返します。
 */
NyLPC_TUInt32 NyLPC_TUInt32_bswap(NyLPC_TUInt32 n);

/**
 * 32bit長のTRUE値です。
 */
#define NyLPC_TUInt32_TRUE NyLPC_TBool_TRUE
/**
 * 32bit長のFALSE値です。
 */
#define NyLPC_TUInt32_FALSE NyLPC_TBool_FALSE
/**
 * 32bit長のFALSEをNyLPC_TBoolへ変換します。
 * @param a
 * 変換する変数です。
 * @return
 * 変換した値です。
 */
#define NyLPC_TUInt32_castto_TBool(a) ((a)?NyLPC_TBool_TRUE:NyLPC_TBool_FALSE)


//----------------------------------------------------------------------

/**
 * 長さ付TChar配列の構造体です。
 *
 */
struct NyLPC_TCharArrayPtr
{
	/** 配列のポインタ */
	NyLPC_TChar* ptr;
	/**　配列の長さ */
	NyLPC_TUInt16 len;
};
/**
 * ptrの位置をi_seekだけ進行します。
 * @param i_struct
 * 操作する構造体
 * @param i_seek
 * シークするバイト長
 */
NyLPC_TBool NyLPC_TCharArrayPtr_seek(struct NyLPC_TCharArrayPtr* i_struct,NyLPC_TUInt16 i_seek);


/**
 * 長さ付TUInt32配列の構造体です。
 *
 */
struct NyLPC_TUInt32ArrayPtr
{
	/** 配列のポインタ */
	NyLPC_TUInt32* ptr;
	/**　要素数 */
	NyLPC_TUInt16 len;
};
/**
 * ptrの位置をi_seekだけ進行します。
 * 進行すると、len要素がi_seekだけ減少します。
 * @param i_struct
 * 操作する構造体
 * @param i_seek
 * シークする要素長
 */
NyLPC_TBool NyLPC_TUInt32ArrayPtr_seek(struct NyLPC_TUInt32ArrayPtr* i_struct,NyLPC_TUInt16 i_seek);
/**
 * 構造体に、参照するバッファの初期位置とサイズをセットします。
 * セットしたバッファは、前方シークの可能な書き込みバッファとして使用できます。
 */
void NyLPC_TUInt32ArrayPtr_setBuf(struct NyLPC_TUInt32ArrayPtr* i_struct,NyLPC_TUInt32* i_ptr,NyLPC_TUInt16 i_len);



/*********************************************************************************
 *
 *********************************************************************************/


#include "../NyLPC_cRingBuffer.h"
#include "../NyLPC_cPtrTbl.h"
#include "../NyLPC_cFifoBuffer.h"
#include "../NyLPC_cPtrStream.h"
#include "../NyLPC_cStr.h"


#if NyLPC_ARCH==NyLPC_ARCH_FREERTOS
	#include "../NyLPC_cStopwatch.h"
	#include "../NyLPC_cMutex.h"
	#include "../NyLPC_cThread.h"
#endif



#endif
