You are on page 1of 5

C:\Users\Zdenko Pavic\AppData\Local\Temp\Rar$DI97.928\EasyMP3.c /* * Project name: EasyMP3 * Copyright: (c) Mikroelektronika, 2009.

* Revision History: 20071210 : - initial release; 20101025 (FJ) : - adapted for PRO compilers; - fixed comments; * Description: This project demonstrates communication with VS1011E mp3 codec. Program reads one mp3 file from MMC and sends it to VS1011E for decoding and playing. MMC and MP3_SCI share Hardware SPI module. MP3_SDI uses Software SPI communicaton. Program progress can be monitored on UART. Buttons RB7..RB4 are used for Left/Right Down/Up Volume control. * Test configuration: MCU: PIC18F87J60 http://ww1.microchip.com/downloads/en/DeviceDoc/39762d.pdf Dev.Board: LV18F v6 http://www.mikroe.com/eng/products/view/303/lv18f-v6-development-system/ Oscillator: HS, 25.0000 MHz Ext. Modules: EasyMP3 Board - ac:EasyMP3 http://www.mikroe.com/eng/products/view/164/easymp3-board/ MMC/SD Board - ac:MMC http://www.mikroe.com/eng/products/view/138/mmc-sd-board/ SmartADAPT MINI Board - ac:SmartADAPT http://www.mikroe.com/eng/products/view/156/smartadapt-mini-board/ EasyTEST board - ac:EasyTEST http://www.mikroe.com/eng/products/view/183/easytest-board/ Wire Jumpers - ac:WireJumpers http://www.mikroe.com/eng/products/view/495/wire-jumpers/ SW: mikroC PRO for PIC http://www.mikroe.com/eng/products/view/7/mikroc-pro-for-pic/ * NOTES: - Make sure that MMC card is properly formatted (to FAT16 or just FAT) before testing it on this example. - Make sure that MMC card contains appropriate mp3 file. - Turn ON switches for RS232B at SW12 (SW12.5 and SW12.6) on LV24-33 v6 board - Put EasyTEST Board on PORTC. - EasyMP3 Board connections: MP3_CS - RC1 DREQ - RE0 MP3_RST - RC2 BSYNC - RE1 SCK - RC3 DCLK - RE2 MISO - RC4 SDATA - RE3 MOSI - RC5 - Use wire jumpers to connect EasyMP3 Board to EasyTEST Board. - MMC/SD Board connections: MMC_CS - RC6 SCK - RC3 MISO - RC4 MOSI - RC5 - Use SmartADAPT MINI Board to connect MMC/SD Board to EasyTEST Board. - Set voltage level jumpers on EasyMP3 board into 3.3V position. - Pull-down PORTB resistors and set Button jumper to Vcc position. */ #include <built_in.h> // Buttons for Left/Right Volume control sbit BtnLeftDown at RB7_bit; sbit BtnLeftUp at RB6_bit; sbit BtnRightDown at RB5_bit; sbit BtnRightUp at RB4_bit; sbit BtnLeftDown_Direction at TRISB7_bit; sbit BtnLeftUp_Direction at TRISB6_bit; sbit BtnRightDown_Direction at TRISB5_bit; sbit BtnRightUp_Direction at TRISB4_bit; // EasyMP3 Board connections sbit MP3_CS sbit MP3_RST sbit DREQ sbit BSYNC sbit DCLK sbit SDATA sbit MP3_CS_Direction sbit MP3_RST_Direction sbit DREQ_Direction

at at at at at at at at at

RC1_bit; RC2_bit; RE0_bit; RE1_bit; LATE2_bit; RE3_bit; TRISC1_bit; TRISC2_bit; TRISE0_bit; 1

