/*
 * @history     2025_03_06  [SDK3.7] SSPサンプルにSPIモードの使用例を追加 (#5781)
 * @history     2025_03_06  [SDK3.7] SSPサンプルにSSPライブラリのDMA送受信関数使用例を追加 (#5782)
 */
/*
 * This program was created by Axell Corporation.
 * Copyright (C) 2017-2025 Axell Corporation, all rights reserved.
 */
#include "sample_common.h"
#include "com.h"
#include "ssp_sample.h"
#include "ssp/sspmgr.h"

/* プロトタイプ */
static int32_t Ssp_init_module(void);
static int32_t Ssp_term_module(void);
static void Ssp_SampleHelp(void);
static void Ssp_I2sAudioRecPio(void);
static void Ssp_I2sAudioPlayPio(void);
static void Ssp_I2sAudioRecDmaExternal(void);
static void Ssp_I2sAudioPlayDmaExternal(void);
static void Ssp_I2sAudioRecDmaInternal(void);
static void Ssp_I2sAudioPlayDmaInternal(void);
static void Ssp_SpiFlashCommandPio(void);
static void Ssp_SpiFlashCommandDmaInternal(void);

/* Param */
#define SSP_SMP_CH_MASTER		(2)		/* SSP CH [Master] 注：変更する場合は端子設定も */
#define SSP_SMP_CH_SLAVE		(3)		/* SSP CH [Slave]  注：変更する場合は端子設定も  */

/* Macro */
#define	EPRINT(FMT, ...)		sys_print(0, FMT,##__VA_ARGS__)
#define	PRINT(FMT, ...)			sys_print(0, FMT"\r\n",##__VA_ARGS__)
#define SSP_ERROR(str)			sys_print(1, " ERROR:%s[%d] *%s*\r\n",__FUNCTION__, __LINE__, str)

/* データ */
static void (*func[])() = {
	Ssp_SampleHelp,
	Ssp_I2sAudioRecPio,
	Ssp_I2sAudioPlayPio,
	Ssp_I2sAudioRecDmaExternal,
	Ssp_I2sAudioPlayDmaExternal,
	Ssp_I2sAudioRecDmaInternal,
	Ssp_I2sAudioPlayDmaInternal,
	Ssp_SpiFlashCommandPio,
	Ssp_SpiFlashCommandDmaInternal,
};

/**
 * @brief		メイン処理
 * @param[in]	param	制御パラメータ
 * @return		なし
 * @note		なし
 */
void SSP_main(uint8_t param)
{
	uint8_t		mode = 0;
	char		input[2+2];

	((void)param);

	Ssp_SampleHelp();	/* Help表示 */

	Ssp_init_module();

	while (mode != 0xFF) {
		EPRINT(" -- Choose sample number (00h<HELP> to FFh): ");
		COM_GetNum_Wait(input, sizeof(input));
		mode = (ASCtoBIN(input[0]) << 4)
			 | (ASCtoBIN(input[1]) << 0);
		if(0xFF == mode) {
			break;
		}
		if(mode >= (sizeof(func)/sizeof(void*))) {
			func[0](); /* Help */
		}
		else {
			func[mode]();		/* Sample func実行 */
		}
	}

	Ssp_term_module();

	return;
}

/**
 * @brief		サブ処理
 * @param[in]	param	制御パラメータ
 * @return		なし
 * @note		なし
 */
void SSP_sub(uint32_t param)
{
	((void)param);
	/* 処理なし */
	return;
}

/**
 * @brief		モジュール初期化
 * @param[in]	なし
 * @retval		AG903_ENONE		正常終了
 * @note		なし
 */
static int32_t Ssp_init_module(void)
{
	static _Bool	SspInit=false;
	int32_t 		init_tx, init_rx, init_ssp0;
	int32_t			ret;
	
	if(false == SspInit) {
		init_tx = AG903_SSPMgrInit(SSP_SMP_CH_MASTER); /* Managaer 初期化 */
		init_rx = AG903_SSPMgrInit(SSP_SMP_CH_SLAVE);
		init_ssp0 = AG903_SSPMgrInit(0);
		if((AG903_ENONE==init_tx)&&(AG903_ENONE==init_rx&&(AG903_ENONE==init_ssp0))) {
			SspInit = true;
		}
		else {
			SSP_ERROR("Init");
		}
	}

	ret = sys_meminit(AG903_SAMPLE_VRAM_SIZE-0x100000,
				 (void *)AG903_SAMPLE_VRAM_ADDR,
				 SYSMEM_NORMAL_CACHE_OFF);
	if(AG903_ENONE != ret) {
		return -AG903_EFAULT;
	}

	return AG903_ENONE;
}

