/*
 * blink.c
 *
 *  Created on: 2021/03/23
 *      Author: 0170886
 */

#include <kernel.h>
#include "kernel_cfg.h"
#include <t_syslog.h>
#include <t_stdlib.h>

#include "device.h"
#include "cup_timer.h"
#include "common.h"
#include "blink.h"

/*
 *  Glboal Variable
 */
static TBL_CTL		gbl_ctl;

/*
 *  Initialization Routine
 */
void
blink_task_init(intptr_t exinf){
	GBL_CTLF = 0;
	GBL_BCOUNT = 0;
	GBL_NOWSTS = ST_BLINK_IDLE;
	GBL_NEXTSTS = ST_BLINK_IDLE;
}

/*
 *  LED4 Blink Time Generate Cyclic Handler
 */
void
led4_blink_time_handler(intptr_t exinf){
	SVC_PERROR(iwup_tsk(LED4_BLINK_TIME_TASK));
}

/*
 *  LED4 Blink Time Generate Task
 */
void
led4_blink_time_task(intptr_t exinf){
	T_EVENT *psnd_data;
	for(;;){
		SVC_PERROR(slp_tsk());          /* ハンドラから起床されるまでスリープ */

		/* 固定長メモリブロックの獲得 */
		SVC_PERROR(get_mpf(EVENT_MPF, (void**)&psnd_data));

		psnd_data -> event = EV_BLINK_BLINK;
		DEBUG_SYSLOG(LOG_NOTICE, " snd_dtq = 0x%p", psnd_data, " ");
	    SVC_PERROR(psnd_dtq(BLINK_DTQ, (intptr_t)psnd_data));
	}
}

/*
 *  LED4 Blink Task
 */
static void
StIdleEvTimeOut(void){
	GBL_NEXTSTS = ST_BLINK_LED_OFF;
	GBL_CTLF |= DBL_STSCHG;		/* 状態遷移有りを設定			 	*/

	GBL_BCOUNT = TIMEOUT_BLINK;
	sta_cyc(LED4_BLINK_TIME_HANDLER);
}

static void
StIdleEvAvtive(void){
	GBL_NEXTSTS = ST_BLINK_LED_OFF;
	GBL_CTLF |= DBL_STSCHG;		/* 状態遷移有りを設定			 	*/

	GBL_BCOUNT = ACT_BLINK_TIME;
	sta_cyc(LED4_BLINK_TIME_HANDLER);
}

static void
StLedOffEvOff(void){
	set_led4_state(OFF);
	GBL_NEXTSTS = ST_BLINK_IDLE;
	GBL_CTLF |= DBL_STSCHG;		/* 状態遷移有りを設定			 	*/

	GBL_BCOUNT = 0;
	stp_cyc(LED4_BLINK_TIME_HANDLER);
}

#define StLedOnEvOff StLedOffEvOff

static void
StLedOffEvBlink(void){
	GBL_BCOUNT--;
	if(GBL_BCOUNT == 0){
		GBL_NEXTSTS = ST_BLINK_IDLE;
		stp_cyc(LED4_BLINK_TIME_HANDLER);
	} else {
		set_led4_state(ON);
		GBL_NEXTSTS = ST_BLINK_LED_ON;
	}
	GBL_CTLF |= DBL_STSCHG;		/* 状態遷移有りを設定			 	*/
}

static void
StLedOnEvBlink(void){
	set_led4_state(OFF);
	GBL_BCOUNT--;
	if(GBL_BCOUNT == 0){
		GBL_NEXTSTS = ST_BLINK_IDLE;
		stp_cyc(LED4_BLINK_TIME_HANDLER);
	} else {
		GBL_NEXTSTS = ST_BLINK_LED_OFF;
	}
	GBL_CTLF |= DBL_STSCHG;		/* 状態遷移有りを設定			 	*/
}

/* ブリンクタスクのジャンプテーブルの定義 */
static const CALLBACK_BL BLStateTable[ST_BLINK_NUM][EV_BLINK_NUM]={
/*   TIMEOUT通知,       ACTIVE通知,      OFF通知,          0.25秒経過 */
	{&StIdleEvTimeOut,  &StIdleEvAvtive, NULL,			   NULL				},/* 休止状態 		*/
    {NULL,				NULL,			 &StLedOffEvOff,   &StLedOffEvBlink	},/* 点滅状態(消灯)	*/
    {NULL,				NULL,			 &StLedOnEvOff,    &StLedOnEvBlink	},/* 点滅状態(点灯)	*/
};

void
blink_task(intptr_t exinf)
{
	const CALLBACK_BL *pFunc;

	for (;;) {
        SVC_PERROR(rcv_dtq(BLINK_DTQ, (intptr_t *)&GBL_RCVAD));
		pFunc = &BLStateTable[GBL_NOWSTS][GBL_RCVEV];
		if(NULL != *pFunc){
			(*pFunc)();		/* 現状態とイベントに対応する関数を実行 */
		} else {
			DEBUG_SYSLOG(LOG_NOTICE, " ignore event. event id = %d ",GBL_RCVEV, " ");
        }
		if(GBL_CTLF & DBL_STSCHG) {		/* 状態遷移要求有り? */
			GBL_CTLF &= ~DBL_STSCHG;	/* 要求クリア		 */
			GBL_NOWSTS = GBL_NEXTSTS;   /* 状態更新 		 */
		}
        DEBUG_SYSLOG(LOG_NOTICE, " rel_mpf = 0x%p", GBL_RCVAD, " ");
		SVC_PERROR(rel_mpf(EVENT_MPF, GBL_RCVAD));
	}
}
