/*
 * Copyright (C) 2016-2017 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#define DEBUG_CONTROL_FLOW      0

/*
 * See: ATMEL docs page 49 ff.
 */

#ifdef INCLUDE
#endif /* INCLUDE */
#ifdef STATE

struct {
	int state_in;

	int irq;

	uint8_t ie;
	uint8_t sc;
} NAME;

#endif /* STATE */
#ifdef EXPORT

/*forward*/ static void                                       
NAME_(f_set)(struct cpssp *cpssp, uint8_t val);                 
/*forward*/ static void                                       
NAME_(f_get)(struct cpssp *cpssp, uint8_t *valp);               
/*forward*/ static void                                       
NAME_(ie_set)(struct cpssp *cpssp, uint8_t val);                
/*forward*/ static void                                       
NAME_(ie_get)(struct cpssp *cpssp, uint8_t *valp);              
/*forward*/ static void                                       
NAME_(sc_set)(struct cpssp *cpssp, uint8_t val);                
/*forward*/ static void                                       
NAME_(sc_get)(struct cpssp *cpssp, uint8_t *valp);              
/*forward*/ static void                                       
NAME_(ack)(struct cpssp *cpssp);                                
/*forward*/ static void                                       
NAME_(__in_set)(struct cpssp *cpssp, unsigned int val);

#endif /* EXPORT */
#ifdef BEHAVIOR

static void
NAME_(update)(struct cpssp *cpssp)
{
	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s\n", __FUNCTION__);
	}

	NAME_(irq_set)(cpssp, cpssp->NAME.ie & cpssp->NAME.irq);
}

static void
NAME_(ack)(struct cpssp *cpssp)
{
	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s\n", __FUNCTION__);
	}

	if (cpssp->NAME.sc != 0) {
		cpssp->NAME.irq = 0;
	}
	NAME_(update)(cpssp);
}

static void
NAME_(f_set)(struct cpssp *cpssp, uint8_t val)
{
	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, val);
	}

	cpssp->NAME.irq &= ~val;
	NAME_(update)(cpssp);
}

static void
NAME_(f_get)(struct cpssp *cpssp, uint8_t *valp)
{
	*valp = cpssp->NAME.irq;

	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, *valp);
	}
}

static void
NAME_(ie_set)(struct cpssp *cpssp, uint8_t val)
{
	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, val);
	}

	cpssp->NAME.ie = val;
	NAME_(update)(cpssp);
}

static void
NAME_(ie_get)(struct cpssp *cpssp, uint8_t *valp)
{
	*valp = cpssp->NAME.ie;

	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, *valp);
	}
}

static void
NAME_(sc_set)(struct cpssp *cpssp, uint8_t val)
{
	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, val);
	}

	cpssp->NAME.sc = val;
}

static void
NAME_(sc_get)(struct cpssp *cpssp, uint8_t *valp)
{
	*valp = cpssp->NAME.sc;

	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=%d\n", __FUNCTION__, *valp);
	}
}

static void
NAME_(__in_set)(struct cpssp *cpssp, unsigned int val)
{
	unsigned int new;

	if (DEBUG_CONTROL_FLOW) {
		fprintf(stderr, "%s: val=0x%08x\n", __FUNCTION__, val);
	}

	new = 2500 <= SIG_mV(val);

	switch (cpssp->NAME.sc) {
	case 0: /* Low Level */
		cpssp->NAME.irq = ! new;
		break;
		
	case 1: /* Any Edge */
		cpssp->NAME.irq = cpssp->NAME.state_in ^ new;
		break;

	case 2: /* Falling Edge */
		cpssp->NAME.irq = cpssp->NAME.state_in & ~new;
		break;

	case 3: /* Rising Edge */
		cpssp->NAME.irq = ~cpssp->NAME.state_in & new;
		break;

	default: assert(0); /* Mustn't happen. */
	}
	cpssp->NAME.state_in = new;

	NAME_(update)(cpssp);
}

static void
NAME_(create)(struct cpssp *cpssp)
{
}

static void
NAME_(destroy)(struct cpssp *cpssp)
{
}

#endif /* BEHAVIOR */

#undef DEBUG_CONTROL_FLOW
