#include #include #include #include "i2cmsu.h" #define DATA_EEMEM_PROTECT_DISABLE 0x0100 #define XT_OSC 0x0001 #define DISABLE_DEBUG 0x0800 #define CP0 0x1010 #define CP1 0x2020 /* CP0,CP1 code protect off*/ /* other bits zero which means WDT disabled Low Voltage prm disabled, brownout disabled power up timer enabled */ __CONFIG((CP1 | CP0) | DATA_EEMEM_PROTECT_DISABLE | XT_OSC | DISABLE_DEBUG); #define bitset(var,bitno) ((var) |= (1 << (bitno))) #define bitclr(var,bitno) ((var) &= ~(1 << (bitno))) #define bittst(var,bitno) (var & (1 << (bitno))) // Audio lab // want to sample at roughly 8 Khz rate, or 125 us // // note the use of 'bank1' for some variables - must do this because // bank0 will be used for everything if you don't do this. // the 16F873 only has two banks. #define ROM 0xA0 /* I2C EEPROM */ #define ROMR 0xA1 /* I2C EEPROM */ #define ROMR_HB 0xA9 /* I2C EEPROM, upper block */ #define DAC 0x58 /* I2C DAC 01011000 */ /* return 8 bit char from Recieve port */ char getch () { unsigned char c; /* while (!RCIF) */ while (!bittst(PIR1,5)); /* check RCIF bit */ c = RCREG; return(c); } /* send 8 bit char to Recieve port */ void putch (c) char c; { /* wait until transmit reg empty */ /* while (!TXIF) */ while (!bittst(PIR1,4)); /* check RCIF bit */ TXREG = c; } void pcrlf () { putch(0x0a); putch(0x0d); } // i2c clock freq = Fosc/4(SSPAD+1) // 100000(SSPPAD+1) = 3686400/4 // SSPAD = 8.2, use 8, will be close to 100 Khz bank1 unsigned char bufptr; bank1 unsigned char buf_flag; bank1 unsigned char save_mem; bank1 unsigned char playback; bank1 unsigned char interrupt_flag; bank1 unsigned char *bptr; unsigned char buf_1[64]; bank1 char buf_2[64]; bank1 char tmp; bank1 char adc_value; /* for PRINTF to work, must declare putch, and include BOTH conio.h and stdio.h */ /* service routine for timer 2 interrupt */ void interrupt timer1_isr(void) { // char adc_value; // char tmp; bitclr(PIR1,1); // TMR2IF = 0; clear timer interrupt flag if (save_mem) { //read A/D register, save in buffer adc_value = ADRESH; // two MSBs of 10-bit value tmp = ADRESL; bitset(ADCON0, 2); /* start new conversion */ adc_value = adc_value << 6; //move to upper 2 bits tmp = tmp >> 2; // only keep upper 6 bits tmp = tmp & 0x3F; //mask upper bits adc_value = adc_value | tmp; // form final 8 bit value to save *bptr = adc_value; bufptr++; bptr++; // if (buf_flag) buf_1[bufptr] = adc_value; // else buf_2[bufptr] = adc_value; // bufptr++; if (bufptr == 64) { bufptr = 0; interrupt_flag = 1; buf_flag = ~buf_flag; // flip buf flag if (buf_flag) bptr = &buf_1[0]; else bptr = &buf_2[0]; } } if (playback) { interrupt_flag = 1; } } bank1 unsigned int i; bank1 unsigned int addr; bank1 char inchar; main() { bptr = &buf_2[0]; TRISB = 0x80; /* MSB is input, others output*/ /* configure A/D */ ADCON1 = 0x8E; /* Port A analog input, right justification of result */ TRISA = 0xFF; /* all bits input */ PORTB = 0x00; /* set baud rate */ /* setup Async communication */ bitclr(TXSTA, 6); /* 8-bit transmit */ bitset(TXSTA, 5); /* transmit enable*/ bitclr(TXSTA, 4); /* async mode */ bitset(TXSTA, 2); /* high speed mode */ // high baud rate mode SPBRG = (Fosc/(baud_rate*16)) - 1 SPBRG = 95; /* 9600 in high baud rate mode, crystal = 14.7456 Mhz */ bitset(TRISC, 7); /* serial port enable */ bitset(TRISC, 6); /* serial port enable */ bitset(RCSTA, 7); /* serial port enable */ bitclr(RCSTA, 6); /* 8-bit reception */ /* set baud rate */ bitset(RCSTA, 4); /* enable recieve */ ADCON0 = 0x80; /* sampling freq = Fsoc/32, channel 0 */ bitset(ADCON0,0); /* turn on ADC*/ /* enable I2C */ SSPCON = 0x28; //Master mode // SSPADD = (Fosc/(baud_rate*4)) - 1 SSPADD = 8; // about 400Khz for 14.7456 Mhz, verified to work // bitset(SSPSTAT,7); //disable slew rate control for 100 Khz bitset(SSPCON,5); //SSPEN = 1; bitset(SSPCON,4); //CKP = 1; bitset(TRISC,3); bitset(TRISC,4); // SDA, SCL pins are inputs /* configure timer 2*/ /* post scale of 1 */ bitclr(T2CON, 6); bitclr(T2CON, 5); bitclr(T2CON, 4); bitclr(T2CON, 3); /* pre scale of 16 */ bitset(T2CON, 1); bitclr(T2CON, 0); /* set period register */ /* to get to 8 KHz, you will need to go as far above 400 Khz on the I2C bus as you can, and optimize the playback loop */ #if 0 PR2 = 28; /* 8 Khz */ #endif #if 0 PR2 = 37; /* 6 Khz */ #endif #if 1 PR2 = 57; /* 4 Khz */ #endif #if 0 PR2 = 114; /* 2 Khz */ #endif /* start timer 2 */ bitset(T2CON, 2); pcrlf (); printf("Enter 'r'(record), 'p' (playback), 'c' (calibrate): "); inchar=getch(); if (inchar == 'c') { while(1) { bitset(ADCON0, 2); /* start conversion */ while (bittst(ADCON0,2)); /* wait for end of conversion */ adc_value = ADRESH; // two MSBs of 10-bit value adc_value = adc_value << 6; //move to upper 2 bits tmp = ADRESL; tmp = tmp >> 2; // only keep upper 6 bits tmp = tmp & 0x3F; //mask upper bits adc_value = adc_value | tmp; // form final 8 bit value to save printf("%x",adc_value); pcrlf(); } } if (inchar == 'r') { pcrlf (); printf("Capturing 64K of audio from ADC"); pcrlf (); // enable interrupts save_mem = 1; bitset(ADCON0, 2); /* start new conversion */ bitclr(PIR1,1); // TMR2IF = 0; clear timer interrupt flag bitset(PIE1, 1) ; // enable timer2 interrupt TMR1IE = 1; bitset(INTCON,6); /* enable peripheral interrupts, PEIE */ bitset(INTCON,7); /* enable global interrupts, GIE */ for (i=0; i < 1024; i++) { while (!interrupt_flag); // wait for block write /* do block write */ interrupt_flag = 0; if (buf_flag) block_mem_write(ROM,addr,buf_2); else block_mem_write(ROM,addr,buf_1); addr = addr + 64; putch('*'); } printf("64K Capture complete, hit reset to continue"); pcrlf (); while(1); } if (inchar == 'p') { playback = 1; pcrlf (); printf("Doing Playback"); pcrlf (); /* fill in the playback code!!!! */ /* end of playback code */ while(1); } }