#ifndef LIBSYS_H
#define LIBSYS_H

// ---------------------------------------------------------
// Types
// ---------------------------------------------------------
#define INT8		signed char
#define INT16		signed short
#define INT32		signed int
#define INT64		signed long long
#define UINT8		unsigned char
#define UINT16		unsigned short
#define UINT32		unsigned int
#define UINT64		unsigned long long
#define INT			INT32
#define UINT		UINT32
#define FLOAT32		float
#define FLOAT64		double

#define	NO_ERROR		LSYS_SUCCESS
#define	ERROR			LSYS_ERR_BASE
#define	LSYS_SUCCESS	0
#define	LSYS_ERR_BASE	0x80000000

#define	IS_ERROR(e)		((e & LSYS_ERR_BASE) == LSYS_ERR_BASE)

#define	sys_gpio0		0xA0000000
#define	sys_gpio1		0xA0000004
#define	sys_led_port	sys_gpio0
#define	sys_usb_ctrl	sys_gpio1
#define	sys_timer_usec	0xA0000008
#define	sys_timer_sec	0xA000000C

#define	sys_itim_ctrl	0xA0000018
#define	sys_itim_stat	0xA000001C
#define	sys_itim0_cnt	0xA0000020
#define	sys_itim1_cnt	0xA0000024
#define	sys_itim2_cnt	0xA0000028
#define	sys_itim3_cnt	0xA000002C
#define	sys_itim0_cmp	0xA0000030
#define	sys_itim1_cmp	0xA0000034
#define	sys_itim2_cmp	0xA0000038
#define	sys_itim3_cmp	0xA000003C

#define	sys_uart_data	sys_uart0_data
#define	sys_uart_stat	sys_uart0_stat
#define	sys_uart_baud	sys_uart0_baud
#define	sys_uart0_data	0xA0010000
#define	sys_uart0_stat	0xA0010004
#define	sys_uart0_baud	0xA0010008
#define	sys_uart1_data	0xA0010100
#define	sys_uart1_stat	0xA0010104
#define	sys_uart1_baud	0xA0010108
#define	sys_uart2_data	0xA0010200
#define	sys_uart2_stat	0xA0010204
#define	sys_uart2_baud	0xA0010208
#define	sys_usb_data	0xA0020000
#define	sys_usb_mbx		0xA0020004
#define	sys_usb_addr	0xA0020008
#define	sys_usb_status	0xA002000C
#define	sys_vga_data	0xA0030004
#define	sys_vga_posx	0xA0030008
#define	sys_vga_posy	0xA0030010
#define	sys_vga_clrscr	0xA0030020
#define	sys_vga_clrline	0xA0030040
#define	sys_vga_cgcol	0xA0030080
#define	sys_vga_mctrl	0xA0030100
#define	sys_vga_moffs	0xA0030200
#define	sys_ac97_stat	0xA0040000
#define	sys_ac97_ctrl	0xA0040000
#define	sys_ac97_acstat	0xA0040400
#define	sys_ac97_acctrl	0xA0040600
#define	sys_ac97_pcm	0xA0040800
#define	sys_ac97_wavin	sys_ac97_pcm
#define	sys_ac97_wavout	sys_ac97_pcm
#define	sys_flash_io	0xA4000000
#define	sys_flash_mem	0x00000000
#define	sys_ssram_io	0xA8000000

//#define STDOUT_FUNCTION	_cg_putchar		// Video character
//#define STDERR_FUNCTION	_putchar		// Serial output

#ifndef _putchar
#define _putchar		_ser_putchar		// Serial output
#endif

#ifndef STDOUT_FUNCTION
#define STDOUT_FUNCTION	_ser_putchar		// Serial output
#endif
#ifndef STDERR_FUNCTION
#define STDERR_FUNCTION	_ser_putchar		// Serial output
#endif


UINT32 CP0_SR_read(void);
void CP0_SR_write(UINT32 val);
UINT32 CP0_CR_read(void);
void CP0_CR_write(UINT32 val);
UINT32 CP0_PRID_read(void);
UINT32 CP0_TR_read(void);
void CP0_TR_write(UINT32 val);
void CP0_TR_write_ptr(UINT32* pPtr);
void CP0_TR_read_ptr(UINT32* pPtr);
void ICACHE_invalidate_all(void);
void ICACHE_invalidate_at(UINT32* pPtr);
void DCACHE_invalidate_all(void);
void DCACHE_invalidate_at(UINT32* pPtr);

#define CALC_BAUD(b) \
	((UINT32)((float)CPU_FREQ_HZ/(16*b) + 0.5f) - 1);

#define	UART0_setbaud(b) \
	*((UINT32*)sys_uart0_baud) = CALC_BAUD(b);

#define	UART1_setbaud(b) \
	*((UINT32*)sys_uart1_baud) = CALC_BAUD(b);

#define	UART2_setbaud(b) \
	*((UINT32*)sys_uart2_baud) = CALC_BAUD(b);

char readchar(void);
void writechar(char c);
int write(int file, char *ptr, int len);
int sputs(char *pStr);
void print_byte(char byte);
void print_word(int word);
void _exit (int exitcode);
void sleep(unsigned ms);

void PrintBuffer8(UINT8 *pBuf, int nbpr, int len);
void memdump(UINT8 *pBuf, int print_offset_only, int num_bytes_per_row, int len);

#endif // LIBSYS_H