C:\Users\Zdenko Pavic\AppData\Local\Temp\Rar$DI97.928\EasyMP3.c sbit BSYNC_Direction at TRISE1_bit; sbit DCLK_Direction at TRISE2_bit; sbit SDATA_Direction at TRISE3_bit; // MMC/SD Board connections sbit Mmc_Chip_Select at LATC6_bit; sbit Mmc_Chip_Select_Direction at TRISC6_bit; // VS1011E const char const char const char const char const char constants WRITE_CODE READ_CODE MODE_ADDR CLOCKF_ADDR VOL_ADDR

= = = = =

0x02; 0x03; 0x00; 0x03; 0x0B;

// global variables filename[14] = "sound1.mp3"; char unsigned long i, file_size; char data_buffer_32[32]; const BUFFER_SIZE = 2048; char BufferLarge[BUFFER_SIZE]; char volume_left, volume_right; // Write text and goto new line CR and LF void UART2_Write_Line (char *text) { UART2_Write_Text(text); UART2_Write(13); UART2_Write(10); } // Writes one byte to MP3 SDI void SW_SPI_Write(char data_) { BSYNC = 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; BSYNC = 0; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; SDATA = data_; DCLK = 1; data_ >>= 1; DCLK = 0; }

// MP3 file name

// Set BSYNC before sending the first bit

// bitorder is LSB first

// Clear BSYNC after sending the second bit

// Writes one word to MP3 SCI void MP3_SCI_Write(char address, unsigned int data_in) { 2

C:\Users\Zdenko Pavic\AppData\Local\Temp\Rar$DI97.928\EasyMP3.c MP3_CS = 0; // select MP3 SCI SPI1_Write(WRITE_CODE); SPI1_Write(address); SPI1_Write(Hi(data_in)); // high byte SPI1_Write(Lo(data_in)); // low byte MP3_CS = 1; // deselect MP3 SCI while (DREQ == 0); // wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI } // Reads words_count words from MP3 SCI void MP3_SCI_Read(char start_address, char words_count, unsigned int *data_buffer) { unsigned int temp; MP3_CS = 0; SPI1_Write(READ_CODE); SPI1_Write(start_address); while (words_count--) { temp = SPI1_Read(0); temp <<= 8; temp += SPI1_Read(0); *(data_buffer++) = temp; } MP3_CS = 1; while (DREQ == 0); Protocol for SCI } // Write one byte to MP3 SDI void MP3_SDI_Write(char data_) { while (DREQ == 0); Protocol for SCI SW_SPI_Write(data_); } // Write 32 bytes to MP3 SDI void MP3_SDI_Write_32(char *data_) { char i; while (DREQ == 0); Protocol for SCI for (i=0; i<32; i++) SW_SPI_Write(data_[i]); } // Set clock void Set_Clock(unsigned int clock_khz, char doubler) { clock_khz /= 2; // calculate value if (doubler) { clock_khz |= 0x8000; } MP3_SCI_Write(CLOCKF_ADDR, clock_khz); // Write value to CLOCKF register } // Set volume void Set_Volume(char left,char right) { unsigned int volume; volume = (left<<8) + right; MP3_SCI_Write(VOL_ADDR, volume); } // If volume Buttons are pressed update volume void Check_Volume() { char old_volume_left, old_volume_right; old_volume_left = volume_left; old_volume_right = volume_right; if (BtnLeftDown) { if (volume_left < 255) { volume_left++; } } if (BtnLeftUp) { if (volume_left > 0) { volume_left--; } // save volume values // calculate value // Write value to VOL register // wait until DREQ becomes 1, see MP3 codec datasheet, Serial // select MP3 SCI

// read words_count words byte per byte

// deselect MP3 SCI // wait until DREQ becomes 1, see MP3 codec datasheet, Serial

// wait until DREQ becomes 1, see MP3 codec datasheet, Serial

// RB7 pressed = LEFT VOLUME DOWN command

// RB6 pressed = LEFT VOLUME UP command

