//**************************************************************** // EASY_MP3_PLAYER_ADD_REC_AND_LCD_24F (Head: EAGLE PCB) // // MPEG Audio Codec LSI: VS1011e(EXT CLK:12.288MHz) // Used Microchip Memory Disk Drive File System:FAT16 // Rec Format: Sample_Rate=22.05k, Sample_Size=16bit, Ch=Mono // // Rec Mode: Sampling AD Input Signal -> Write ADC Value to SD // Play Mode: Read MP3 or WAV to SD -> VS1011e // // Rec/Play SW: Mode Change // Skip SW : Play Next File // // Used Timer1: T1= 22.05k(45.3uS) is ADC Sample Trig // // AD Input: AN1 // // LCD I/F : Transmit Command for RS232C-> Slave CPU LCD Side // // Condition: // 8MHz Internal RC oscillator, 4x PLL (8MHzx4= 32MHz) // Fcy=32MHz/2=16MHz, Tcy=62.5ns // // CPU: PIC24FJ64GA002 // // 2012/1/28: N.Ishii //**************************************************************** /* Addition to Project File */ // Source Files Folder VS1011.c // FSIO.c // SD-SPI.c // easy_mp3_player_add_rec_and_lcd_24f.c // Header Files Folder VS1011.h // GenericTypeDefs.h // FScohfig.h // FSDefs.h // FSIO.h // SD-SPI.h // uart.h // Linker Script Folder p24FJ64GA002.gld #include #include "stdio.h" #include "VS1011.h" #include "GenericTypeDefs.h" #include "FSIO.h" #include "uart.h" // Used Debug #include "timer.h" /// Set Configuration Word 1 _CONFIG1 ( JTAGEN_OFF & // JTAG Port: OFF GCP_OFF & // Code Protect: OFF GWRP_OFF & // Write Protect:OFF BKBUG_OFF & // Background Debug: OFF COE_OFF & // Clip On Emulation: OFF ICS_PGx1 & // Select ICD Pin: EMUC/EMUD-> PGC1/PGD1 For Common Use FWDTEN_OFF // WDT: OFF ) /// Set Configuration Word 2 _CONFIG2 ( IESO_OFF & // 2 Speed Start Up: OFF FNOSC_FRCPLL & // 8MHz Internal RC oscillator, 4x PLL-> 8MHzx4=32MHz // FNOSC_FRC & // Non PLL: 8MHz(Fcy=4MHz) FCKSM_CSDCMD & // Change Clock Control: OFF Clock Monitor: OFF OSCIOFNC_ON & // OSCO/RA3 function: Used RA3 IOL1WAY_OFF & // RP Register Protection: Unlimited Writes To RP Registers I2C1SEL_PRI & // I2C1 pins Select: Use Primary I2C1 pins POSCMOD_NONE // Oscillator Selection: Primary disabled ) /// Used debug: Function Prottypes 110129 void delay_us(int usec); void delay_ms(int msec); //----------------------------------------------------------------------------------- struct myWaveHeader // Header Size:44Byte { char id_RIFF[4]; // Chunk ID RIFF Header: 4Byte unsigned long int size_file; // File Size(Total - 8): 4Byte char id_WAVE[4]; // Chunk ID WAVE: 4Byte char id_fmt[4]; // Chunk ID fmt: 4Byte unsigned long int size_fmt; // Number of Byte fmt Chunk: 4Byte unsigned int code_wavefmt; // Format ID: 2Byte unsigned int channel; // Number of Channel: 2Byte unsigned long int rate_sample; // Sample Rate: 4Byte unsigned long int rate_transfer;// Transfer Rate: 4Byte unsigned int align_block; // Block Size: 2Byte unsigned int bit_sample; // Sample Bit: 2Byte char id_data[4]; // Chunk ID DATA: 4Byte unsigned long int size_data; // Data Size: 4Byte }; // Initialize Wave Header Structer: 44Byte struct myWaveHeader mywaveheader = { "RIFF", // Chunk ID RIFF 0x00000000, // File Size "WAVE", // Chunk ID WAVE "fmt ", // Chunk ID fmt 16, // Number of Byte fmt Chunk: 16Byte-> Linear PCM 0x0001, // Format ID: 1-> Linear PCM 1, // Number of Channel: 1-> MONO 22050, // Sample Rate: 22.05kHz 44100, // Transfer Rate: 44100bps 2, // Block Size: 2-> 1 * 2Byte 16, // Sample Bit: 16bit "data", // Chunk ID data 0x00000000 // Data Size }; struct myWaveHeader *ptrWH; // Pointer of Structure //---------------------------------------------------------------- /// Message Table for RS232C char ModeMSG1[] = "Play Mode "; char ModeMSG2[] = "Recode Mode "; char RecFileName[] = "VOICE.WAV "; //---------------------------------------------------------------- /// RS232C Define #define CR 0x0d #define LF 0x0a #define STX 0x02 //---------------------------------------------------------------- /// SD Define #define SD_CS_ENABLE PORTBbits.RB4 = 0 // CS_pin = 0 #define SD_CS_DISABLE PORTBbits.RB4 = 1 // CS_pin = 1 //---------------------------------------------------------------- /// A Variable of VS1011 BYTE Volume, BASS, ChgFlag; //---------------------------------------------------------------- /// A Variable of FAT16 FSFILE *pfile; // Structure Pointer for FAT File size_t result; BYTE Buffer[256]; SearchRec Record; SearchRec *rptr = &Record; int i; //-------------------------------------------------------------------- /// A Variable of Rec_Play int data1_sound[512]; // Sound Data BUF1(Store ADC Value) int data2_sound[512]; // Sound Data BUF2(Store ADC Value) int count_buf1 = 0; // Number of Data : BUF1 int count_buf2 = 0; // Number of Data : BUF2 int flag_buf1 = 0; // Status of BUF1  int flag_buf2 = 0; // Status of BUF2 // 0: Possible Receive Sound Data // 1: Possible Transmit to SD int Mode = 0; // Rec/Play Mode: 0-> Play / 1-> Rec int Next = 0; int mode_tranceive = 0; // 0: BUF1= Receive Sound Data / BUF2= Transmit to SD // 1: BUF1= Transmit to SD / BUF2= Receive Sound Data int Stop_SDwriting = 0; // 1: Stop Write to SD / 0: Enable Write to SD unsigned long int adr_SD; unsigned long int count_block = 0; unsigned int size_dataBlock = 512; //------------------------------------------------------------------------------------- /// LCD Control (RS232C) void play_mode_LCD(void) { unsigned char i; char *str_filename; str_filename = Record.filename; SRbits.IPL = 7; // Add 110218:Right in the middle of Processing UART is CN Interrupt Disable putcUART1(CR); for (i = 0; i <15; ++i) { WriteUART1(str_filename[i]); while(BusyUART1()); } putcUART1(LF); putsUART1(ModeMSG1); delay_ms(1); putcUART1(STX); SRbits.IPL = 2; // Add 110218: CN Interrupt Enable Again } //---------------------------------------------------------------------------------------------------------- void wav_end(void) { unsigned int result; /// Update Wave Header mywaveheader.size_data = count_block * 1024; mywaveheader.size_file = count_block * 1024 + sizeof mywaveheader - 8; do { delay_ms(100); LATAbits.LATA4 = 0; // Green LED ON result = FSfseek(pfile, 0, SEEK_SET); // Seek from start of file delay_ms(100); LATAbits.LATA4 = 1; // Green LED OFF } while(result != 0); // Loop SEEK_SET unsuccesful // SEEK_SET succesful LATAbits.LATA4 = 0; // Green LED ON delay_ms(1500); do { delay_ms(100); LATAbits.LATA4 = 1; result = FSfwrite((const void*)ptrWH, sizeof(struct myWaveHeader), 1, pfile); // Write WAV Header delay_ms(100); LATAbits.LATA4 = 0; } while(result != 1); // End of Write WAV Header // END Write WAV Header LATAbits.LATA4 = 0; // Green LED ON delay_ms(1500); do { delay_ms(100); LATAbits.LATA4 = 1; result = FSfclose(pfile); // File Close delay_ms(100); LATAbits.LATA4 = 0; } while(result != 0); // Loop Close unsuccesful // Green LED OFF delay_ms(1500); } //------------------------------------------------------------------------------------------------------------------ void play() { int i; ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF); // T1 Stop-> Disable IntT1 DisableIntT1; /// Out of Music Data if (pfile != 0) { // Success File Open ? /* LATAbits.LATA4 = 0; // Green LED ON delay_ms(1000); LATAbits.LATA4 = 1; // Green LED OFF delay_ms(1000); */ // Out of Music Data As Far as EOF of File do{ /* Send of Music Data */ SRbits.IPL = 7; // Right in the middle of Processing SPI is CN Interrupt Disable MP3_XDCS_IO = 0; /// File Read (Unit 256Byte) result = FSfread(Buffer, 1, 256, pfile); // LATAbits.LATA3 = 0; // Red LED ON for( i= 0; i Write to SD (Unit 512Data) count_block++; flag_buf2 = 0; // End of Transmit BUF2 (Receive Sound Data) } } else { // 0: BUF1=Transmit to SD / BUF2= Receive Sound Data if (flag_buf1 == 1) { // BUF1: Possible Transmit to SD (BUF2: Possible Receive Sound Data) FSfwrite((const void*)data1_sound, sizeof(int), size_dataBlock, pfile); // BUF1 -> Write to SD (Unit 512Data) count_block++; flag_buf1 = 0; // End of Transmit BUF1 (Receive Sound Data) } } if (Stop_SDwriting == 1) { delay_ms(200); wav_end(); // Processing End of Rec Mode = 0; // Return to Play Mode delay_ms(1000); pfile = FSfopen("VOICE.WAV", "r"); // Rec File Open // LCD Disp VOICE.WAV + Play Mode(RS232C) putcUART1(CR); putsUART1(RecFileName); delay_ms(1); putcUART1(LF); putsUART1(ModeMSG1); delay_ms(1); putcUART1(STX); } } //-------------------------------------------------------------------------------------------------------------- void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void) // Read ADC: T1 = 45.3uS (22.05k Sample) { unsigned int temp1; long int temp2; IFS0bits.T1IF = 0; // Clead IF Flag // LATAbits.LATA3 = 0; // Red LED ON AD1CON1bits.SAMP =1; // Sampling Start while(!AD1CON1bits.DONE); // Wait EOC temp1 = ADC1BUF0; // temp1 <- ADCBUF0(AN1) temp2 = temp1*64 - 32768; // Convert ADC Value: Real 10bit -> 2's Complement 16Bit (Center Level:0/ Offset = 32768) /// Over Level Clipping if (temp2 >= 32767) temp2 = 32767; if (temp2 <= -32768)temp2 = -32768; /// Have Priority Transmit to SD if (mode_tranceive == 0) { // 0: BUF1= Receive Sound Data / BUF2= Transmit to SD if (flag_buf1 == 0) { // Possible Receive Sound Data BUF1? data1_sound[count_buf1] = temp2; // BUF1<- Receive Sound Data count_buf1++; if (count_buf1 >= size_dataBlock) { // Store 512Data ? count_buf1 = 0; flag_buf1 = 1; // BUF1: Buffer Full (Wait Transmit to SD) mode_tranceive = 1; // Change Duble Buffer ALT Flag } } } else { // BUF1=Transmit to SD / BUF2= Receive Sound Data if (flag_buf2 == 0) { // Possible Receive Sound Data BUF2? data2_sound[count_buf2] = temp2; // BUF2<- Receive Sound Data count_buf2++; if (count_buf2 >= size_dataBlock) { // Store 512Data ? count_buf2 = 0; flag_buf2 = 1; // BUF2: Buffer Full (Wait Transmit to SD) mode_tranceive = 0; // Change Duble Buffer ALT Flag } } } // LATAbits.LATA3 = 1; // Red LED OFF } //----------------------------------------------------------------------------------------------------------- /// Switch Change Notification Interrupts void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) { if (!PORTBbits.RB1) { // Rec/Play SW ON ? if (Mode == 0) {// Play Mode ? Mode = 1; // To Rec Mode Stop_SDwriting = 0; // Enable Write to SD MP3_XDCS_IO = 1; // Disable xDCS Line MP3_XCS_IO = 1; // Disable xCS Line FSfclose(pfile); // Compulsory Close Now File PlayEnd(); // Processing End of Play delay_ms(200); pfile = FSfopen("VOICE.WAV","w"); // File Open Write Mode /// Write WAV Header(Initialize Data) ptrWH = &mywaveheader; // Set Structer Top address FSfseek(pfile, 0, SEEK_SET); // Seek from start of file delay_ms(50); FSfwrite((const void*)ptrWH, sizeof(struct myWaveHeader), 1, pfile); // Write WAV Header delay_ms(50); adr_SD = 0x2C; // 0x2C= Point 44Byte FSfseek(pfile, adr_SD, SEEK_SET); // Seek from Point 44Byte of file(PCM Data Block Area) count_block = 0; // LCD Disp VOICE.WAV + Recode Mode(RS232C)----- putcUART1(CR); putsUART1(RecFileName); delay_ms(1); putcUART1(LF); putsUART1(ModeMSG2); delay_ms(1); putcUART1(STX); //-------------------------------------------- delay_ms(300); ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON); // T1 ON EnableIntT1; // Enable T1 Interrupts } if ((Mode == 1) && (count_block >= 10)) { // Rec Mode + Over 10 Block Write? ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_OFF); // T1 OFF DisableIntT1; // Disable T1 Interrupts LATAbits.LATA3 = 1; // Red LED OFF: 110411 Stop_SDwriting = 1; // After End of Write 1Block, Start Processing Stop_SDwriting } } if (!PORTBbits.RB0) { // SKIP SW ON? Next = 1; // After End of Read File Sector, Play Next File } IFS1bits.CNIF = 0; // Clead CNIF Flag } //---------------------------------------------------------------------------------------------------------------- /// Main routine int main(void) { // CPU Clock Pre Scalere 1:1 CLKDIV = 0; // Set AD1PCFG: ANx Port is All Digital Pin AD1PCFG = 0xFFFF; /// Set LED & SW Port Direction TRISAbits.TRISA3 = 0; // RA3 is RED_LED output used debug TRISAbits.TRISA4 = 0; // RA4 is GREEN_LED output TRISBbits.TRISB0 = 1; // RB0 is SKIP_1Sec_Pulse input TRISBbits.TRISB1 = 1; // RB1 is REC/PLAY_1Sec_Pulse input // Set SD Port Direction TRISBbits.TRISB4 = 0; // RB4 is CS/ output TRISBbits.TRISB8 = 1; // RB8 is CD/ input TRISBbits.TRISB9 = 1; // RB9 is WE/ input // ADC Module OFF AD1CON1bits.ADON=0; /// Initialize ADC AD1PCFG = 0xFFFD; // AD Channel-1 Aanalog Input AD1CHS = 0x0001; // AD Channel-1 Select AD1CSSL = 0x0000; // Scan_None AD1CON3 = 0x1F05; // Acquisition Time=31Tad, 1Tad=3*Tcy AD1CON2 = 0x0000; // Vref=AVdd-AVss, Scan Off, Interrupt Timming=EOC AD1CON1 = 0x00E0; // Module Off, Format Integer, Tad Base Triger, Set SAMP Bits-> Start Sampling // ADC Module ON AD1CON1bits.ADON = 1; /// Inittalize Timer1:T1= Tcy*PS*n= 0.0625uS*1*725 = 45.3uS PR1 = 724; // n = 725 (PR1=n-1) T1CON = 0b1000000000000000; // T1_ON, T1_GATE_OFF, T1_PS_1_1, T1_SOURCE_INT // Set Pull Up // CNPU1 = 0x0000; // Non Pull Up (RB0(SKIP_1Sec_Pulse), RB1(REC/PLAY_1Sec_Pulse) (RB14(DREQ) is EXT 2.2k Pull Up) CNPU1 = 0x1000; // Non Pull Up (RB0(SKIP_1Sec_Pulse), RB1(REC/PLAY_1Sec_Pulse) (RB14(DREQ) is Int Pull Up 120128) CNPU2 = 0x00E1; // Pull Up Port is RB10(SO_VS1101(SI_PIC Side)),RB7(SDI), RB8(CD/), RB9(WE/) /// Set Switch Change Notification Interrupts CNEN1 = 0x0030; // Valid SKIP_1Sec_Pulse, REC/PLAY_1Sec_Pulse IPC4bits.CNIP = 6; // The Order of Priority: CN INT=6, (T1 INT=5) IEC1bits.CNIE = 1; // Enable CN INT /// SPI1 Pin Mapping: SD Side RPINR20bits.SDI1R = 7; // RP7 is SDI1 RPOR3bits.RP6R = 8; // RP6 is SCK1 RPOR2bits.RP5R = 7; // RP5 is SDO1 /// SPI2 Pin Mapping: VS1011e Side RPINR22bits.SDI2R = 10; // RP10 is SDI2 (VS_S0) RPOR6bits.RP12R = 11; // RP12 is SCK2 (VS_SCLK) RPOR5bits.RP11R = 10; // RP11 is SDO2 (VS_SI) //------< Initialize RS232C>-------------------------------------------------- /// Set RX Input Port TRISBbits.TRISB3 = 1; // RB3 is RX input /// UART1 Pin Mapping RPINR18bits.U1RXR = 3; // UART1 RX to RP3 RPOR1bits.RP2R = 3; // UART1 TX to RP2(Function No=3 -> U1TX) /// Initialize UART1: 9600bps, 8Bit, Non Parity, Non Control Flow // U1BRG = 103; // 9600bps@Fcy=16MHz:Value of U1BRG= (16M/16x9600)-1 U1BRG = 51; // 19200bps@Fcy=16MHz:Value of U1BRG= (16M/16x19200)-1 U1MODE = 0b1000100000000000; // UART1 Mode Set: UARTEN,RTSMD= '1' Other Bit= '0' U1STA = 0b0000010000000000; // UART1 Status Set:UTXEN= '1' Other Bit= '0' //----------------------------------------------------------------------------- // Initialize LED & SD LATAbits.LATA3 = 1; // RED_LED OFF LATAbits.LATA4 = 1; // GREEN_LED OFF SD_CS_DISABLE; // CS = 1 /// Initialize VS1011e VS1011_Init(); // Initialize VS1011 Port+ SPI2(CKP=4M)+ SDI_TestMode+ CLK Doubler // Volume = 0x08; // Set Volume = -4[dB] Volume = 0x014; // Set Volume = -10[dB] 120128 SetVolume(Volume, Volume); BASS = 0; // Set Bass Boost = off SetBassBoost(BASS, 15); delay_ms(1000); // Start VS1011e Sine Test // VS1011_SineTest(); // Start Sin_5kHz //--------------------------------------------------------------------- /// Check Mount SD Card and Format SD_CS_ENABLE; // CS = 0 while(FSInit() != 1) // Check Mount SD Card and Format { LATAbits.LATA3 = 0; // Red LED ON delay_ms(1000); LATAbits.LATA3 = 1; // Red LED OFF delay_ms(1000); } // SD Mount LATAbits.LATA4 = 0; // Green LED ON delay_ms(1000); LATAbits.LATA4 = 1; // Green LED OFF delay_ms(1000); // First File Search (A Precondition: Loute Only Be MP3 File) result = FindFirst("*.*", ATTR_ARCHIVE, rptr); if (result == 0) { pfile = FSfopen(Record.filename, "r"); // File Open (Read Mode) } // LCD Disp. (RS232C) play_mode_LCD(); /* LATAbits.LATA4 = 0; // Green LED ON delay_ms(1000); LATAbits.LATA4 = 1; // Green LED OFF delay_ms(1000); */ Mode = 0; //------------------------------------------------------------------------------------- /// main loop while(1) { if (Mode == 0) { // LATAbits.LATA3 = 1; // Red LED OFF LATAbits.LATA4 = 0; // Green LED ON play(); // Play Mode } else { LATAbits.LATA4 = 1; // Green LED OFF LATAbits.LATA3 = 0; // Red LED ON SD_write(); // Rec Mode } } }