パラメータを適応変化させる事により圧縮率を向上させた動的ライス・ゴロム符号を利用した可逆圧縮方式。圧縮ソフト、圧縮率のMATLABシミュレーションは詳細はInterface誌2011年8月号に掲載されるRX62Nマイコン連動特集にて掲載予定。

Dependencies:   mbed

main.cpp

Committer:
lynxeyed_atsu
Date:
2011-03-30
Revision:
0:d920d64db582

File content as of revision 0:d920d64db582:

#include "mbed.h"
#include "MSCFileSystem.h"
#include "SDHCFileSystem.h"
#include "TextLCD.h"
#include "i2s_irq_test.h"
#include "lpc17xx_i2s.h"
#include "lpc17xx_clkpwr.h"
#include "aic23b_comm.h"
#include "string"
#include "_bitio.h"

#define _RGM_ADAPTIVE   1   /* 1:Adaptive 0:Constant */

#define k_bits	0x07        //    k_bits:0x09 to 0x0b?    
#define min_of_k 0x07 
#define max_of_k 0x0b		/*for dynamic Rice-Golomb codings */

DigitalOut led1(LED1); 
DigitalOut led2(LED2);
DigitalOut led3(LED3); 
DigitalOut led4(LED4); 
Serial pc(USBTX, USBRX); // tx, rx       
I2C AIC23B(p9,p10);     //sda,scl

TextLCD lcd(p24, p26, p27, p28, p29, p30);
SDFileSystem sd(p11, p12, p13, p14, "sd");//p5,6,7,8
//MSCFileSystem msc("msc"); // Mount flash drive under the name "msc"
FILE    *infp,*outfp,*playlist;

Ticker  tick;
Ticker  fl_leds;

#define AudioBufRow	256                         /* length of proc_r */  
volatile short int AudioBuf[2][AudioBufRow];    /* Audio Data Buffer:AudioBuf[empty_c][proc_r] */
volatile BYTE empty_c=0;			            /* Column of AudioBuf */
volatile BYTE proc_r=0;				            /* Row of AudioBuf */			
bool dac_semp;						            /* Write AudioBuf Complete? true:Yes, false:No */


int aic23b_send(int addr,char ctrl_address,char ctrl_data){
    int flag;
    char cmd[2];
    cmd[0]=ctrl_address;
    cmd[1]=ctrl_data;
    flag = AIC23B.write(addr, cmd, 2);
    pc.printf("ADDR=0x%x, CTRL_ADD=0x%x, CTRL_DATA=0x%x, RESP=0x%x\r\n",(addr&0x7f),cmd[0],cmd[1],flag);
    return (flag);
}

int aic23b_init(void){
    int flag=0;
    printf("*************************\r\nReset TLV320AIC23B\r\n*************************\r\n");
    AIC23B.frequency(150000);   
    flag = aic23b_send(AIC23B_ADDRESS,RESET_REFGISTER,RESET);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,POWER_DOWN_CONTROL,0);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,POWER_DOWN_CONTROL,1);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,DIGITAL_AUDIO_INTERFACE_FORMAT,(MASTER_MODE|INPUT_DATA_16_BIT_LENGTH|I2S_FORMAT));
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,SAMPLE_RATE_CONTROL,(SR_USB_44_1_KHZ_MODE| BOSR_USB_44_1_KHZ_MODE| USE_USB_CLOCK_44_1_KHZ_MODE));
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,ANALOG_AUDIO_PATH_CONTROL,0x10);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,DIGITAL_AUDIO_PATH_CONTROL,0);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,DIGITAL_INTERFACE_ACTIVATION,DIGITAL_INTERFACE_ACTIVE);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,LEFT_CHANNEL_HEADPHONE_VOLUME_CONTROL,LHV_VOLUME_DEFAULT);
    wait(0.1);
    flag += aic23b_send(AIC23B_ADDRESS,RIGHT_CHANNEL_HEADPHONE_VOLUME_CONTROL,RHV_VOLUME_DEFAULT);
 
    if(!flag) {
        printf("*************************\r\nReset OK\r\n*************************\r\n");
        return 0;
    }
    else{ 
        printf("*************************\r\nReset FAILED\r\n*************************\r\n");
        return -1;
    }
}

void pl_led_flash(void)
{
    if(led1){
        led1 = 0;
        led2 = 1;
        return;
    }

    if(led2){
        led2 = 0;
        led3 = 1;
        return;
    }
    
    if(led3){
        led3 = 0;
        led4 = 1;
        return;
    }    
    
    if(led4){
        led4 = 0;
        led1 = 1;
        return;
    }       


}

void dac_out(void)
{
    volatile static short i,j;		// AudioBuf[j][i]
    volatile uint32_t   DBufLR;     // Buffer Data to send I2S_TX 
    uint16_t BufLPCnt;
    for(BufLPCnt=0 ; BufLPCnt < 9 ; BufLPCnt++ )
    {
    	if(i >= AudioBufRow-1)
    	{
    		if(dac_semp)					/* colunm (empty_c) is full? true:Yes */
    		{
    			i=0;
    			empty_c =(empty_c==1)?0:1;	/* empty_c:empty column of buffer AudioBuf, Because I2S_TX used these data */
    			j=(empty_c==1)?0:1;			/* Change column which buffer is filled with data by function decode() */
    			dac_semp = false;			/* false: empty_c is ready to get data from function decode() */
    			
    		}else{							/* Buffer is NOT ready to read? */
    			return;						/* NO:return */
    		}
    	}
    	//Send I2S_TX
    	if(I2S_GetLevel(LPC_I2S, I2S_TX_MODE)==TXFIFO_FULL)break;
    	DBufLR = (0xffff0000 & (AudioBuf[j][i++]<<16))|(0x0000ffff & AudioBuf[j][i++]);
        I2S_Send(LPC_I2S,DBufLR);
    } 
}

