/*
 * messageproc.c
 *
 *  Created on: 2021Äê11ÔÂ1ÈÕ
 *      Author: graydon
 */
#include <string.h>
#include <stdlib.h>
#include <SRU.h>
#include "messageproc.h"
#include "../drv/spi.h"
#include "../drv/gpio.h"
#include "../drv/memory.h"
#include "queue.h"
#include "tob.h"
#include "F2F.h"
#include "zlib.h"
#include "ModuleProAPI.h"

s32 Message::Send(MsgType msg_type, uvoidptr buffer, u32 len)
{
	MSG msg;

	msg.Enc(msg_type, buffer, len);
	return txQueue->Push(msg);
}

s32 Message::Send(MSG* pmsg )
{
	extern u32 g_spiQ_drop_cnt;
	u32 ret=  txQueue->Push(*pmsg);
	if(ret == 0) {
		g_spiQ_drop_cnt++;
		set_error(DSP_SPIQ_OVERRANGE);
	}
	return ret;
}

s32 Message::PresetProcess(MSG* pmsg)
{
	static u8* bin = NULL;
	extern ubool  TopoLoading ;
	extern eErrStatus err_status;

	if(pmsg->pktNo == 0 && bin != NULL ) {
		sram_free(SRAM_DDR, bin);
		bin = NULL;
	}
	if(pmsg->pktNo == 0 && bin == NULL) {
		bin = (u8*)sram_malloc(SRAM_DDR, mem_any ,pmsg->totalPkts*MSG_DATA_LEN);
	}
	if(bin == NULL) return -1;

	memcpy(bin+pmsg->pktNo*MSG_DATA_LEN, pmsg->data , pmsg->dataLen);
	if(pmsg->pktNo == pmsg->totalPkts -1) {
		ToB* tob = ToB::GetInstance();
		u32 size = (pmsg->totalPkts -1)*MSG_DATA_LEN+pmsg->dataLen;
		uLongf realsize = size*10;
		Bytef* uncompress_ptr = (Bytef*)sram_malloc(SRAM_DDR, mem_any ,realsize);
		ErrStatus err = ErrStatus::ERR_PARAM;

		if(uncompress_ptr){
			if(tob && uncompress(uncompress_ptr, &realsize, (Bytef*)bin, size) == Z_OK) {
				err = tob->toCtrl(uncompress_ptr, realsize);
			}
			if(err != ErrStatus::SUCCESS){
				set_error(DSP_PRESET_INVALID);
			}
			sram_free(SRAM_DDR, uncompress_ptr);
		}

		sram_free(SRAM_DDR, bin);
		bin = NULL;
		TopoLoading = ufalse;
		Send(MsgType::MSG_PRESET_RES, 0 ,0) ;
	}

	return 0;
}

s32 Message::TopoProcess(MSG* pmsg)
{
	static u8* bin = NULL;
	extern ubool  TopoRequest;
	extern ubool  TopoLoading ;
	u32 size =0;

	if(pmsg->pktNo == 0 && bin != NULL ) {
		sram_free(SRAM_DDR, bin);
		bin = NULL;
	}
	if(pmsg->pktNo == 0 && bin == NULL) {
		bin = (u8*)sram_malloc(SRAM_DDR, mem_any ,pmsg->totalPkts*MSG_DATA_LEN);
		size =0 ;
	}
	if(bin == NULL) return -1;
	TopoLoading = utrue;
	memcpy(bin+pmsg->pktNo*MSG_DATA_LEN, pmsg->data , pmsg->dataLen);
	if(pmsg->pktNo == pmsg->totalPkts -1) {
		ToB* tob = ToB::GetInstance();
		ErrStatus err = ErrStatus::SUCCESS;
		size = (pmsg->totalPkts -1)*MSG_DATA_LEN+pmsg->dataLen;

		SetTxRxNullBufferPtr();
		SetNumOfChannels(0, 0);

		if(tob) {
			tob->toClear();
			err = tob->CreateModule(bin, size);
		}
		if(err != ErrStatus::SUCCESS) {
			set_error(DSP_TOPO_INVALID);
		}

		sram_free(SRAM_DDR, bin);
		bin = NULL;
		if(TopoRequest) {
			Send(MsgType::MSG_TOPO_RES, 0 ,0) ;
			TopoRequest = ufalse;
		}
	}

	return 0;
}

s32 Message::ParamCtrl(MSG* pmsg)
{
	ToB* tob = ToB::GetInstance();
	Param * ptr = (Param *)pmsg->data;
	const s16* val = (const s16*)(pmsg->data+sizeof(Param));

	if(tob != NULL)
		tob->toCtrl(ptr->mID, ptr->pID, val, ptr->num);

	return ptr->num;
}



