/*
 * Copyright (C) 2007 Speecys Corporation
 *		Toshiaki Nozawa <nozawa@speecys.com>
 * All rights reserved.
 */

#ifndef __SCIFTRAFMAIN_H__
#define __SCIFTRAFMAIN_H__

#define EVENT_PRIORITY

#include "libaccelSensor.h"
#include "libled.h"

/**
 * signal wrap
 */

#define	SIG_BUFCLR	SIGHUP		//buffer clear request
#define SIG_EMRREQ	SIGINFO		//emargency request

#define FLG_RESET_BASETIME	(uint32_t)(1 << 0)
#define FLG_END_OF_SEQ		(uint32_t)(1 << 1)
#define FLG_SOUND_REQ		(uint32_t)(1 << 8)
#define FLG_PIPE_READ_RETRY	(uint32_t)(1 << 31)

#define RESPDEVSTS_LEN	10

/**
 * Request ID from master process
 */
enum e_ReqCat {
    /**
     * control command requst.
     * ex.	request cancel.
     */
    ReqCmd,

    /**
     * one-shoot raw packet request.
     * This request must set priority to 'PrioReqOnce',
     * Others priority is not support !!
     * Never set 'PrioHigh' that couse priority rolling
     */
    ReqOnce,

    ReqDevPolling,	/** device status polling request */
    ReqEventHndl,	/** event handling request */
    ReqDevSts		/** read to status from polling table */
};

/**
 * Request priority level
 */
enum e_Priority {
    PrioHigh,	// packet delete command, and other command
    PrioReqOnce,// only servo move command, and must use servo move cmd
#ifdef EVENT_PRIORITY
    PrioSignal,
    PrioTimer,
#endif
    PrioMid,
    PrioLow
    , NUM_e_Priority
};

/**
 * struct cmnHeader flags symbol
 */
enum e_cmnHF {
   CmnHF_noFlg = 0,
   CmnHF_noAck = 1 << 0
};

/**
 * packet part
 */
enum e_packetCat {PcHdr, PcData, NUM_e_packetCat};

/**
 * One shoot request.
 * Data is send to fifo.
 *
 * Socket stream will following data after this header,
 * and that data length is datLen.
 */
struct cmnHeader {
    /**
     * In case of Request, sequense number.
     * client can start any valuse, and incremant it by request.
     * 
     * In case of Response, return requested sequense number.
     */
    uint32_t seq;

    /** Priority - should use 'enum e_Priority' value*/
    uint16_t pri;

    /** request/response category. should use enum e_ReqCat/e_RespCat	*/
    uint16_t cat;

    /** flags. should use enum e_cmnFlg	*/
    uint16_t flg;

    /** to align 64bit	*/
    uint16_t padding[2];

    /** data length */
    uint16_t datLen;

    /** should follow request packet. or datLen = 0	*/
};

/**
 * request command symbol for reqCmd.
 */
enum e_reqCmd {
    /** control command. no use 'id'	*/
    reqCancel,	/**
		 * request cancel.
		 * arg32_t: cancel seqNo
		 */

    /** LED command	*/
    ledDisp,	/**
		 * LED display request.
		 * arg32_t: pattern ID
		 */
    ledSrvOn,	/**
    		 * LED servo power turn on/off.
		 * arg32_t: 0 off, 1 on
		 */
    ledSrvMv,	/**
		 * LED servo move.
		 * arg16_t[0]: angle(1/10 deg), arg16_t[1]: time(1/10 sec)
		 */

    /** servo command	*/
    servoReset,	/**
		 * servo reset.
		 * arg: no use
		 */
    servoMove,	/**
		 * servo move. be carefull about all servo.
		 * arg16_t[0]: angle(1/10 deg), arg16_t[1]: time(1/10 sec)
		 */
    servoPower,	/**
		 * servo power turn on/off.
		 * arg8_t[0]: mode(1:on, 0:off)
		 */
    servoCmpMgn,	/**
			 * set servo compliance margin.
			 * arg8_t[0]: margin
			 */
    servoCmpSlope,	/**
			 * set servo compliance slope.
			 * arg8_t[0]: slope
			 */
    servoPunch,	/**
		 * set servo punch.
		 * arg16_t[0]: punch
		 * network byte order.
		 */
    servoTorque,	/**
			 * set servo torque.
			 * arg8_t[0]: torque
			 */
    servoTempLim,	/**
			 * set servo temprature limit.
			 * arg16_t[0]: limit
			 * network byte order.
			 */