C:\Users\Zdenko Pavic\AppData\Local\Temp\Rar$DI97.928\EasyMP3.c } if (BtnRightDown) { // RB5 pressed = RIGHT VOLUME DOWN command if (volume_right < 255) { volume_right++; } } if (BtnRightUp) { // RB4 pressed = RIGHT VOLUME UP command if (volume_right > 0) { volume_right--; } } // if volume values are changed, set volume to new values if ( (volume_left != old_volume_left) || (volume_right != old_volume_right) ) { Set_Volume(volume_left,volume_right); } } // Software Reset void Soft_Reset(char fill_zeros) { char i; MP3_SCI_Write(MODE_ADDR,0x0204); Delay_us(2); while (DREQ == 0); Protocol for SCI if (fill_zeros) { for (i=0; i<32; i++) { data_buffer_32[i] = 0; } for (i=0; i < 2048/32; i++) { MP3_SDI_Write_32(data_buffer_32); } } else MP3_SDI_Write(0); } // Initialize VS1011E void MP3_init() { Soft_Reset(0); Set_Clock(25000,0); volume_left = 50; volume_right = 50; Set_Volume(volume_left,volume_right); } void Init() { ADCON1 |= 0x0F; CMCON |= 7; BtnLeftDown_Direction BtnLeftUp_Direction BtnRightDown_Direction BtnRightUp_Direction BtnLeftDown = 0; BtnLeftUp = 0; BtnRightDown = 0; BtnRightUp = 0; DCLK_Direction = 0; SDATA_Direction = 0; DCLK = 0; SDATA = 0; MP3_CS_Direction MP3_CS MP3_RST_Direction MP3_RST = = = = 0; 1; 0; 1; = = = = 1; 1; 1; 1; // Write to MODE register // set SM_RESET bit and SM_BITORD bit(bitorder is LSB first) // Required, see MP3 codec datasheet -> Software Reset // wait until DREQ becomes 1, see MP3 codec datasheet, Serial

// feed 2048 zeros to the MP3 SDI bus: // clear 32byte buffer

// use 32byte buffer to clear MP3 buffer

// write zero once

// SW Reset, do not feed zeros // Set clock to 25MHz, do not use clock doubler // Set volume to initial value

// Configure AN pins as digital // Disable comparators // set pin direction as input

// set pin value to zero

// Set SW SPI pin directions to output // Clear SW SPI SCK // Clear SW SPI SDO // // // // Configure MP3_CS as output Deselect MP3_CS Configure MP3_RST as output Set MP3_RST pin

DREQ_Direction = 1; BSYNC_Direction = 0; BSYNC = 0; } // main void main() {

// Configure DREQ as input // Configure BSYNC as output // Clear BSYNC

C:\Users\Zdenko Pavic\AppData\Local\Temp\Rar$DI97.928\EasyMP3.c Init(); // Initialize USART for signaling UART2_Init(9600); Delay_100ms(); UART2_Write_Line("Initializing SPI"); SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH) ; UART2_Write_Line("Initializing VS1011E decoder interface"); MP3_init(); UART2_Write_Line("Initializing MMC_FAT"); if (Mmc_Fat_Init() == 0) { if (Mmc_Fat_Assign(&filename, 0) ) { // reinitialize SPI1 at higher speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); UART2_Write_Line("File Assigned"); Mmc_Fat_Reset(&file_size); // Call Reset before file reading, // procedure returns size of the file // send file blocks to MP3 SDI while (file_size > BUFFER_SIZE) { for (i=0; i<BUFFER_SIZE; i++) { Mmc_Fat_Read(BufferLarge + i); } for (i=0; i<BUFFER_SIZE/32; i++) { MP3_SDI_Write_32(BufferLarge + i*32); } file_size -= BUFFER_SIZE; Check_Volume(); } // send the rest of the file to MP3 SDI for (i=0; i<file_size; i++) { Mmc_Fat_Read(BufferLarge + i); } for (i=0; i<file_size; i++) { MP3_SDI_Write(BufferLarge[i]); } } else { UART2_Write_Line("File not assigned"); } } else { UART2_Write_Line("MMC FAT not initialized"); } }

You might also like