diff --git a/audio.sv b/audio.sv
index 4fae75d4ff3315397be7912e15d99e6a54e4d30e..6fa101ae63b615e449d046b1e7788cb2514d300d 100644
--- a/audio.sv
+++ b/audio.sv
@@ -33,7 +33,7 @@ logic [7:0]counter,counter_next/*synthesis keep*/;
 
 logic audio_out_allowed,write_audio_out,write_audio_out_next;
 
-logic [4:0] data,data_next;
+logic [6:0] data,data_next;
 
 logic vol_set,vol_set_next;
 
@@ -244,8 +244,8 @@ Audio_Controller Audio_Controller (
 	.read_audio_in				(1'b0),
 	
 	.clear_audio_out_memory		(),
-	.left_channel_audio_out		({{8{audio_data_in[31]}},audio_data_in[31:16],8'h0}),
-	.right_channel_audio_out	({{8{audio_data_in[15]}},audio_data_in[15:0],8'h0}),
+	.left_channel_audio_out		({{4{audio_data_in[31]}},audio_data_in[31:16],12'h0}),
+	.right_channel_audio_out	({{4{audio_data_in[15]}},audio_data_in[15:0],12'h0}),
 	
 	//16'(signed'(IR[5:0]))
 	.write_audio_out			(write_audio_out),
diff --git a/avconf/avconf.v b/avconf/avconf.v
index 5d23ba986cd3638caaeb27e760a1f3a88e9c58c2..49aec8205d77cc80707525e42ced36f310e291d8 100644
--- a/avconf/avconf.v
+++ b/avconf/avconf.v
@@ -13,7 +13,7 @@ input		reset;
 output		I2C_SCLK;
 inout		I2C_SDAT;
 //  audio_volumn control
-input 		[4:0] AUD_VOL;
+input 		[6:0] AUD_VOL;
 
 //	Internal Registers/Wires
 reg	[15:0]	mI2C_CLK_DIV;
@@ -27,14 +27,16 @@ reg	[15:0]	LUT_DATA;
 reg	[5:0]	LUT_INDEX;
 reg	[3:0]	mSetup_ST;
 
-wire [8:0] AUD_LINE_IN_LC,AUD_LINE_IN_RC;
+wire [8:0] AUD_LINE_OUT_LC,AUD_LINE_OUT_RC;
 
 parameter USE_MIC_INPUT		= 1'b0;
 
-assign AUD_LINE_IN_LC	= {4'b0,AUD_VOL};
-assign AUD_LINE_IN_RC	= {4'b0,AUD_VOL};
-parameter AUD_LINE_OUT_LC	= 9'd119;
-parameter AUD_LINE_OUT_RC	= 9'd119;
+parameter AUD_LINE_IN_LC	= 9'b000010111;
+parameter AUD_LINE_IN_RC	= 9'b000010111;
+assign AUD_LINE_OUT_LC	= {2'b0,AUD_VOL};
+assign AUD_LINE_OUT_RC	= {2'b0,AUD_VOL};
+//assign AUD_LINE_OUT_RC	= 9'd119;
+//assign AUD_LINE_OUT_LC	= 9'd119;
 parameter AUD_ADC_PATH		= 9'd17;
 parameter AUD_DAC_PATH		= 9'd6;
 parameter AUD_POWER			= 9'h000;
diff --git a/software/audio_sd_other/main.c b/software/audio_sd_other/main.c
index 6490627786d83985e77bc6166302409ecbe4ae07..96fa4f5756622d7621fd45be6a3a8086bc812ea1 100644
--- a/software/audio_sd_other/main.c
+++ b/software/audio_sd_other/main.c
@@ -14,7 +14,7 @@
 #include <time.h>
 
 #include ".\terasic_lib\terasic_includes.h"
-#include ".\terasic_fat\FatFileSystem.h"
+#include ".\osufs\osufs.h"
 
 //#include ".\mp3lib\mad.h"
 //#include ".\mp3lib\minimad.h"
@@ -28,82 +28,45 @@ volatile uint32_t *audioReady = AUDIO_BASE+0x100;
 int main() {
 	printf("Hello world\n");
 	//from 00000 to 11111
-	*audioVol = 0xff;
+	*audioVol = 0x77;
 	//notice: must reset to start the I2C config
 	*VolReset = 1;
 	//short int fileP;
 	char filename[256];
 
-    FAT_HANDLE hFat;
-    FAT_FILE_HANDLE fileP;
     unsigned int fileSize;
     int i,j;
-
-    //unsigned char audioBuffer[32768];
+    osu_meta o_meta;
+    osu_song o_song;
+    osu_init_device();
    
     while(1){
-        printf("Initialized! Processing...\r\n");
+        if (osu_read_meta(&o_meta)){
+            printf("Sdcard mount success!\n");
+            printf("magic:%c%c%c%c\n",o_meta.magic[0],o_meta.magic[1],o_meta.magic[2],o_meta.magic[3]);
+            printf("Song Count:%d\n", o_meta.songs);
 
-        hFat = Fat_Mount(FAT_SD_CARD, 0);
-        if (hFat){
-            printf("sdcard mount success!\n");
-            printf("Root Directory Item Count:%d\n", Fat_FileCount(hFat));
-            //Fat_Test(hFat, "test.txt");
-            //Fat_Unmount(hFat);
             goto AUDIO;
             
-            //printf("===== Test Done =====\r\nPress KEY3 to test again.\r\n");
         }else{
-            printf("Failed to mount the SDCARD!\r\nPlease insert the SDCARD into DE2-115 board and press KEY3.\r\n");
-
+            printf("Failed to mount the SDCARD!\r\nPlease retry!\r\n");
         }
 
     } // while            
-  
-    AUDIO:
-    printf("please enter file name\n");
-	scanf("%s",filename);
-	fileP = Fat_FileOpen(hFat,filename);
-	if (!fileP){
-		printf("file open failed\n");
+  	
+    
+    printf("please enter song index(1 base)\n");
+    scanf("%d",&i);
+	if (!osu_read_song(i,&o_song)){
+		printf("song read failed\n");
 		goto AUDIO;
-	}
-	
-	
-	//pin point the beginning of file
-	fileSize = Fat_FileSize(fileP);
-	fileSize = fileSize >> 4;
-	uint32_t* audioDataInDram = malloc(fileSize);
-	memset(audioDataInDram,0xCC,fileSize);
-
-
-	//size_t end = clock();
-	//printf("mp3 decoding finished!\n %d ms used!\n",end-start);
-	
-	//unsigned int ptr=0;
-	//bool flag = 0;
-	
-	//for (i=0;i<(fileSize);++i){
-	i=0;
-	Fat_FileRead(fileP,audioDataInDram,fileSize);
-	fileSize = fileSize>>9;
-	//printf("%s\n", audioDataInDram);
-	while(i<fileSize){
+	}	
+	printf("%s\n",o_song.title);
+	AUDIO:
+	while(1){
 		if ((*audioReady)){
-				//Fat_FileRead(fileP,audioData,512);
-				for(j=0;j<128;++j){
-					audioData[j] = audioDataInDram[j];
-				//audioData[j+1] = (audioDataInDram[j>>1]&(0x00FF));
-					//printf("%c%c%c%c",  ((char*)(audioDataInDram+i))[0],((char*)(SDData+i))[1],((char*)(SDData+i))[2],((char*)(SDData+i))[3]);
-
-				}
-				//printf("%s",audioDataInDram);
-//			memcpy(audioData,audioDataInDram,512);
-		//}else{
-
-			//if (!flag) flag=1;
-				++i;
-				audioDataInDram += 128;
+			if (!osu_read_audio512(&o_song,audioData))
+				break;
 		}
 	}
 	printf("Playback completed\n");
diff --git a/software/audio_sd_other/osufs/osufs.c b/software/audio_sd_other/osufs/osufs.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb2942c0708cf6c32c94c925da873e75989776d6
--- /dev/null
+++ b/software/audio_sd_other/osufs/osufs.c
@@ -0,0 +1,76 @@
+//
+//  osufs.c
+//  osufs
+//
+//  Created by Fang Lu on 11/28/17.
+//  Copyright © 2017 Fang Lu. All rights reserved.
+//
+
+#include "osufs.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+
+bool osu_read_meta(void *buf) {
+	return SDLIB_ReadBlock512(0,buf);
+}
+
+bool osu_read_song(uint32_t block,void *buf) {
+	return SDLIB_ReadBlock512(block,buf);
+}
+
+bool osu_read_audio512(osu_song* o_song,void *buf) {
+	if (o_song->audio_offset > o_song->audio_len)
+		return 0;
+	if (SDLIB_ReadBlock512((o_song->audio_begin)+(o_song->audio_offset),buf)){
+		++(o_song->audio_offset);
+		return 1;
+	}else
+		return 0;
+}
+
+bool osu_read_cover(osu_song* o_song) {
+	//read palette data
+	uint16_t buf[256];
+	int i,j;
+	if (!SDLIB_ReadBlock512(o_song->cover_begin,buf)){
+		printf("palette read failed!\n");
+		return 0;
+	}
+	if (((char*)buf)[0]!="p" || ((char*)buf)[1]!="l" || ((char*)buf)[2]!="t"){
+		printf("palette magic number failed!\n");
+		return 0;
+	}
+
+	++(o_song->cover_begin);
+	
+	//send palette data
+	for (i=1;i<385;i+=3){
+		GL_PLWR(i-1, (((char*)buf[i])<<16)|(((char*)buf[i])<8)|((char*)buf[i]));
+	}
+	
+
+	//read & send cover data
+	for (i=0;i<600;++i){
+		SDLIB_ReadBlock512(o_song->cover_begin,buf);
+		++(o_song->cover_begin);
+		for (j=0;j<256;++j){
+			GL_SRAMWR(GL_SRAM_BGBASE + i<<8 + j, buf[j]);
+		}
+
+	}
+}
+
+/*void osu_write_meta(mdev *dev, osu_meta *meta) {
+	blkio_write(dev, 0, meta);
+}
+
+void osu_write_song(mdev *dev, int idx, osu_song *song) {
+	blkio_write(dev, idx+1, song);
+}*/
+
+bool osu_init_device(void) {
+	return SDLIB_Init();
+}
diff --git a/software/audio_sd_other/osufs/osufs.h b/software/audio_sd_other/osufs/osufs.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d5b2d5f8e45c0ef9d15e027aae933be2818ba3c
--- /dev/null
+++ b/software/audio_sd_other/osufs/osufs.h
@@ -0,0 +1,76 @@
+//
+//  osufs.h
+//  osufs
+//
+//  Created by Fang Lu on 11/28/17.
+//  Copyright © 2017 Fang Lu. All rights reserved.
+//
+
+#ifndef osufs_h
+#define osufs_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//define palette 
+#include "input/hid.h"
+#include "gl/gl.h"
+#include "gl/regs.h"
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+	typedef struct __attribute__((__packed__)) osu_meta_t {
+		char magic[4];							// 0   - 3
+		uint16_t songs;							// 4   - 5
+		uint16_t available_block;				// 6   - 7
+
+		char _padding[504];						// 8   - 511
+	} osu_meta;
+
+	typedef struct __attribute__((__packed__)) osu_song_t {
+		char magic[4];							// 0   - 3
+		uint32_t cover_begin, cover_len;		// 4   - 7
+		uint32_t audio_begin, audio_len;		// 8   - 11
+		uint32_t beatmap_begin, beatmap_len;	// 12  - 15
+		int16_t difficulty;						// 16  - 17
+		int16_t hp_drain;						// 18  - 19
+		int16_t circle_size;					// 20  - 21
+		int16_t approach_rate;					// 22  - 23
+		int16_t slider_mult;					// 24  - 25
+		int16_t slider_tick;					// 26  - 27
+		uint8_t combo_colors[3][8];				// 28  - 51
+		uint32_t preview_blk_offset;			// 52  - 55
+		uint32_t beatmap_id;					// 56  - 59
+		uint32_t beatmap_setid;					// 60  - 63
+		uint16_t audio_leadin;					// 64  - 65
+		uint16_t stack_leniency;				// 66  - 67
+
+		uint32_t audio_offset;
+		//uint32_t cover_offset;
+		//uint32_t beatmap_offset;
+		char _padding[242];						// 68  - 319
+
+		char title[64];							// 320 - 383
+		char artist[64];						// 384 - 447
+		char creator[32];						// 448 - 479
+		char version[32];						// 480 - 511
+	} osu_song;
+
+	bool osu_read_meta(void *buf);
+	bool osu_read_song(uint32_t block,void *buf);
+	//void osu_write_meta(mdev *dev, osu_meta *meta);
+	//void osu_write_song(mdev *dev, int idx, osu_song *song);
+	bool osu_read_audio512(osu_song* o_song,void *buf);
+	
+	bool osu_read_cover(osu_song* o_song);
+
+	bool osu_init_device(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* osufs_h */
diff --git a/software/audio_sd_other/terasic_sdcard/sd_hal.c b/software/audio_sd_other/terasic_sdcard/sd_hal.c
index cabca960606bde776413d944bbd4c643c4de8f09..d8dd3eb9a6b5d212878bed5f5382c297a65423ba 100644
--- a/software/audio_sd_other/terasic_sdcard/sd_hal.c
+++ b/software/audio_sd_other/terasic_sdcard/sd_hal.c
@@ -62,11 +62,7 @@ bool SDHAL_IsSupport4Bits(void){
 }
 
 void SDHAL_Init(void){
-//    SD_CMD_OUT;
-//    SD_DAT_IN;
-//    SD_CLK_HIGH;
-//    SD_CMD_HIGH;
-//    SD_DAT_LOW;
+
     IOWR_32DIRECT(InterfaceCmd,0,7);
     //*InterfaceCmd = 7;
 }
@@ -74,28 +70,11 @@ void SDHAL_Init(void){
 void SDHAL_SendCmd(alt_u8 szCommand[6], int nCmdLen){
 
     int i;
-    //alt_u8 Mask, Data;
-    
-    //SD_CMD_OUT;
-//    for(i=0;i<nCmdLen;i++){
-//        Mask = 0x80;
-//        Data = szCommand[i];
-//        for(k=0;k<8;k++){
-//            SD_CLK_LOW;
-//            if (Data & Mask)
-//                SD_CMD_HIGH;
-//            else
-//                SD_CMD_LOW;
-//            SD_CLK_HIGH;
-//            //
-//            Mask >>= 1;
-//           // usleep(1);
-//        }
-//    }
+
     for (i=0;i<6;++i){
         IOWR_32DIRECT(SDCmd+i,0,szCommand[i]);
         //*(SDCmd+i) = szCommand[i];
-        //printf("%c sent, %c receive\n",szCommand[i],*(SDCmd+i));
+
     }
     //*InterfaceCmd = 1;
     IOWR_32DIRECT(InterfaceCmd,0,1);
@@ -105,10 +84,7 @@ void SDHAL_SendCmd(alt_u8 szCommand[6], int nCmdLen){
 
 
 bool SDHAL_GetResponse(alt_u8 szResponse[], int nLen){
-    // bool bDone, bTimeout;
-    // const int nMaxCnt = 20; // !!!! Note. the value should be large than 8
-    // int nCnt, nBitCnt, nIndex;
-    // alt_u8 Value;
+
     int i;
     //*InterfaceCmd = 6;
     IOWR_32DIRECT(InterfaceCmd,0,6);
@@ -129,51 +105,7 @@ bool SDHAL_GetResponse(alt_u8 szResponse[], int nLen){
         //szResponse[i] = *SDResponse;
         szResponse[i] = IORD_32DIRECT(SDResponse,0);
     }
-    // SD_CMD_IN;
-    
-    // //===== check start bit == 0
-    // nCnt = 0;
-    // bDone = FALSE;
-    // bTimeout = FALSE;
-    // while(!bDone && !bTimeout){
-    //     SD_CLK_LOW;
-    //     SD_CLK_HIGH;
-    //     if(!(SD_TEST_CMD))
-    //         bDone = TRUE;
-    //     else if(nCnt++ > nMaxCnt)
-    //         bTimeout = TRUE;
-    // }
-    
-    // if (!bDone || bTimeout)
-    //     return FALSE;
-  
-    // //===== check transmitter bit == 0
-
-    // SD_CLK_LOW;
-    // SD_CLK_HIGH;
-    // if (SD_TEST_CMD)
-    //     return FALSE;   // 0 is expected
 
-    
-    // //===== read content + CRC + end-bits ======
-    // nIndex = 2;
-    // nBitCnt = nLen*8;
-    // bDone = FALSE;
-    // Value = 0;
-    // while(nIndex < nBitCnt){
-    //     SD_CLK_LOW;
-    //     SD_CLK_HIGH;
-    //     if (SD_TEST_CMD){
-    //         Value |= 0x80 >> (nIndex % 8);
-    //     }
-    //     if (nIndex%8 == 7){
-    //         szResponse[nIndex/8] = Value;
-    //         Value = 0;
-    //     }
-    //     nIndex++;
-    // } 
-    //IOWR_32DIRECT((addr),offset,data);
-    // A command with response. 8 clocks after the card response end bit.
     //*InterfaceCmd = 4;
     IOWR_32DIRECT(InterfaceCmd,0,4);
     return 1;
@@ -181,60 +113,19 @@ bool SDHAL_GetResponse(alt_u8 szResponse[], int nLen){
 
 
 bool SDHAL_ReadData(alt_u8 szBuf[], int nBufLen){
-//     bool bSuccess = TRUE;
-//     int nTry = 0;
-//     const int nMaxTry = 5000; 
-//     int i, j,k,n=0;   
-//     alt_u8  DataTemp;
-//     alt_u8 Data8;
- 
-// #ifndef SD_4BIT_MODE     
-//     alt_u16 DataCrc16, MyCrc16;
-    
-// #else
-//     alt_u8  szBuf_0[128],szBuf_1[128],szBuf_2[128],szBuf_3[128];
-    
-//     alt_u16 DataCrc16_0,DataCrc16_1,DataCrc16_2,DataCrc16_3;
-//     alt_u16 MyCrc16_0,MyCrc16_1,MyCrc16_2,MyCrc16_3;
-    
-//     alt_u8 Data8_0,Data8_1,Data8_2,Data8_3;
-    
-// #endif    
-    // wait start bits (zero)
-//     while(1){
-//       SD_CLK_LOW;
-//       SD_CLK_HIGH;
-// #ifdef SD_4BIT_MODE
-//       if((SD_TEST_DAT & 0x0F) == 0x00) // check start bits (zero is expected)
-// #else      
-//       if((SD_TEST_DAT & 0x01) == 0x00) // check start bits (zero is expected)
-// #endif      
-//         break;
-//       if (nTry++ > nMaxTry)
-//         return FALSE;        
-//     }     
+
     int i;
     
     //*InterfaceCmd = 3;
     IOWR_32DIRECT(InterfaceCmd,0,3);
-    //printf("fucked\n");
-    //scanf("%d",&i);
-    //usleep(100);
+
     //while (!(*InterfaceStatus));
     while (!(IORD_32DIRECT(InterfaceStatus,0)));
     for (i=0;i<128;++i){
-        //printf("%c%c%c%c",  ((char*)(SDData+i))[0],((char*)(SDData+i))[1],((char*)(SDData+i))[2],((char*)(SDData+i))[3]);
-        //usleep(20);
-        //((uint32_t*)szBuf)[i] = *(SDData+i);
+
         ((uint32_t*)szBuf)[i] = IORD_32DIRECT(SDData+i,0);
     }
-    //===== CRC16 and end-bit check (each channel is seperated)
-
-    // check end bit (value 'one' is expected
 
-     
-    // to provide8 (eight) clock cycles for the card to complete the operation before shutting down the clock 
-    //SDHAL_DummyClock(8);     
     //*InterfaceCmd = 5;
     IOWR_32DIRECT(InterfaceCmd,0,5);
     //*InterfaceCmd = 4;
@@ -244,17 +135,7 @@ bool SDHAL_ReadData(alt_u8 szBuf[], int nBufLen){
 
 bool SDHAL_WriteData(alt_u8 szDataWrite[], int nDataLen){
    
-    // to provide8 (eight) clock cycles for the card to complete the operation before shutting down the clock 
-    //SDHAL_DummyClock(8);     
-
-    /*
-    //
-    for(i=0; i<16; i++){
-        SD_CLK_LOW;
-        SD_CLK_HIGH;
-    }*/
-    
-    return 1;
+    return 0;
     
 }