#ifndef _AXEFX_H_
#define _AXEFX_H_

#define AXEFX_VER				2
#define AXEFX_EXTERN_BASE		16

#if AXEFX_VER == 1
	typedef uint8_t ParamType;
#elif AXEFX_VER == 2
	typedef uint16_t ParamType;
#endif
extern uint8_t AxefxModel;

/// This is the Axefx midi sysex ID
extern uint8_t AxefxId[];

enum AxefxCc
{
	CcNone,
	#define _(name, val)	Cc##name = val,
	#include "axefx-cc.h"
	#undef _
};

struct AxefxBlock
{
	uint8_t DefaultCc;
	uint8_t BlockId;
	char BypassParamId;
	const char *Name;
};

enum AxefxBlockId
{
	BlockAmp1 = 0x6A,
	BlockAmp2 = 0x6B,
	BlockCab1 = 0x6C,
	BlockCab2 = 0x6D,
	BlockDelay1 = 0x70, // See also DelayBlockParams
	BlockDelay2 = 0x71,
};

enum AmpBlockParams
{
	AmpBlock_Gain = 1,
	AmpBlock_Bass = 2,
	AmpBlock_Mid = 3,
	AmpBlock_Treble = 4,
	AmpBlock_Master = 5,
	AmpBlock_Level = 21,
	AmpBlock_Bright = 97,
};

enum DelayBlockParams
{
	DelayBlock_Tempo = 9, // Valid values are in DelayBlockTempo
	DelayBlock_Bypass = 22, // 4 = On, 5 = Off
};

#define DELAY_DIV_ENUM() \
	_(None, "None") \
	_(64trip, "1/64 trip") \
	_(64, "1/64") \
	_(64dot, "dotted 1/64") \
	_(32trip, "1/32 trip") \
	_(32, "1/32") \
	_(32dot, "dotted 1/32") \
	_(16trip, "1/16 trip") \
	_(16, "1/16") \
	_(16dot, "dotted 1/16") \
	_(8trip, "1/8 trip") \
	_(8, "1/8") \
	_(8dot, "dotted 1/8") \
	_(4trip, "1/4 trip") \
	_(4, "1/4") \
	_(4dot, "dotted 1/4") \
	_(2trip, "1/2 trip") \
	_(2, "1/2") \
	_(2dot, "dotted 1/2") \
	_(1trip, "bar trip") \
	_(1, "bar") \
	_(1dot, "dotted bar") \
	_(2bar, "2 bars") \
	_(3bar, "3 bars") \
	_(4bar, "4 bars")

enum DelayBlockTempo
{
	#define _(sym, txt) Tempo_##sym,
	DELAY_DIV_ENUM()
	#undef _
};
const char *ToString(DelayBlockTempo d);

/// Axefx sysex command ID's from:
/// http://wiki.fractalaudio.com/index.php?title=Axe-Fx_SysEx_Documentation
enum AxefxMidiCmd
{
	MIDI_PARAMETER											= 2,
	MIDI_GET_PATCH,											// 3
	MIDI_PATCH_DUMP,										// 4
	MIDI_PLACE_EFFECT,										// 5
	MIDI_CONNECT_EFFECT,									// 6
	MIDI_SET_MODIFIER,										// 7
	MIDI_GET_FIRMWARE_VERSION,								// 8
	MIDI_SET_PRESET_NAME,									// 9
	MIDI_TUNER_INFO											= 13, // 0x0d
	MIDI_GET_PRESET_EFFECT_BLOCKS_AND_CC_AND_BYPASS_STATE,	// 14,   0x0e
	MIDI_GET_PRESET_NAME,									// 15,   0x0f
	MIDI_TEMPO_BEAT,										// 16,   0x10
	MIDI_ACCESS_BLOCK_XY									= 0x11,
	MIDI_GET_PRESET_NUMBER									= 0x14,
	MIDI_GET_ROUTING_GRID_LAYOUT							= 0x20,
	MIDI_STATE_CHANGED_EVENT								= 0x21,
	MIDI_LOOPER_STATUS_ENABLE								= 0x23,
	MIDI_SET_SCENE_NUMBER									= 0x29,
	MIDI_STOP_SYSEX_OVER_USB								= 0x42,
};

enum AxefxParamMsgType
{
	AxefxParamGet = 0,
	AxefxParamSet = 1
};

extern const char *ToString(AxefxCc cc);
extern AxefxCc StringToCc(const char *s);
extern const AxefxBlock *AxefxGetBlocks();
extern int AxefxBlockCount();
extern const AxefxBlock *GetBlockById(int Id);
extern const AxefxBlock *GetBlockByIndex(int Idx);
extern uint8_t AxefxChecksum(uint8_t *p, int len);
extern void AxefxEncode(uint8_t *p, ParamType val);
extern ParamType AxefxDecode(uint8_t *p, uint8_t threeByte);


#endif