/*	
 *	clipay3.h
 *
 *	P/ECE AY-3-8910 Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Sat Feb 07 19:08:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_AY3_H__
#define __CLIP_AY3_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

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

#define AY38910BUFLEN 320 /* = 16000/50 … 1[tick](=1/50[sec])当たりのサンプル数 */

typedef struct _AY38910 AY38910;

/*
 *	AY-3-8910ポート入出力外部関数の型定義
 */
typedef unsigned char AY38910INPROC (AY38910* ay, int port/*0:ポートA/1:ポートB*/);
typedef          void AY38910OUTPROC(AY38910* ay, int port/*0:ポートA/1:ポートB*/, unsigned char data);

/*
 *	AY-3-8910チャネル
 */
typedef struct _AY38910CHANNEL {
	int tone_enable;		/* トーン (0:Off/1:On) */
	int noise_enable;		/* ノイズ (0:Off/1:On) */
	int amplitude_mode;		/* 音量モード (0:音量指定/1:エンベロープ) */
	int amplitude_level;		/* 音量指定 (小:0〜15^2:大) */
	int tone_period;		/* トーン分周比 (0x000〜0xfff)×(16÷2) */
	int tone_progress;		/* トーン進行カウンタ */
	int tone_output;		/* トーン出力値 (0:Lo/1:Hi) */
} AY38910CHANNEL;

/*
 *	AY-3-8910コア
 */
/*typedef*/ struct _AY38910 {
	unsigned char reg[16];		/* レジスタ値 */
	int address;			/* レジスタアドレス選択 (0〜15) */
	//
	AY38910CHANNEL channel[3];	/* チャネル (0:A/1:B/2:C) */
	//
	int noise_enable;		/* いずれかのチャネルがノイズを使用している? */
	int noise_period;		/* ノイズ分周比 (0x00〜0x1f)×16 */
	int noise_progress;		/* ノイズ進行カウンタ */
	int noise_lfsr;			/* Linear Feedback Shift Register */
	int noise_output;		/* ノイズ出力値 (0:Lo/1:Hi) */
	//
	int envelope_enable;		/* いずれかのチャネルがエンベロープを使用している? */
	int envelope_shape_cycle;	/* エンベロープパターン (0〜15) */
	int envelope_period;		/* エンベロープ分周比 (0x00〜0xffff)×16 */
	int envelope_progress;		/* エンベロープ進行カウンタ */
	unsigned envelope_counter;	/* エンベロープ波形カウンタ */
	int envelope_level;		/* エンベロープ出力値 (0〜15^2) */
	//
	AY38910INPROC* in;		/* ポート入力外部関数 */
	AY38910OUTPROC* out;		/* ポート出力外部関数 */
	//
	DDA clock_progress;		/* クロック進行DDA */
} /*AY38910*/;

/****************************************************************************
 *	内部関数
 ****************************************************************************/

/* AY-3-8910リセット時に設定される、AY-3-8910コア内蔵のポート入出力外部関数です。
 * アプリケーションから直接呼び出すことはありません。
 */
unsigned char ay38910_internal_in (AY38910* ay, int port);
         void ay38910_internal_out(AY38910* ay, int port, unsigned char data);

int ay38910_process(AY38910* ay, int cycle);
int ay38910_channel_process(AY38910* ay, AY38910CHANNEL* channel, int cycle);

/****************************************************************************
 *	アプリケーション用関数
 ****************************************************************************/

/* AY-3-8910コアをリセットします。
 * [in]
 *	ay		AY38910構造体。
 *	clock		入力クロック。
 *	in		ポート入力外部関数。
 *	out		ポート出力外部関数。
 * [note]
 *	* アプリケーションプログラムは、少なくとも最初に一度、この関数を呼び出してください。
 *	  その後は、AY-3-8910リセットを行う場合に、必要に応じて呼び出してください。
 *	* in,outにNULLを指定すると、コア内蔵の外部関数を使用します。
 *	  コア内蔵の外部関数は、次のような動作を行います。
 *	  ・IN		常に-1を返します。
 *	  ・OUT		何もしません。
 */
void ay38910_reset(AY38910* ay, int clock, AY38910INPROC* in, AY38910OUTPROC* out);

/* 次回の読み書きレジスタを選択します。
 * [in]
 *	ay		AY38910構造体。
 *	address		レジスタアドレス。(0〜15)
 */
void ay38910_address(AY38910* ay, int address);

/* レジスタ値を読み出します。
 * [in]
 *	ay		AY38910構造体。
 * [out]
 *	戻り値		レジスタ値。
 * [note]
 *	* 読み出すレジスタ番号は、あらかじめay38910_address()にて設定しておいてください。
 */
unsigned char ay38910_read(AY38910* ay);

/* レジスタ値を書き込みます。
 * [in]
 *	ay		AY38910構造体。
 *	data		レジスタ値。
 * [note]
 *	* 書き込むレジスタ番号は、あらかじめay38910_address()にて設定しておいてください。
 */
void ay38910_write(AY38910* ay, unsigned char data);

/* 出力サンプリングレート=SPEAKER_OUTPUT[Hz]で、指定されたサンプル数のミキシングを行います。
 * [in]
 *	ay		AY38910構造体。
 *	wbuff		出力サンプルバッファ。
 *	count		出力サンプル数。
 */
void ay38910_mix(AY38910* ay, short wbuff[/*count*/], int count);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_AY3_H__*/