void encode(long int n){
    int zero_shift = 0;
    
    if(n < 0){
        putbit(0);                    // sign (put 0:if n as negative)
        n = -n;                        // n = abs(n)
        //printf("\t 0");
    }
    else{ 
        putbit(1);                    // sign (put 1:if n as positive)
        //printf("\t 1");
    }
    zero_shift = (n >> (_lsb_k));
    //printf("\t shift= %d",zero_shift);
    while(zero_shift > 0){

        zero_shift--;
        putbit(0);
    }    // put n/(2^_lsb_k) 0's
    
    putbit(1);                        // terminating "1"
    putbits(_lsb_k,rightbits(_lsb_k,n));
    //printf("\t finish= %d \r\n",(n & ((1U<<_lsb_k)-1)));
}



void decode(void)
{
	volatile short		i=0,j=0;

	volatile long int	diff=0,diff2=0;				/* differential of previous data buffer  */
	volatile unsigned  int	buff_sign,zero_shift;	/* sign buffer,register for unary codings */
	volatile long int	decode_buff;				
	
	volatile unsigned char	k1= k_bits;				/* Coding Parameter (init:k_bits) */
	volatile unsigned char	k2= k_bits;
	
	init_bit_o();
	init_bit_i();								/* init bit control function */
	while(1){
		
		if(i!=empty_c)
		{
			if(j>=AudioBufRow-1)
			{
				i=empty_c;			/* Choose empty buffer*/
				j=0;
			}
		}
		
		if (j<AudioBufRow-1) 
		{
			/* decode */
			if((buff_sign = getbit()) == OVERRUN)break; /*get sign*/

			zero_shift = 0;
	    	while(getbit()==0)
				zero_shift++;							/* decode unary code */
			
			decode_buff = (signed int)(zero_shift*(1U<<k1));	/*decode Rice-Golomb code*/
			decode_buff += getbits(k1);
			
			if(!buff_sign)decode_buff =- decode_buff;	/*add sign */
			diff =(diff + decode_buff);					/* get audio data */		
        
			AudioBuf[i][j]=(short int)(diff);			/* write AudioBuf */
			j++;
			
			
#if _RGM_ADAPTIVE
			/* calc k */
			if(zero_shift > 2)k1=k1+1;
			if(zero_shift == 0)k1=k1-1;
			if(k1 < min_of_k)k1 = min_of_k;
			if(k1 > max_of_k)k1 = max_of_k; 
#endif	
			
			if((buff_sign = getbit()) == OVERRUN)break; /* get sign */
			
			zero_shift = 0;
			while(getbit()==0)
				zero_shift++;									/* decode unary code */
		
			decode_buff = (signed int)(zero_shift*(1U<<k2));	/* decode Rice-Golomb code */
			decode_buff += getbits(k2);			
			
			if(!buff_sign)decode_buff =- decode_buff;	/* add sign */
			diff2 =(diff2 + decode_buff);				/* get Audio data */		
        
			AudioBuf[i][j]=(short int)(diff2);					/* Write Buffer */
			j++;

#if _RGM_ADAPTIVE			
			/* calc k */
			if(zero_shift > 2)k2=k2+1;
			if(zero_shift == 0)k2=k2-1;
			if(k2 < min_of_k)k2 = min_of_k;
			if(k2 > max_of_k)k2 = max_of_k;
#endif 
		
		}
		if(j>=AudioBufRow-1){				/* AudioBuf is filled with data? */
			dac_semp = true;
		}
	}
}

  
int main() {

    char s[256];
    char* p;
    
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("I2S Codec:");
    mbed_i2s_init();    //DAC:44100Hz sampling ,16bit ,Stereo ,MCLK Disable, TLV320AIC23B=Master
    if(aic23b_init()==0){
        lcd.locate(12,0);
        lcd.printf("OK");
    }else{
        lcd.locate(12,0);
        lcd.printf("NG");
    }
    Buffer_Init();
    pc.printf("CCLKCFG= %d \r\n",LPC_SC->CCLKCFG);
    pc.printf("I2S Send start.\r\n");
    led1=1;
    lcd.locate(0,1);
    lcd.printf("> Please Wait..."); 
 
    if ( NULL == (playlist = fopen( "/sd/play.txt", "r" )) ) {
        printf( "\r\nError: The Playlist file cannot be accessed\r\n" );
        return -1;
    }


    while(1){
        if((fgets( s, 256, playlist ))==NULL){
            fseek(playlist, 0L, SEEK_SET);
            fgets( s, 256, playlist );
        } 
        p=strchr(s,'\n');
        if(p!=NULL){
            *p='\0';
        
        }                   //remove CR code for Macintosh text-file 
        p=strchr(s,'\r');
        if(p!=NULL){
            *p='\0';
        
        }                   //remove LF code for Linux & Windows text-file  
        printf("\r\n open file:%s \r\n",s); // cut '\n' symbol
        lcd.locate(0,1);
        lcd.printf(">               ");
        s[15]='\0';                           
        lcd.locate(1,1);
        lcd.printf("%s",s);
        if ( NULL == (infp = fopen( s, "r" )) ) {
            printf( "\r\nError: The message file cannot be accessed\r\n" );
            return -1;
        }
            
        fseek(infp, 0L, SEEK_SET);
        tick.attach_us(&dac_out, 181); //set 44.1kHz/8(word FIFO) sampling data
        fl_leds.attach(&pl_led_flash,1);
        
        
        decode();
    
        fclose( infp );
        infp = NULL;    
        tick.detach();
        fl_leds.detach();
                lcd.locate(0,1);
        lcd.printf("> Please Wait...");    
    }
}