⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phonerec.c

📁 基于AVR制作的电话语音录制系统
💻 C
📖 第 1 页 / 共 5 页
字号:
void inline spi_finish(void);void mmc_command(unsigned char cmd, unsigned long arg);/* ------------------------------ Main Program ---------------------------- */int main(void){    DDRD     |= _BV(PD1);      // UART TX is output    RTS_DDR  |= _BV(RTS_BIT);  // CTS is output    RTS_PORT |= _BV(RTS_BIT);  // We can't accept data right now    /* Set PBD in PORTD to output -- it's the Playback PWM output*/    DDRD  |= _BV(PD4) | _BV(PD7);	/* The whole C port is for input */	DDRC=0;        HOOK_DDR |= _BV(HOOK_BIT); // Hook relay    // Timer 0 Setup -- Used to make the basic 8KHz samping rate used by the    // ADC and most everything else        TCCR0 = _BV(WGM01)  // Enable CTC mode          | 2;          // Enable counter with prescaling=CLK/8    // Set OCR0 initial value for making ADC auto-trigger rate = 8000Hz    // Nearly everything is synchronous with this rate, so we have    // 1382.4 cycles to do all our work. We acheive this non-integral number    // of cycles at the Timer0 compare match interrupt service routine by    // making OCR0=171 every 5 samples or 172 otherwise.    // For sake of timing issues, it is safer to think that we have at most    // 172*8 = 1376 cycles at most to do everything    OCR0   = 172;           // Generate interrupts on compare matches     TIMSK |= _BV(OCIE0);        // Timer 1 Setup -- Used for generating output audio for the phone line        // OC1A disconnect, OC1B clear on upcounting match, set on downcouting    // match; PWM mode = phase and frequency correct with top at OC1A    // (mode 9, here we set just the 2 low bits = 1)    TCCR1A = (0<<COM1A0) | (2<<COM1B0) | (3<<WGM10);    // PWM mode = phase and frequency correct with top at OC1A    // (mode 9, here we set just the 2 upper bits = 2)    // Timer clock = no prescaling    // No input captures    TCCR1B = (2<<WGM12) | (1<<CS10);    /* 500 upcounts + 500 downcounts = 1000 cycles, fits exactly with       the main 8KHz sample rate generated from timer1 */    OCR1A=255;	    // Timer2 setup -- generates output audio for the monitor speaker        TCCR2 = _BV(WGM20) | _BV(WGM21) // Fast PWM          | _BV(COM21) | _BV(COM20) // Set at compare match, clear at bottom          | _BV(CS20);              // enable counter with prescaler = 1        // UART setup -- used for transmitting audio and detected line events    // to the computer; and for receiving commands from the PC    	UCSRC  = 0x80|(3<<UCSZ0);   // Set async 8bit, no parity, 1 stop bit	UCSRB  =  _BV(TXEN)         // Enable transmitter,...	       |  _BV(RXEN)         // receiver,...           |  _BV(RXCIE);       // receiver interrupts,...           //|  _BV(UDRIE);     // and transmit interrupts.	UBRRL  = 5;                 // Set 115200bps with external 11.0592MHz clock	UBRRH  = 0;                 // (this yields 0.00% error)		// ADC Setup -- Gets the actual audio    	// Enable ADC, single conversion, generate interrupt on done    // prescaler=clk/64 (yields ADC clock=172.8KHz, well within the    // recommended 200KHz maximum). Normal conversions take about 832 cycles.    	ADCSRA = _BV(ADEN) | (6<<ADPS0) | _BV(ADIE) | _BV(ADATE); 	ADMUX  = 0 | _BV(ADLAR);    // Use AREF, channel 0, left adjust result    ADMUX |= _BV(REFS0) | _BV(REFS1);  // 2.56V reference    SFIOR  = (SFIOR & 0x1F)|(3<<ADTS0); // Auto Tigger on Timer0 compare match        // Analog Comparator setup -- used to detect whether the phone line is    // in use, idle or disconnected    	SFIOR &= ~_BV(ACME);   // Disable Analog Comparator Mux, AIN1 is neg input    ACSR  &= ~_BV(ACBG);   // Disable Bandgap ref, positive input is from AIN0	ACSR  &= ~_BV(ACD);    // Enable Analog Comparator#ifdef HAVE_MMC    // SPI setup -- used for talking to the MMC/SD card         PORTB |= _BV(PB7);                       // Set SCK hi    DDRB  |= _BV(PB7) | _BV(PB5) | _BV(PB4); // SCK, MOSI and SS are outputs    SPCR  |= _BV(MSTR)                       // Master mode          |  _BV(SPE);                       // Enable SPI    // Sets up the audio and IO buffers to buffer A and B arbitrarily.    // Could just as well be the reverse. Those pointers are exchanged    // at the end of each read/write/playback/record cycle    audio_buf=buffer_a;    io_buf=buffer_b;#endif // HAVE_MMC	fifo_head=fifo_tail=0;            #ifdef HAVE_GOERTZEL    // Sets up the accumulators for the MAC (multiply-and-accumulate) phase    // of Goertzel's algorithm. These pointers are exchanged after each    // block is processed.    d=q1; q=q2;#endif // HAVE_GOERTZEL          // ---------------- Setup port directions  #ifdef HAVE_LCD	    // Set LCD backlight port as output    LCD_BACKLIGHT_DDR |= _BV(LCD_BACKLIGHT_BIT);    // Turn backlight on    LCD_BACKLIGHT_PORT &= ~_BV(LCD_BACKLIGHT_BIT);	lcd_init(LCD_DISP_ON);#endif    has_sample=FALSE;	/* Enable interrupts */    sei();    for (;;) {	    //set_sleep_mode(0);		//sleep_mode();        if (has_sample) {            has_sample=FALSE;            process_sample();        }	}	/* We never return, but we put this here to avoid gcc warnings */    return 0;}#ifdef HAVE_MMCvoid inline do_block_mmc_io(void){    if (mmc_read_state==3) {        if (mmc_ptr_count) {            //dtmf_string[4]='-';            if (spi_has_reply) {                //dtmf_string[4]='+';                *mmc_ptr++=spi_reply;                mmc_ptr_count--;                spi_get_next();            }        } else {            //dtmf_string[1]='O';            mmc_read_state++;            spi_finish();        }    } else if (mmc_write_state==3) {        if (mmc_ptr_count) {            //dtmf_string[10]='+';            SPDR=*mmc_ptr++;            mmc_ptr_count--;        } else {            mmc_write_state++;            spi_buf_putc(0xFF); // First byte of the dummy 16-bit CRC            spi_start_xmit();            spi_autofinish=FALSE;           }     }}void stop_playback(void){    if (mmc_read_cluster)         audio_status |= AS_PLAYBACK_SHUTTING_DOWN;#ifdef ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK    if (has_index & DEFERRED_INDEX_WRITE) {        has_index &= ~DEFERRED_INDEX_WRITE;        mmc_write_index_state=1;    }#endif // ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK}void start_playback(unsigned short from_cluster, unsigned short to_cluster){    if (mmc_read_cluster) {        // We're already playing something -- so all we've got to do is        // to arrange the new places to read        mmc_read_cluster=from_cluster;        mmc_read_stop_at=to_cluster;        mmc_read_cluster_sector=0;    } else {        // We're not playing anything yet#ifdef ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK        if (mmc_write_cluster) {            // Attempt to have combined record&playback... for now, we            // can't start playback if there is already a recording in            // progress            mmc_read_cluster=1;            //dtmf_string[11]='C';        } else #endif // ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK        {            // We should only start playing back if the MMC card has            // been sucessfully initialized in the past at least once            if (!mmc_init_state) {                mmc_read_buf_state=1;                mmc_read_cluster=from_cluster;                mmc_read_stop_at=to_cluster;                //dtmf_string[11]='P';                mmc_init_state=6;                mmc_read_cluster_sector=0;                audio_cnt=0;            }        }    }}void stop_recording(void){    if (audio_status & AS_RECORDING_IN_PROGRESS)        audio_status |=  AS_RECORDING_SHUTTING_DOWN;    xmit(CMD_BLOCK_START);    xmit(CMD_RECORDING_STOPPED);}void start_recording(unsigned short cluster){    if (!mmc_init_state && !mmc_write_cluster) {#ifndef ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK        if (mmc_read_cluster) {            // Attempt to have combined record & playback...            // for now, the two of them won't work together,            // so we stop the playback first            // audio_status |= AS_PLAYBACK_SHUTTING_DOWN;            //dtmf_string[11]='C';        }#endif // ALLOW_SIMULTANEOUS_RECORD_AND_PLAYBACK        if (!cluster) cluster=mmc_index.last_cluster;        mmc_write_cluster=cluster;        mmc_index.start[mmc_index.last_call++]=cluster;        if (mmc_index.last_call==MAXCALLS) mmc_index.last_call=0;        current_playback_call=mmc_index.last_call;        if (mmc_index.last_call==mmc_index.first_call) {            mmc_index.first_call++;            if (mmc_index.first_call==MAXCALLS)                mmc_index.first_call=0;        }        audio_status |=  AS_RECORDING_IN_PROGRESS;        if (!mmc_read_cluster) {           audio_cnt=0;        }        mmc_write_cluster_sector=0;    }    xmit(CMD_BLOCK_START);    xmit(CMD_RECORDING_STARTED);    call_number_already_copied=FALSE;    call_year  = now_year;    call_month = now_month;    call_day   = now_day;    call_hour  = now_hour;    call_min   = now_min;    call_sec   = now_sec;}#endif // HAVE_MMC#define MMC_MANY_IO_BLOCKSvoid process_sample(void){   #ifdef HAVE_MMC#ifdef MMC_MANY_IO_BLOCKS    do_block_mmc_io();#endif // MMC_MANY_IO_BLOCKS#endif // HAVE_MMC    // Tell the computer we can receive data on the serial port    RTS_PORT &= ~_BV(RTS_BIT);        unsigned char pwm=0;    if (has_rx_data()) {        pwm=recv();         if (cmd_cnt>0) {            if (cmd_cnt==1) {                if (pwm==CMD_BLOCK_START) {                    cmd_cnt=0;                } #ifdef HAVE_LCD                else if (pwm==CMD_LCD_BACKLIGHT_ON) {                    cmd_cnt=0;                     // Turn backlight on                    LCD_BACKLIGHT_PORT &= ~_BV(LCD_BACKLIGHT_BIT);                 } else if (pwm==CMD_LCD_BACKLIGHT_OFF) {                    cmd_cnt=0;                     // Turn backlight off                    LCD_BACKLIGHT_PORT |=  _BV(LCD_BACKLIGHT_BIT);                }#endif // HAVE_LCD                else if (pwm==CMD_GO_OFF_HOOK) {                    cmd_cnt=0;                     HOOK_PORT |=  _BV(HOOK_BIT); // Turn on hook relay                } else if (pwm==CMD_GO_ON_HOOK) {                    cmd_cnt=0;                     HOOK_PORT &= ~_BV(HOOK_BIT); // Turn off hook relay                } else if (pwm==CMD_SET_TIME) {                    cmd_cnt++; pending_cmd=pwm;                }            } else if (pending_cmd==CMD_SET_TIME) {                if (cmd_cnt==2) now_hour= pwm;                if (cmd_cnt==3) now_min = pwm;                if (cmd_cnt==4) now_sec = pwm;                cmd_cnt++; if (cmd_cnt==5) cmd_cnt=0;            } else if (pending_cmd==CMD_SET_DATE) {                if (cmd_cnt==2) now_year = pwm;                if (cmd_cnt==3) now_month = pwm;                if (cmd_cnt==4) now_day   = pwm;                cmd_cnt++; if (cmd_cnt==5) cmd_cnt=0;            }            pwm=last_pwm;        } else {            if (pwm==CMD_BLOCK_START) {                cmd_cnt++; pwm=last_pwm;            } else {                age=0;                if (pwm>248) pwm=248;                last_pwm=pwm;            }        }    } else {        if (age>10) {            age=0; pwm=0; last_pwm=0;        } else {            pwm=last_pwm; age++;        }    }    if (wav_cnt) {        pwm=pgm_read_byte(wavp++);        if (!pwm) {            wavp=wavp0;            pwm=pgm_read_byte(wavp++);            if (!--wav_rep) {                wav_rep=wav_rep0;                wav_cnt--;            }        }        if (wav_cnt & wav_mask) pwm=128;    }    OCR1B = pwm;    //OCR2=pwm;    //OCR2 = last_reported_hook==OffHook ? sample8 : 0;    //OCR2=pgm_read_byte(wav440+w440);    //if (++w440==18) w440=0;    #ifdef HAVE_MMC    if (audio_status && !audio_cnt) {        unsigned char *tmp=audio_buf;        audio_buf=io_buf;        io_buf=tmp;        //dtmf_string[9]='*';        if (mmc_read_buf_state) {            //dtmf_string[5]='^';        }        if (mmc_write_cluster) {            //dtmf_string[10]='r';            mmc_init_state=1;            mmc_write_buf_state=1;            if (audio_status & AS_RECORDING_SHUTTING_DOWN) {                if (mmc_write_cluster_sector==15) {                    unsigned char i,*p=io_buf+                        MMC_BLOCK_SIZE-7-MAXDTMFSTRINGLENGTH;                    *p++=1; // Version info                    for (i=0;i<MAXDTMFSTRINGLENGTH+6;i++)                        *p++=call_number[i];                }            }        } else if (mmc_read_cluster) {            //dtmf_string[9]='p';            mmc_read_buf_state=10;            //mmc_init_state=6;        }    }        unsigned char *p=audio_buf+audio_cnt;    if (audio_status & AS_PLAYBACK_IN_PROGRESS) {        OCR2=*p;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -