
#include <stdlib.h>
#include <stdio.h>

#include "ag101.h"
#include "symbol.h"
#include "cpe.h"
#include "apb_dma.h"
#include "command.h"
#include "ssp.h"
#include "ac97_test.h"
#include "interrupt.h"

#define CODEC_Sizes (UINT32)0x300000
#define AC97_REC_LENGTH (CODEC_Sizes/2)
#define ptrCODEC    (UINT32)0x2000000

UINT32 RecordCmd(CommandTableStruct_T *CmdTable);
UINT32 PlayCmd(CommandTableStruct_T *CmdTable);

static UINT16 *ptrData;
static UINT16 *DataStart;
static UINT32 u32AC97_Base;
static UINT32 u32APBDMA_Base;
static UINT32 EXIT=FALSE;

extern CommandTableStruct_T fLib_CmdTable[21];

static CommandTableStruct_T AC97_CmdTable[] =
{
    {{"play","p", NULL,}, "play/p [-m]\n",
        0, 0, 0, 0, 0, 0, PlayCmd, 0, 0,
        {
            {0, NULL, 0, FALSE, ""},
        },
    },

    {{"record","rc", NULL,}, "record/rc [-m]\n",
        0, 0, 0, 0, 0, 0, RecordCmd, 0, 0,
        {
            {0, NULL, 0, FALSE, ""},
        },
    },

    {{NULL},
    },
	 
};

void main()
{
    char Buf[0x80];
    UINT32 target,u32i;

    ptrData=(UINT16 *)ptrCODEC;
    DataStart=(UINT16 *)ptrCODEC;
    EXIT=FALSE;

    target=1;

    if(target==1){
        u32AC97_Base =  CPE_I2S_BASE;
        u32APBDMA_Base= AHB2APB_DMA_A;
    }
    REG32(CPE_PMU_BASE + 0x28) |= (1 << 6); 

    REG32(CPE_PMU_BASE + 0x28) |= (1 << 3); 

    REG32(CPE_PMU_BASE + 0x28) |= (1 << AC97ClkOutSel); 

    fLib_SSP_GetTxFIFOLen(u32AC97_Base);

    fLib_SetSSPFrame(u32AC97_Base,AC97_Format);

    fLib_SetSSP_ColdReset(u32AC97_Base);

    fLib_SetSSP_Enable(u32AC97_Base,FALSE);

    fLib_SetSSP_IntMask(u32AC97_Base,0);


    fLib_InsertCommand(AC97_CmdTable);
    fLib_InitUserSymbol(NULL);
    while(!EXIT)
    {
        printf("AC97>>>\n");
        gets(Buf);
        fLib_ExecuteCommand(Buf);
    }
    return;
}

UINT32 RecordCmd(CommandTableStruct_T *CmdTable)
{
    volatile UINT16 *data;
    UINT32  intDataLen;
    UINT32 revlen;
    int i;

    data=(UINT16 *)ptrCODEC;
    intDataLen=0;
	printf("Recording music from LINE IN, please waiting!!\n");

    if(u32AC97_Base == CPE_I2S_BASE)
        fLib_DisableInt(intrAC97);

    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_RESET, 0);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_MASTER_VOLUME, 0x8000);

	fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_LINE_IN_VOLUME, 0x0808);
	fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_RECORD_SELECT, 0x0404);

    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_PCM_OUT_VOL, 0x8000);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_RECORD_GAIN, 0x0808);

    fLib_AC97_SetSlotValidReg(u32AC97_Base,0x9800);

    fLib_SSPClearRxFIFO(u32AC97_Base);

    fLib_SetSSP_Enable(u32AC97_Base,TRUE);


    while(intDataLen<AC97_REC_LENGTH)
    {
        revlen = (inw(u32AC97_Base + SSP_STATUS)&0x1F0)>>4;
        if(revlen>0)
        {
            for(i=0;i<revlen;i++)
            {
                *data++ = (inw(u32AC97_Base+SSP_DATA)&0xFFFFF)>>4;
                intDataLen++;
                if(intDataLen>=AC97_REC_LENGTH)
                    break;
            }
        }
    }

    printf("Record completely\n");
    fLib_SetSSP_Enable(u32AC97_Base,FALSE);

	fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_LINE_IN_VOLUME, 0x8000);

    return OK_COMMAND;
}

UINT32 PlayCmd(CommandTableStruct_T *CmdTable)
{
    volatile UINT16 *data;
    UINT32 u32RemainDataLen;
    UINT32 sample;


    data=(UINT16 *)ptrCODEC;
    ptrData=(UINT16 *)ptrCODEC;
    u32RemainDataLen=AC97_REC_LENGTH;

    printf("Play music....\n");
	if(u32AC97_Base == CPE_I2S_BASE)
		fLib_EnableInt(intrAC97);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_RESET, 0);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_MASTER_VOLUME, 0);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_PCM_OUT_VOL, 0x0808);
    fLib_AC97_WriteRegisterEx(u32AC97_Base,AC97_RECORD_GAIN, 0x8000);   

    fLib_AC97_SetSlotValidReg(u32AC97_Base,0x9800);

    fLib_SSPClearTxFIFO(u32AC97_Base);

    fLib_SetSSP_Enable(u32AC97_Base,TRUE);
    while(u32RemainDataLen>0)
    {
        if((inw(u32AC97_Base + SSP_STATUS)&0x2)!=0) 
        {
            sample = (*data)<<4;
            data++;
            outw(u32AC97_Base+SSP_DATA, sample);
            u32RemainDataLen--;
        }
    }

    fLib_SetSSP_Enable(u32AC97_Base,FALSE);
    printf("Play completely \n");
    if(u32AC97_Base == CPE_I2S_BASE)
        fLib_DisableInt(intrAC97);

    return OK_COMMAND;
}