s32 Message::SystemConfigSetProcess(MSG* pmsg)
{
	extern ubool  HandShakeSuccesful;
	extern ubool  TopoRequest;
	extern u16 mDspIndex;
	extern u32 g_level_report_interval;
	DSPConfig* conf = (DSPConfig*)pmsg->data;

	if(HandShakeSuccesful == ufalse) {
		//ĬÈÏÖµ¼ì²é
		if(conf->mLevelReportInt <50 || conf->mLevelReportInt >1000) {
			conf->mLevelReportInt = 200;
		}
		if(conf->mSampleNum <16 || conf->mSampleNum >64) {
			conf->mSampleNum = 64;
		}
		SAMPLE_NUM = conf->mSampleNum;
		mDspIndex = conf->mDspIndex;
		g_level_report_interval = LEVEL_REPORT_TIME(conf->mLevelReportInt);
		new ToB(conf->mDualDsp , conf->mDspIndex);

		ModuleLeveldBUSetting(conf->mConvertUnit);
		//Config(conf);
		RouteConfig(conf->routes,conf->mRouteNum);
		SRCsConfig(0 , conf->srcs);
		SRCsConfig(1 , &conf->srcs[4]);
		PCGsConfig(conf->pcgs);
		SportsConfig(conf->sports);

		HandShakeSuccesful = utrue;
		TopoRequest = utrue;
	}

	Send(MsgType::MSG_HANDSHAKE_RES, 0 , 0);

	return 0;
}



s32 Message::DSPStatusProcess(MSG* pmsg)
{
	struct DSPStatus* status = (struct DSPStatus*)pmsg->data;
	extern ufloat cpu_utility();
	extern u32 g_spiQ_drop_cnt;
	ToB* tob = ToB::GetInstance();

	status->mCpu =  cpu_utility()*100; //all modules execute time.;
	status->mInternalUnUsedMem = space_unused();
	status->mExternalUnUsedMem = sram_free_space(SRAM_DDR,mem_any);
	status->mSPIQDropCnt = g_spiQ_drop_cnt;
	status->mErrStatus = err_status;
	status->mLevelPacketsNum = tob?tob->GetLevelPacketNum():0;
	status->mModuleCnt = tob?tob->GetModuleNum():0;


	pmsg->Enc(MsgType::MSG_DSP_STATUS_RES, 0, sizeof(struct DSPStatus));

	return Send(pmsg);
}
//int count = 0;
s32 Message::RxMessageHandler(MSG* pmsg)
{
	if(pmsg->magic != 0x5aa5) {
		//printf("magic error.\n");
		return -1;
	}

	switch(pmsg->msgType){
	case MsgType::MSG_PARMA_CTRL_REQ:
		//printf("pctl.\n");
		ParamCtrl(pmsg);
		break;
	case MsgType::MSG_LEVEL_GET_REQ:
		break;
	case MsgType::MSG_PRESET_REQ:
		//printf("preset.%d(%d)\n",pmsg->totalPkts,pmsg->pktNo);
		PresetProcess(pmsg);
		break;
	case MsgType::MSG_TOPO_REQ:
		//printf("topo.%d(%d)\n",pmsg->totalPkts,pmsg->pktNo);
		TopoProcess(pmsg);
		break;
	case MsgType::MSG_HANDSHAKE_REQ:
		//printf("handshake.\n");
		SystemConfigSetProcess(pmsg);
		break;
	case MsgType::MSG_DSP_STATUS_REQ:
		DSPStatusProcess(pmsg);
		break;
	default:
		break;
	}

	return 0;
}



uvoid Message::Proc()
{
	u32 status = 0;

	if(SPIRxDone) {
		RxMessageHandler((MSG*)SPI_Rx_BUFFER);
		if(txQueue->Count() > 0) {
			txQueue->Pop(*(MSG*)SPI_Tx_BUFFER);
		}
		else {
			SPI_Tx_BUFFER[0] = 0;
		}
		SPI2_SetTransMode(SPIStatus::SPI_TRX);
	}

//	else {
//		if(SPIRxDone){
//			RxMessageHandler((MSG*)SPI_Rx_BUFFER);
//			status |= (u32)SPIStatus::SPI_RX;
//		}
//
//		if(SPITxDone && txQueue->Count() > 0){
//			txQueue->Pop(*(MSG*)SPI_Tx_BUFFER);
//			status |= (u32)SPIStatus::SPI_TX;
//		}
//		if(status ) {
//			SPI2_SetTransMode((SPIStatus)status);
//		}
//	}
}