/**
 * @brief		モジュール終了
 * @param[in]	なし
 * @retval		AG903_ENONE		正常終了
 * @note		なし
 */
static int32_t Ssp_term_module(void)
{
	sys_memfinal();

	return AG903_ENONE;
}

/**
 * @brief		ヘルプ表示
 * @param		なし
 * @return		なし
 * @note		なし
 */
static void Ssp_SampleHelp(void)
{
	PRINT("\t# 00 ... Help");
	PRINT("\t# 01 ... I2S Audio Rec  PIO");
	PRINT("\t# 02 ... I2S Audio Play PIO");
	PRINT("\t# 03 ... I2S Audio Rec  DMA External");
	PRINT("\t# 04 ... I2S Audio Play DMA External");
	PRINT("\t# 05 ... I2S Audio Rec  DMA Internal");
	PRINT("\t# 06 ... I2S Audio Play DMA Internal");
	PRINT("\t# 07 ... SPI Flash Command PIO");
	PRINT("\t# 08 ... SPI Flash Command DMA Internal");

	PRINT("\t# FF ... Exit Sample");
	
	return;
}


/**
 * @brief		オーディオ録音  [PIO]
 * @param		なし
 * @return		なし
 * @note		LINE-IN1から入力したデータをファイル保存します
 */
static void Ssp_I2sAudioRecPio(void)
{
	PRINT(" I2S Audio Rec PIO");
	
	Ssp_AudioRecPio(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		オーディオ再生  [PIO]
 * @param		なし
 * @return		なし
 * @note		ファイル保存されたオーディオデータをLINE-OUT1から出力します
 */
static void Ssp_I2sAudioPlayPio(void)
{
	PRINT(" I2S Audio Play PIO");
	
	Ssp_AudioPlayPio(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		オーディオ録音  [ユーザー制御DMA]
 * @param		なし
 * @return		なし
 * @note		LINE-IN1から入力したデータをファイル保存します
 */
static void Ssp_I2sAudioRecDmaExternal(void)
{
	PRINT(" I2S Audio Rec DMA External");
	
	Ssp_AudioRecDmaExternal(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		オーディオ再生  [ユーザー制御DMA]
 * @param		なし
 * @return		なし
 * @note		ファイル保存されたオーディオデータをLINE-OUT1から出力します
 */
static void Ssp_I2sAudioPlayDmaExternal(void)
{
	PRINT(" I2S Audio Play DMA External");
	
	Ssp_AudioPlayDmaExternal(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		オーディオ録音  [ライブラリ制御DMA]
 * @param		なし
 * @return		なし
 * @note		LINE-IN1から入力したデータをファイル保存します
 */
static void Ssp_I2sAudioRecDmaInternal(void)
{
	PRINT(" I2S Audio Rec DMA Internal");
	
	Ssp_AudioRecDmaInternal(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		オーディオ再生  [ライブラリ制御DMA]
 * @param		なし
 * @return		なし
 * @note		ファイル保存されたオーディオデータをLINE-OUT1から出力します
 */
static void Ssp_I2sAudioPlayDmaInternal(void)
{
	PRINT(" I2S Audio Play DMA Internal");
	
	Ssp_AudioPlayDmaInternal(SSP_SMP_CH_MASTER, SSP_SMP_FMT_I2S);
	
	return;
}

/**
 * @brief		SPIフラッシュコマンド制御 [PIO]
 * @param		なし
 * @return		なし
 * @note		SPIフラッシュにコマンドを送信し応答を受信します
 */
static void Ssp_SpiFlashCommandPio(void)
{
	_Bool dma;

	PRINT(" SPI Flash Command PIO");

	dma = false;
	Ssp_SpiFlashCommand(dma);
	
	return;
}

/**
 * @brief		SPIフラッシュコマンド制御 [ライブラリ制御DMA]
 * @param		なし
 * @return		なし
 * @note		SPIフラッシュにコマンドを送信し応答を受信します
 */
static void Ssp_SpiFlashCommandDmaInternal(void)
{
	_Bool dma;

	PRINT(" SPI Flash Command DMA Internal");
	
	dma = true;
	Ssp_SpiFlashCommand(dma);
	
	return;
}