    NUM_e_reqCmd 
};

struct reqCmd {
    /**
     * command. this should use 'enum e_reqCmd'
     */
    uint32_t cmd;

    /**
     * servo ID. all servo is '0xFF'
     */
    u_char id;
    u_char padding[3]; 	//to align 32bit

    /** argument of command	*/
    union unionArg {
	uint32_t arg32_t;
	uint16_t arg16_t[2];
	u_char arg8_t[4];
    } arg;
};

struct reqOnce {
    /**
     * FLG_RESET_BASETIME:	reset basetime flag.
     * FLG_END_OF_SEQ:		end of sequence flag.
     * FLG_SOUND_REQ:		sound output command flag.
     */
    uint32_t flg;

    /**
     * ofset msec from basetime.
     *
     * !! IMPORTANT !!
     * This is interval to next packet. different to KFRM specific. 
     */
    uint32_t msec;

    /**
     * revive time value to read request from prioritied pipe(2)
     * at the requested timing past.
     *
     * 0: use last request value.
     */
    uint32_t revive_msec;

    /** command data array	*/
    u_char cmd[];	// c99 style for variable length data
};

struct reqDevPoll {
    /** group ID - should use 'enum e_DevPollGrp'	*/
    uint16_t grp;

    /**
     * polling flag
     * 0 : disable
     * others : enable
     */
    uint16_t enb;

    /**
     * dev polling interval in 'msec'.
     * MUST BE GREATER THAN 100msec.
     */
    uint32_t intervalMs;
};

enum e_reqEventHndlCat	{
    EHC_stop,	/** stop event report	*/

    EHC_gt,	/** greater than th.arg32_t	*/
    EHC_ge,	/** greater than and equal th.arg32_t	*/
    EHC_eq,	/** equal th.arg32_t		*/
    EHC_le,	/** less than and equal th.arg32_t	*/
    EHC_lt,	/** less than th.arg32_t	*/

    EHC_btwn,	/** between, th.arg16_t[0] <= value <= th.arg16_t[1]	*/
    EHC_ob,	/** out of bounds, value < th.arg16_t[0] or value > th.arg16_t[1]*/

    EHC_ledBtn,	/** LED button status	*/

    NUM_e_reqEventHndlCat
};

struct reqEventHndl {
    /** RS485 ID	*/
    uint16_t id;

    /** 'e_reqEventHndlCat'	*/
    uint16_t cat;

    /** thresh-hold value(2's comp).*/
    union unionArg th;
};

/**
 * device status request ID category
 */
enum e_ReqDevStsIDCat {
    DSIDCat_dev,	/** one device request	*/
    DSIDCat_grp		/** devece group request.	*/
};

/**
 * device status request category flag
 */
enum e_ReqDevStsCat {
    DSCat_params, DSCat_sts
    , NUM_e_ReqDevStsCat
};

enum e_ReqDevStsFlg {
    DSFlg_params	= 1 << DSCat_params,
    DSFlg_sts		= 1 << DSCat_sts
};

struct reqDevSts {
    /** should use 'enum e_ReqDevStsIDCat'	*/
    u_char idcat;

    /** ID no. should use 'enum e_DevGrp' or 'enum e_DevGrp'	*/
    u_char id;

    u_char padding[2];

    /**
     * should use 'enum e_ReqDevStsFlg'.
     */
    uint32_t reqStsFlg;
};



/**
 * Response ID from master process
 */
enum e_RespCat {
    RespAck,
    RespNack,
    RespEvent,
    RespDevSts,
    RespEndOfReqOnce,

    ErrNotInTime_ReqOnce
};

struct respEvent {
    u_char id; /** RS485 ID	*/

    u_char padding[3];	// align 32bit

    /** event th value	*/
    union {
	struct ledSwitchInf	ledSw[NUM_PUSH_SWITCH_ON_LED];
	uint16_t accelVal[NUM_accElem];
    } val;
};

struct respDevSts {
    u_char	id;	/** device ID	*/
    u_char	num;	/** num of elm	*/
    u_char	padding[2];

    struct devStsElm {
	uint32_t respStsCat;	/** use 'enum e_ReqDevStsCat'	*/
	u_char len;		/** valid sts len	*/
	u_char padding[5];
	u_char sts[RESPDEVSTS_LEN];	/** read status	*/
    } elm[];	//c99 style
};

#endif	//__SCIFTRAFMAIN_H__
