#include "PinNames.h" #include "basic_types.h" #include #include "i2c_api.h" #include "i2c_ex_api.h" #include "pinmap.h" #include "wait_api.h" #include "alc5680.h" #define I2C_ALC5680_ADDR (0X5A/2) #if defined(CONFIG_PLATFORM_8195A) #define I2C_MTR_SDA PB_3 #define I2C_MTR_SCL PB_2 #elif defined(CONFIG_PLATFORM_8711B) #define I2C_MTR_SDA PA_30 #define I2C_MTR_SCL PA_29 #endif #define I2C_BUS_CLK 100000 //100K HZ //i2c_t alc5680_i2c; #if defined (__ICCARM__) i2c_t alc5680_i2c; #else volatile i2c_t alc5680_i2c; #define printf DBG_8195A #endif #define HELLO_BLUE_GENIE 0X03 #define ALEXA 0X04 #define SESAMEE 0X05 #define BAIDU 0X76 #define OLD_VERSION 0 #define NEW_VERSION 1 #define ALC_FW_START_ADDR 0X70000000 #if OLD_VERSION #define header_offset 32 //[addr1][len1][addr2]][len2][addr3]][len3][size][checksum] typedef struct _alc5680_fw{ unsigned int alc_addr[3]; unsigned int alc_len[3]; unsigned int size; unsigned int checksum; unsigned int alc_addr_offset; unsigned int alc_len_offset; unsigned int alc_len_index; }alc5680_fw; #endif #if NEW_VERSION #define header_offset 12 //[size][checksum][version] typedef struct _alc5680_fw{ unsigned int version; unsigned int size; unsigned int checksum; unsigned int alc_addr_offset; unsigned int alc_len_offset; }alc5680_fw; #endif static alc5680_fw alc5680_info; static void alc5680_delay(void) { int i; i=10000; while (i) { i--; asm volatile ("nop\n\t"); } } u8 alc5680_reg_write_16(u16 reg, u16 val) { int length = 0; char buf[4]; buf[0] = (char)(reg >> 8); buf[1] = (char)(reg&0xff); buf[2] = (char)(val>>8); buf[3] = (char)(val&0xff); length = i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 4, 1); //alc5680_delay(); return (length==4)?0:1; } u8 alc5680_reg_write_32(u32 reg, u32 val) { int tmp; char *buf = (char*)&tmp; u16 val1; u8 ret = 0; ret = alc5680_reg_write_16(0x0001,reg&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0002,reg>>16); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0003,val&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0004,val>>16); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0000,0x0003); if(ret != 0) printf("error\r\n"); return 0; }//0x1800C02C u8 alc5680_reg_write_16b(u32 reg, u16 val) { int tmp; char *buf = (char*)&tmp; u16 val1; u8 ret = 0; ret = alc5680_reg_write_16(0x0001,reg&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0002,reg>>16); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0003,val&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0000,0x0001); if(ret != 0) printf("error\r\n"); return 0; } u8 alc5680_reg_read_32(u32 reg, u32* val) { unsigned int tmp; char *buf = (char*)&tmp; u16 val1; u8 ret = 0; ret = alc5680_reg_write_16(0x0001,reg&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0002,reg>>16); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0000,0x0002); if(ret != 0) printf("error\r\n"); buf[0] = 0x0003>>8; buf[1] = 0x0003&0xff; if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){ DBG_8195A("alc5680_reg_read(): write register addr fail\n"); ret = 1; } //alc5680_delay(); buf[0] = 0xaa; buf[1] = 0xaa; if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){ printf("alc5680_reg_read(): read register value fail\n"); ret = 1; }else *val = ((buf[1]&0xFF)<<24)|((buf[0]&0xFF)<<16); buf[0] = 0x0004>>8; buf[1] = 0x0004&0xff; if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){ DBG_8195A("alc5680_reg_read(): write register addr fail\n"); ret = 1; } if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){ printf("alc5680_reg_read(): read register value fail\n"); ret = 1; }else *val |= ((buf[1]&0xFF)<<8)|(buf[0]&0xFF); //alc5680_delay(); return ret; } u8 alc5680_reg_read_16(u32 reg, u16* val) { int tmp; char *buf = (char*)&tmp; u16 val1; u8 ret = 0; ret = alc5680_reg_write_16(0x0001,reg&0xffff); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0002,reg>>16); if(ret != 0) printf("error\r\n"); ret = alc5680_reg_write_16(0x0000,0x0002); if(ret != 0) printf("error\r\n"); buf[0] = 0x0003>>8; buf[1] = 0x0003&0xff; if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){ DBG_8195A("alc5680_reg_read(): write register addr fail\n"); ret = 1; } //alc5680_delay(); buf[0] = 0xaa; buf[1] = 0xaa; if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){ printf("alc5680_reg_read(): read register value fail\n"); ret = 1; }else *val = ((buf[0]&0xFF)<<8)|(buf[1]&0xFF); //alc5680_delay(); return ret; } void alc5680_i2c_init(void) { i2c_init(&alc5680_i2c, I2C_MTR_SDA, I2C_MTR_SCL); i2c_frequency(&alc5680_i2c, I2C_BUS_CLK); memset(&alc5680_info,0,sizeof(alc5680_fw)); } void alc5680_erase() { unsigned short value = 0; alc5680_reg_write_32(0x18009508,0x00000001);//erase command while(1){ vTaskDelay(1000); alc5680_reg_read_16(0x18009508,&value); if((value&0x01)==0x00){ printf("Erase finish %d\r\n",value); break; }else{ printf("Erase ..... %x\r\n",value); } vTaskDelay(1000); } } void alc5680_write_data_to_flash(const unsigned char *data_value,unsigned int len,unsigned int addr) { int i = 0; unsigned int value = 0; const unsigned char *ptr = data_value; for(int i =0; i < len/4;i++){ value = (ptr[0])|(ptr[1]<<8)|(ptr[2]<<16)|(ptr[3]<<24); alc5680_reg_write_32(addr+i*4,value); ptr+=4; } } int alc5680_get_version() { unsigned int value = 0; alc5680_reg_read_32(0x7000A004,&value); value = value>>24; if(value == HELLO_BLUE_GENIE ) printf("VERSION:HELLO_BLUE_GENIE\r\n"); else if(value == ALEXA) printf("VERSION:ALEXA\r\n"); else if(value == SESAMEE) printf("VERSION:Zhima kaimen\r\n"); else if(value == BAIDU) printf("VERSION:Xiao du xiao du\r\n"); else printf("NON-DEFINE VERSION ADDR=0X7000A004 %x\r\n",value); return value; } void set_alc5680_volume(unsigned char left,unsigned char right) { alc5680_reg_write_16b(0x1800C02C, left<<8|right); } void get_alc5680_volume(unsigned short *value) { alc5680_reg_read_16(0x1800C02C, value); } void alc5680_status() { unsigned int value = 0; alc5680_reg_read_16(0x1800c1fe,&value); printf("codec id = %x\r\n",value); alc5680_reg_read_16(0x1800C0CA,&value); printf("status state = %x\r\n",value); alc5680_get_version(); } ///////////////////////////////////////////////////// #if OLD_VERSION void alc5680_get_info(unsigned char *buffer) { alc5680_info.size = buffer[0]<<24|buffer[1]<<16|buffer[2]<<8|buffer[3]; alc5680_info.checksum = buffer[4]<<24|buffer[5]<<16|buffer[6]<<8|buffer[7]; alc5680_info.version = buffer[8]<<24|buffer[9]<<16|buffer[10]<<8|buffer[11]; printf("codec size = %x checksum = %x version = %x\r\n",alc5680_info.size,alc5680_info.version); } void alc5680_handler_function(unsigned char *buffer,int len,unsigned int index) { unsigned char *buf_index = buffer; unsigned int buf_len = len; if(index == 1){ alc5680_get_info(buf_index); buf_index += header_offset; buf_len = buf_len - header_offset; alc5680_info.alc_len_offset = 0; alc5680_info.alc_len_index = 0; alc5680_info.alc_addr_offset = ALC_FW_START_ADDR; } alc5680_write_data_to_flash(buf_index,buf_len,alc5680_info.alc_addr_offset); alc5680_info.alc_addr_offset += buf_len; alc5680_info.alc_len_offset += buf_len; if(len != 512){ printf(" alc_addr_offset = %x alc_len_offset = %x \r\n",alc5680_info.alc_addr_offset,alc5680_info.alc_len_offset); } } void alc5680_check_sum() { unsigned int alc_checksum = 0; unsigned int i = 0, j = 0; unsigned int value = 0; unsigned int count = 0; unsigned int percent = alc5680_info.size/100; unsigned int percent_count = 0; if(percent%4) percent=percent+(4-(percent%4)); printf("checksum start\r\n"); for(i=ALC_FW_START_ADDR;i>8)+((value&0xff0000)>>16)+((value&0xff000000)>>24)); count+=4; if(count%percent == 0){ printf("%d%%\r", percent_count ); percent_count++; } } if(alc_checksum != alc5680_info.checksum) printf("Checksum error\r\n"); else printf("Checksum successful\r\n"); printf("bin_checksum %x alc_checksum = %x count = %d\r\n",alc5680_info.checksum,alc_checksum,count); } #endif #if NEW_VERSION void alc5680_get_info(unsigned char *buffer) { alc5680_info.size = buffer[0]<<24|buffer[1]<<16|buffer[2]<<8|buffer[3]; alc5680_info.checksum = buffer[4]<<24|buffer[5]<<16|buffer[6]<<8|buffer[7]; alc5680_info.version = buffer[8]<<24|buffer[9]<<16|buffer[10]<<8|buffer[11]; printf("codec size = %x checksum = %x version = %x\r\n",alc5680_info.size,alc5680_info.checksum,alc5680_info.version); } void alc5680_handler_function(unsigned char *buffer,int len,unsigned int index) { unsigned char *buf_index = buffer; unsigned int buf_len = len; if(index == 1){ alc5680_get_info(buf_index); buf_index += header_offset; buf_len = buf_len - header_offset; alc5680_info.alc_len_offset = 0; alc5680_info.alc_addr_offset = ALC_FW_START_ADDR; } alc5680_write_data_to_flash(buf_index,buf_len,alc5680_info.alc_addr_offset); alc5680_info.alc_addr_offset += buf_len; alc5680_info.alc_len_offset += buf_len; if(len != 512){ printf(" alc_addr_offset = %x alc_len_offset = %x \r\n",alc5680_info.alc_addr_offset,alc5680_info.alc_len_offset); } } void alc5680_check_sum() { unsigned int alc_checksum = 0; unsigned int i = 0, j = 0; unsigned int value = 0; unsigned int count = 0; unsigned int percent = alc5680_info.size/100; unsigned int percent_count = 0; if(percent%4) percent=percent+(4-(percent%4)); printf("checksum start\r\n"); for(i=ALC_FW_START_ADDR;i>8)+((value&0xff0000)>>16)+((value&0xff000000)>>24)); count+=4; if(count%percent == 0){ printf("%d%%\r", percent_count ); percent_count++; } } if(alc_checksum != alc5680_info.checksum) printf("Checksum error\r\n"); else printf("Checksum successful\r\n"); printf("bin_checksum %x alc_checksum = %x count = %d\r\n",alc5680_info.checksum,alc_checksum,count); } #endif