#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)

// GPIO
#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

// TIMERs
#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

// UARTs
#define SYS_UART_BIT_TX_HALFFULL		0x00000001
#define SYS_UART_BIT_TX_FULL			0x00000002
#define SYS_UART_BIT_RX_HALFFULL		0x00000004
#define SYS_UART_BIT_RX_FULL			0x00000008
#define SYS_UART_BIT_RX_AVAIL			0x00000010
#define SYS_UART_BIT_TX_INTEN			0x00000020
#define SYS_UART_BIT_RX_INTEN			0x00000040
#define SYS_UART_BIT_TX_IRQ				0x00000100
#define SYS_UART_BIT_RX_IRQ				0x00000200
#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

// PS2s
#define SYS_PS2_BIT_TX_EMPTY			0x00000001
#define SYS_PS2_BIT_RX_AVAIL			0x00000004
#define SYS_PS2_BIT_PIN_CLOCK			0x00000008
#define SYS_PS2_BIT_PIN_DATA			0x00000010
#define SYS_PS2_BIT_TX_INTEN			0x00000020
#define SYS_PS2_BIT_RX_INTEN			0x00000040
#define SYS_PS2_BIT_TX_IRQ				0x00000100
#define SYS_PS2_BIT_RX_IRQ				0x00000200
#define SYS_PS2_BIT_RX_ERR_PAR			0x00000800
#define SYS_PS2_BIT_RX_ERR_FLAG			0x00008000
#define	SYS_PS2_0_DATA					0xA0010200
#define	SYS_PS2_0_STAT					0xA0010204
#define	SYS_PS2_1_DATA					0xA0010300
#define	SYS_PS2_1_STAT					0xA0010304

// USB
#define	SYS_USB_DATA					0xA0020000
#define	SYS_USB_MBX						0xA0020004
#define	SYS_USB_ADDR					0xA0020008
#define	SYS_USB_STATUS					0xA002000C

// VGA
#define	SYS_VGA_CTRL					0xA0030000	// R/W
#define	SYS_VGA_BIT_CGRDY				0x00000001	// RO
#define	SYS_VGA_BIT_MSTEN				0x00000002	// R/W
#define	SYS_VGA_BIT_BUFCHG_INTEN		0x00000004	// RO
#define	SYS_VGA_BIT_BUFCHG_FLAG			0x00000008	// RO
#define	SYS_VGA_BIT_CLRSCR				0x00000010	// WO
#define	SYS_VGA_BIT_CLRLINE				0x00000020	// WO
#define	SYS_VGA_BIT_BLIT_REQ			0x00000100	// R/W
#define	SYS_VGA_BIT_BLIT_BSY			0x00000100	// R/W
#define	SYS_VGA_BIT_BLIT_FIN			0x00000200	// R/W
#define	SYS_VGA_BIT_BLIT_ACK			0x00000200	// R/W
#define	SYS_VGA_BIT_BLIT_FIN_INTEN		0x00000400	// R/W
#define	SYS_VGA_ASCII					0xA0030004	// R/W
#define	SYS_VGA_POSX					0xA0030008	// R/W
#define	SYS_VGA_POSY					0xA003000C	// R/W
#define	SYS_VGA_CGCOL					0xA0030010	// R/W
#define	SYS_VGA_RES						0xA0030014	// RO
#define	SYS_VGA_FB_FRONT				0xA0030018	// R/W
#define	SYS_VGA_FB_BACK					0xA003001C	// R/W
#define	SYS_VGA_BLIT_SRC0				SYS_VGA_BLIT_SRC0_FIRST	// R/W
#define	SYS_VGA_BLIT_SRC0_FIRST			0xA0030020	// R/W
#define	SYS_VGA_BLIT_SRC0_LAST			0xA0030024	// R/W
#define	SYS_VGA_BLIT_SRC0_DIMX			0xA0030028	// R/W
#define	SYS_VGA_BLIT_DST				SYS_VGA_BLIT_DST_FIRST	// R/W
#define	SYS_VGA_BLIT_DST_FIRST			0xA0030050	// R/W
#define	SYS_VGA_BLIT_DST_LAST			0xA0030054	// R/W
#define	SYS_VGA_BLIT_DST_DIMX			0xA0030058	// R/W
#define	SYS_VGA_BLIT_NX					0xA0030060	// R/W
#define	SYS_VGA_BLIT_NY					0xA0030064	// R/W

// AC'97
#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

// Flash
#define	SYS_FLASH_IO					0xA4000000
#define	SYS_FLASH_MEM					0x00000000

// Sync. SRAM
#define	SYS_SSRAM_IO					0xA8000000

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(UINT32 port);
void writechar(UINT32 port, 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);

char _getchar(void);

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

void Screen_clr(void);
void Screen_line_clr(void);
void Screen_csr_set_x(UINT32 coord);
void Screen_csr_set_y(UINT32 coord);
UINT32 Screen_get_resx(void);
UINT32 Screen_get_resy(void);
UINT32 Screen_get_fps(void);



#endif // LIBSYS_H

