📄 phonerec.c
字号:
//dtmf_string[9]='$'; } else { //dtmf_string[9]=' ';#endif // HAVE_MMC if (monitor_mode) { OCR2=(monitor_mode==2 || last_reported_hook==OffHook)?sample8:0; } else { OCR2=0; } #ifdef HAVE_MMC } if (audio_status & AS_RECORDING_IN_PROGRESS) { *p=sample8; } if (audio_status) { audio_cnt++; audio_cnt&=(MMC_BLOCK_SIZE-1); }#endif // HAVE_MMC unsigned char out=sample8; // ADPCM compression and on-hook/off-hook/disconnect logic // We are actually working with the previous sample; we run while the ADC // is busy converting, since it takes 832 cycles perform a conversion // (adc clock=64 main clock cycles * 13 adc clocks = 832 cycles). // Remember that we get here every 1000 cycles (8MHz/8KHz sampling rate)#ifdef USE_ADPCM_COMPRESSION#ifdef ADPCM_USES_LONGS unsigned char sign; /* Current adpcm sign bit */ unsigned char delta; /* Current adpcm output value */ long step; /* Stepsize */ long diff; /* Difference between val and valprev */ long vpdiff; /* Current change to valpred */#else // ADPCM_USES_LONGS unsigned char sign; /* Current adpcm sign bit */ unsigned char delta; /* Current adpcm output value */ short step; /* Stepsize */ short diff; /* Difference between val and valprev */ short vpdiff; /* Current change to valpred */#endif // ADPCM_USES_LONGS#endif // USE_ADPCM_COMPRESSION enum hook_status_t hook=HookUnknown; // if (in>=126 && in<=130) val=128; // Transmit only if off-hook // if (!(ACSR & _BV(ACO))) xmit(val);#ifdef USE_ADPCM_COMPRESSION#ifdef USE_PROGMEM_CONSTANTS step = pgm_read_word(stepsizeTable+idx);#else step = stepsizeTable[idx];#endif diff = sample16 - inpred; sign = (diff < 0) ? 8 : 0; if ( sign ) diff = (-diff); /* Step 2 - Divide and clamp */ /* Note: ** This code *approximately* computes: ** delta = diff*4/step; ** vpdiff = (delta+0.5)*step/4; ** but in shift step bits are dropped. The net result of this is ** that even if you have fast mul/div hardware you cannot put it to ** good use since the fixup would be too expensive. */ delta = 0; vpdiff = (step >> 3); if ( diff >= step ) { delta = 4; diff -= step; vpdiff += step; } step >>= 1; if ( diff >= step ) { delta |= 2; diff -= step; vpdiff += step; } step >>= 1; if ( diff >= step ) { delta |= 1; vpdiff += step; }#ifdef ADPCM_USES_LONGS /* Step 3 - Update previous value */ if ( sign ) inpred -= vpdiff; else inpred += vpdiff; /* Step 4 - Clamp previous value to 16 bits */ if ( inpred > 32767 ) inpred = 32767; else if ( inpred < -32768 ) inpred = -32768;#else /* Step 3 - Update previous value */ if (sign) { if (vpdiff>0 && inpred<vpdiff-32767) inpred=-32768; else inpred-=vpdiff; } else { if (vpdiff>0 && inpred>32767-vpdiff) inpred=32767; else inpred+=vpdiff; }#endif // ADPCM_USES_LONGS /* Step 5 - Assemble value, update index and step values */ delta |= sign;#ifdef USE_PROGMEM_CONSTANTS idx += (char)pgm_read_byte(indexTable+delta); #else idx += indexTable[delta];#endif if ( idx < 0 ) idx = 0; if ( idx > 88 ) idx = 88; /* Step 6 - Output value */ if (pending & 128) { out = (pending<<4)|delta; pending=0; if (!--count) { count=AUDIO_BLOCK_LENGTH; xmit(CMD_BLOCK_START); xmit(CMD_ADPCM_STATE); xmit_short(inpred); xmit(idx); /* On-hook/Off-hook/Disconnected detection logic & debounce */ if (ACSR & _BV(ACO)) { hook=Disconnected; } else { if (PINB & _BV(PB3)) { hook=OnHook; } else { hook=OffHook; } } if (inverts<0) inverts++; if (ring_age>0) { if (ring_age<255) ring_age--; } else { ring_age=255; call_timer_stop(); call_status=CallIdle; stop_recording(); ring_count=0; } if (hook != last_hook) { steady=0; last_hook=hook; if (inverts>=0) { inverts++; if (inverts==4) { lcd_home(); ring_count++; if (ring_count==1) { if (call_status!=CallIncoming) { call_timer_reset(); call_status=CallIncoming; start_recording(0); } } inverts=-70; ring_age=250; } } } else { if (steady==STEADY_COUNT) { if (inverts>0) inverts=0; if (last_reported_hook!=hook) { xmit(CMD_BLOCK_START); xmit(hook); steady=0; last_reported_hook=hook; if (hook==OffHook) { if (call_status==CallIdle) { call_timer_reset(); call_status=CallOutgoing; dtmf_string_clear(); dialing_digits=TRUE; digit_age=0; start_recording(0); } } if (hook==OnHook) { call_timer_stop(); call_status=CallIdle; stop_recording(); ring_count=0; dtmf_string_clear(); } } } else { steady++; } } } if (out==CMD_BLOCK_START) xmit(out); xmit(out); } else { pending = (delta&15)|128; }#else // USE_ADPCM_COMPRESSION#ifdef HAVE_MMC spi_next_xmit();#endif // HAVE_MMC //unsigned char ringdet=PINB & _BV(PB3); if (!ringdet_quell) { unsigned char ringdet=2; if (sample8>250) ringdet=1; if (sample8<5) ringdet=0; if (ringdet==1) { ringdet_mids=0; if (last_ringdet) { ringdet_his++; } else { ringdet_his=0; if (ringdet_los>=60 || ringdet_los<=140) { ringlike++; } else { ringlike--; } } } else if (ringdet==0) { ringdet_mids=0; if (last_ringdet) { ringdet_los=0; if (ringdet_his>=60 || ringdet_his<=140) { ringlike++; } else { ringlike--; } } else { ringdet_los++; } } else { ringdet_mids++; if (ringdet_mids>100) ringdet_his=ringdet_los=ringlike=0; } last_ringdet=ringdet; } if (!--count) { count=AUDIO_BLOCK_LENGTH;#define DO_HOOK_LOGIC#ifdef DO_HOOK_LOGIC /* On-hook/Off-hook/Disconnected detection logic & debounce */ if (ACSR & _BV(ACO)) { hook=Disconnected; } else { if (PINB & _BV(PB3)) { hook=OnHook; } else { hook=OffHook; } } if (hook != last_hook) { steady=0; last_hook=hook; } else { if (steady==STEADY_COUNT) { if (last_reported_hook!=hook) { xmit(CMD_BLOCK_START); xmit(hook); steady=0; last_reported_hook=hook; if (hook==OffHook) { if (call_status==CallIdle) { call_timer_reset(); call_status=CallOutgoing; dtmf_string_clear(); dialing_digits=TRUE;#ifdef HAVE_LCD digit_age=0;#endif // HAVE_LCD#ifdef HAVE_MMC start_recording(0);#endif // HAVE_MMC } else if (call_status==CallIncoming) { ring_age=255; } } else if (hook==OnHook) { call_timer_stop(); call_status=CallIdle;#ifdef HAVE_MMC stop_recording();#endif // HAVE_MMC dtmf_string_clear(); ring_age=255; } } } else { steady++; } }#endif // DO_HOOK_LOGIC xmit(CMD_BLOCK_START); xmit(CMD_RAW_BLOCK); } //out=TCNT0; //if (out==CMD_BLOCK_START) xmit(out); //xmit(out);#endif // USE_ADPCM_COMPRESSION do_xmit();#ifdef HAVE_MMC#ifdef MMC_MANY_IO_BLOCKS spi_next_xmit(); ////////////// --- THIS /* MMC/SD read/write block 2 */ do_block_mmc_io();#endif // MMC_MANY_IO_BLOCKS#endif // HAVE_MMC// -- Goertzel algorithm for DTMF, ring and dial/ring/busy tone detection#ifdef HAVE_GOERTZEL //unsigned char n; //for (n=0;n<3;n++) { // unsigned char one=n<<1; // unsigned char two=one+1; // coef=pgm_read_word(gcos+n); // short y=((d[one]*coef)>>8)-d[two]+sample8; // d[two]=d[one]; d[one]=y; //} asm("lds r30,(%0)+1 \n\t" "eor r31,r31 \n\t" "sbrc r30,7 \n\t" "com r31 \n\t": : "m"(sample16) : "r30","r31"); // Saves r1, which is clobbered by goertzel_inner asm("push r1\n\t"); // Gets Y pointing to 'd' asm("lds r28,%0 \n\t" "lds r29,(%0)+1 \n\t" : : "m" (d) : "r28", "r29"); goertzel_inner_16(GCOS0440); goertzel_inner_16(GCOS0697); goertzel_inner_16(GCOS0770); goertzel_inner_16(GCOS0852); goertzel_inner_16(GCOS0941); goertzel_inner_16(GCOS1209); goertzel_inner_00(GCOS1336); goertzel_inner_08(GCOS1477); goertzel_inner_08(GCOS1633); do_xmit(); // Restores r1 asm("pop r1\n\t");#ifdef HAVE_MMC spi_next_xmit();#ifdef MMC_MANY_IO_BLOCKS /* MMC/SD read/write block 2 */ do_block_mmc_io();#endif // MMC_MANY_IO_BLOCKS#endif // HAVE_MMC //y=((d[ 2]*0x1E3)>>8)-d[ 3]+c; d[ 3]=d[ 2]; d[ 2]=y; //y=((d[ 2]*0x1E3L)>>8)-d[ 3]+c; d[ 3]=d[ 2]; d[ 2]=y; //y=((d[ 4]*0x1B4L)>>8)-d[ 5]+c; d[ 5]=d[ 4]; d[ 4]=y; //y=((d[ 6]*0x1A3L)>>8)-d[ 7]+c; d[ 7]=d[ 6]; d[ 6]=y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -