/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017-2021 AXELL CORPORATION, all rights reserved.
 */

/*
   AG903用OpenVGのuC3でのポーティング例
*/

#include <stdlib.h>
#include <kernel.h>
#include <gmalloc.h>

#include "sample_common.h"
#include "openvg_port_uc3.h"

/* defineするとOpenVGの内部処理が完了するまでCPUを開放します。
 * undefとした場合はCPUで処理完了をポーリングします。
 */
#undef ENABLE_UC3_API


#ifdef ENABLE_UC3_API

#define INTNO_GFX 50 // IRQ18:GFX (INTNO=IRQ+32)

// Declare OpenVG callback
extern uint32_t get_interrupt_status_ovg(void);
extern void mask_interrupt_status_ovg(uint32_t mask);


static ID ovg_sem_id = E_ID;
static ID ovg_isr_id = E_ID;

static
void openvg_isr(VP_INT exinf)
{
	(void)exinf;
	mask_interrupt_status_ovg(0x00000000);
	isig_sem(ovg_sem_id);
}

void wait_event_ovg(void)
{
	ER er;
    er = wai_sem(ovg_sem_id);
	if (er != E_OK) {
		abort();
	}
}

#endif /* ENABLE_UC3_API */


void *malloc_ovg(size_t size)
{
	return sys_malloc(size);
}

void free_ovg(void *ptr)
{
	sys_free(ptr);
}

void *realloc_ovg(void *ptr, size_t size)
{
	void* get;

	get = sys_malloc(size);
	if(NULL != get) {
		sys_memcpy(get, ptr, size);
		sys_free(ptr);
	}

	return get;
}



int openvg_port_uc3_init(void)
{
#ifdef ENABLE_UC3_API
	ER er = AG903_ENONE;

	T_CISR cisr = {
		.isratr = TA_HLNG | TA_FPU,
		.exinf  = (VP_INT)0,
		.intno  = INTNO_GFX,
		.isr    = (FP)openvg_isr,
		.imask  = 0,
	};
	ovg_isr_id = acre_isr(&cisr);
	if (ovg_isr_id < 1) {
		er = ovg_isr_id;
		goto err_cisr;
	}

	T_CSEM csem = {
		.sematr  = TA_HLNG,
		.isemcnt = 0,
		.maxsem  = 1,
		.name    = "ovg_sem",
	};
	ovg_sem_id = acre_sem(&csem);
	if (ovg_sem_id < 1) {
		er = ovg_sem_id;
		goto err_csem;
	}

	ena_int(INTNO_GFX);

	return AG903_ENONE;

	//// Error exit code
		
 err_csem:
	ovg_sem_id = E_ID;

	del_isr(ovg_isr_id);
 err_cisr:
	ovg_isr_id = E_ID;

	return -AG903_ESYS;
#else
	return AG903_ENONE;
#endif
}

int openvg_port_uc3_term(void)
{
#ifdef ENABLE_UC3_API
	dis_int(INTNO_GFX);

	if (ovg_sem_id >= 1) {
		del_sem(ovg_sem_id);
		ovg_sem_id = E_ID;
	}

	if (ovg_isr_id >= 1) {
		del_isr(ovg_isr_id);
		ovg_isr_id = E_ID;
	}

	return AG903_ENONE;
#else
	return AG903_ENONE;
#endif
}
