#ifndef DIGIRULE1_H
#define	DIGIRULE1_H

#include <xc.h>

///////////////////////////////////////////////////////////////////////////////
// build options

#define SR_GATED_LATCH	0		// 0 = rising-edge clocked SR flip-flop (legacy)
								// 1 = high-active gated SR transparent latch

///////////////////////////////////////////////////////////////////////////////
// port bit assignments

#define DOWN_SW			PORTAbits.RA0
#define UP_SW			PORTAbits.RA1
#define A_LED			LATAbits.LA2
#define B_LED			LATAbits.LA3
#define NOT_LED			LATAbits.LA4
#define OR_LED			LATAbits.LA5
#define AND_LED			LATAbits.LA6
#define XOR_LED			LATAbits.LA7

//						LATBbits.LB0
#define A_SW			PORTBbits.RB1
#define B_SW			PORTBbits.RB2
#define GATE_SEL_SW		PORTBbits.RB3
#define SJTD_SW			PORTBbits.RB4
#define CLK_SW			PORTBbits.RB5
#define RK_SW			PORTBbits.RB6		// PGC
#define FF_SEL_SW		PORTBbits.RB7		// PGD

#define X_LED			LATCbits.LC0
#define SJTD_LED		LATCbits.LC1
#define CLK_LED			LATCbits.LC2
#define RK_LED			LATCbits.LC3
#define SR_LED			LATCbits.LC4
#define JK_LED			LATCbits.LC5
//						LATCbits.LC6
#define TEST_POINT		LATCbits.LC7		// TQFP pin 1, DIP pin 26

#define T_LED			LATDbits.LD0
#define D_LED			LATDbits.LD1
#define Q_LED			LATDbits.LD2
#define QNOT_LED		LATDbits.LD3
#define CTR8_LED		LATDbits.LD4
#define CTR4_LED		LATDbits.LD5
#define CTR2_LED		LATDbits.LD6
#define CTR1_LED		LATDbits.LD7

#define NOR_LED			LATEbits.LE0
#define NAND_LED		LATEbits.LE1
#define XNOR_LED		LATEbits.LE2
//						PORTEbits.RE3		// VPP/MCLR, input only

///////////////////////////////////////////////////////////////////////////////
// type declarations

typedef enum { false, true } bool_t;
typedef unsigned char uint8;
typedef unsigned short uint16;

typedef union
{
	uint8 byte;
	struct
	{
		uint8 bit0 : 1;
		uint8 bit1 : 1;
		uint8 bit2 : 1;
		uint8 bit3 : 1;
		uint8 bit4 : 1;
		uint8 bit5 : 1;
		uint8 bit6 : 1;
		uint8 bit7 : 1;
	};
} union8_t;

typedef union
{
	uint16 word;
	struct
	{
		uint8 low_byte, high_byte;
	};
	struct
	{
		uint8 bit0  : 1;
		uint8 bit1  : 1;
		uint8 bit2  : 1;
		uint8 bit3  : 1;
		uint8 bit4  : 1;
		uint8 bit5  : 1;
		uint8 bit6  : 1;
		uint8 bit7  : 1;
		uint8 bit8  : 1;
		uint8 bit9  : 1;
		uint8 bit10 : 1;
		uint8 bit11 : 1;
		uint8 bit12 : 1;
		uint8 bit13 : 1;
		uint8 bit14 : 1;
		uint8 bit15 : 1;
	};
} union16_t;

typedef union
{
	uint8 byte;
	struct
	{
		uint8 state		: 1;
		uint8 pressed	: 1;
		uint8 held1		: 1;
		uint8 held2		: 1;
		uint8 released	: 1;
		uint8			: 3;
	};
} button_flags_t;

typedef union
{
	struct	// by name
	{
		button_flags_t a;
		button_flags_t b;
		button_flags_t gate_select;
		button_flags_t sjtd;
		button_flags_t clk;
		button_flags_t rk;
		button_flags_t ff_select;
		button_flags_t down;
		button_flags_t up;
	};
	struct	// by index
	{
		button_flags_t array[9];
	};
} button_t;

typedef enum
{
	CounterModeBinary,
	CounterModeGray,
} counter_mode_t;

///////////////////////////////////////////////////////////////////////////////
// public function declarations

void all_leds_set( uint8 n );
void buttons_process( void );
uint8 ctr_leds_get( void );
uint8 ctr_leds_set( uint8 n );

void mode_dice_init( void );
void mode_dice_process( void );

void mode_game_init( void );
void mode_game_process( void );

void mode_led_test_init( void );
void mode_led_test_process( void );

void mode_logic_init( void );
void mode_logic_process( void );

void mode_pov_init( void );
void mode_pov_process( void );

void mode_shift_reg_init( void );
void mode_shift_reg_process( void );

void mode_sparkle_init( void );
void mode_sparkle_process( void );

void mode_standard_init( counter_mode_t mode );
void mode_standard_process( void );

uint8 prng( void );

///////////////////////////////////////////////////////////////////////////////
// public variable declarations

extern uint16 ticks;
extern button_t button;

#endif	// DIGIRULE1_H
