?? voice.c
字號:
/* * "Voice" support for ltmodem * * Actually, as long as we don't want to use onboard DSP, * this is going to be used not only for voice but for * _everything_. * * Copyright 1999 Pavel Machek * Copyright 1999 Jamie Lokier * Copyright 1999 R.J.M. Close * * Can be distributed under GPL */#include "voice.h"// Voice specific initialisation stuff.void voice_init(void){ int i; dp_spk_volume = 0x8ab8; io_voice_count = 0; io_voice_count_rx= 0; S_synthetic_ring_volume = 0x0a; dp_sleep = 0; //x68229 = 0x81; dp_vt_cntrl = 0; //x6822a = 1; // hmm, setting to 1 basically crashes modem // Initialise io_dce_tx_buff array. for ( i=0; i < 32; i = (i + 4)) { io_dce_tx_buff[i] = 0; io_dce_tx_buff[i + 1] = 50; io_dce_tx_buff[i + 2] = 100; io_dce_tx_buff[i + 3] = 50; }}// ** Stuff robbed from jamie.cint voice_transmit(int fd_to_exit){ struct timeval tv_timeout; int retval; fd_set rfds; PRINTF( "Starting tad: " ); dp_start_tad(0x80); /* d0, b0, 90 looks nice but does not work! */ /* 0x80 seems to work */ x_modem_state = 0xc; dp_state = 0x28; PRINTF( "ok\n" ); fcntl(0, F_SETFL, O_NONBLOCK); fprintf( stderr, "+Fullduplex transmit/receive started\n" ); while(1) { io_voice_count_rx = 0; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(0, &rfds); if (fd_to_exit > 0) FD_SET(fd_to_exit, &rfds); tv_timeout.tv_sec = 0; tv_timeout.tv_usec = 20; retval = select(4, &rfds, NULL, NULL, &tv_timeout); /* Don't rely on the value of tv now! */ if (FD_ISSET(0, &rfds)) { int res; res = read(0, io_dce_tx_sptr, 0x100 - io_voice_count); io_voice_count += res; while (!dp_dualport_vc_Tx()) { usleep(1); } } if (fd_to_exit > 0 && FD_ISSET(fd_to_exit, &rfds)) { PRINTF( "Exiting fullduplex mode\n" ); return 0; } if (dp_dualport_vc_Rc()) if (write(1, io_dce_rx_sptr, 0x100)!=0x100) { PRINTF("Could not write on stdout\n" ); }#if TRY_INTERRUPTS PRINTF("voice_transmit: dp_dsp_isr is disabled!\n");#else dp_dsp_isr();#endif }}int dp_dualport_vc_Rc(void){ int cnt, ebx, al; char *ebp; int readreg = 0; /* 0x10(%esp,1) */ if (io_voice_count_rx != 0) return 0; cnt = dp_read_dsp_ram(0xe7); if (0x100 > cnt) { if (LT_DEBUG) PRINTF( "Rc count too low: %x\n", cnt ); return 0; } ebp = io_dce_rx_sptr;#if 0 if (0x100 >= io_voice_count_rx) { io_voice_count = 0; return 0; }#endif do { if (dp_regread(0xb0)) { readreg = 0x90; do { al = dp_regread(readreg); // PRINTF( "%x", al ); *ebp++ = al; readreg++; } while (readreg <= 0x9f); io_voice_count_rx += 0x10; } dp_regread(0xb0); ebx = x_current_time(); while(1) { if (dp_regread(0xb7) & 0x10) break; if (x_elapsed_time(ebx) > 0x32) { PRINTF( "Timeout receiving\n" ); io_voice_count = 0; return 0; } } } while (0x100 > io_voice_count_rx); return 1;}int dp_dualport_vc_Tx(void){ int writereg, esi, ebx, al; char *edi; if (io_voice_count != 0x100) { // PRINTF( "io_voice_count != 0x100 (%x)\n", io_voice_count ); return 1; } if ((0x100 > (esi = dp_read_dsp_ram(0xe1)))) { if (LT_DEBUG) PRINTF( "read_dsp_ram(0xe1) returned less than 0x100 (%x)\n", esi ); return 0; } edi = io_dce_tx_sptr; if (0 != io_voice_count) { do { writereg = 0x80; /* -4(%ebp) */ do { al = *edi++; dp_regwrite(writereg++, al); } while (0x8f >= writereg); dp_regwrite(0xb0, 0x10); io_voice_count -= 0x10; ebx = x_current_time(); while (1) { if (dp_regread(0xb7) & 1) break; if (x_elapsed_time(ebx) >= 0x32) { PRINTF( "Timeout while sending :-(\n" ); io_voice_count = 0; return 0; } } } while (io_voice_count != 0); } return 1;}voiddp_download_fdsp(void){ dp_modem_command(0x13, 0, 0); //printf( "Size of wDspFdsp is %x, should be %x\n", sizeof(wDspFdsp), 0xcb9*2); dp_download_dsp(wDspFdsp, 0xcb9);}voiddp_init_fdsp(void){ dp_write_dsp_ram(0x86, 0); dp_write_dsp_ram(0x880, 0x9a54); dp_write_dsp_ram(0x86c, 0x20); dp_write_dsp_ram(0x86e, 0xfff8);}voiddp_mute_fdsp(int arg){ printf( "dp_mute_fdsp: %d\n", arg ); if (arg != 0) dp_write_dsp_ram(0x885, dp_spk_volume /* ??? 0x6821c */); else dp_write_dsp_ram(0x885, 0);}voiddp_stop_fdsp(void){ dp_modem_command(0x13, 0, 0); x_output(0x18); dp_modem_command(0x27, 1, 0); dp_set_mercury_gain(); // if (something) // dp_stop_fdsp(); // else v8bis_init();}voiddp_fdsp_record_start(void){ // movb $0x01,0x67d32 dp_write_dsp_ram(0x871, dp_read_dsp_ram(0x871) | 0x02);}/* Strange, dp_start_spkphone is always called with 0 as argument ? */voiddp_start_spkphone(int arg){ // dp_change_mercury_gain(...); dp_write_dsp_ram(0x86, 0); dp_modem_command(0x13, 0, 0); dp_download_fdsp();#if 0 /* It seems to hangup. I do not want to hangup! */ printf( "X_output: 0x07\n" ); x_output(0x07); printf( "X_output: 0x17\n" ); x_output(0x17);#endif dp_write_dsp_ram(0x800, 0x1c); if (arg) { // dp_apollo_command(....); // dp_init_hdsp(); die( "must not happen\n" ); } else { // dp_apollo_command(....); dp_init_fdsp(); } printf( "Write volume\n" ); dp_write_dsp_ram(0x885, dp_spk_volume ); dp_write_dsp_ram(0x724, 0x400); printf( "Done\n" );}voiddp_init_hdsp(void){ dp_write_dsp_ram(0x8e6, 0x21); dp_write_dsp_ram(0x86e, 0xfffd); dp_write_dsp_ram(0x87b, 0x8100); dp_write_dsp_ram(0x87e, 0x800); dp_write_dsp_ram(0x724, 0x400); dp_write_dsp_ram(0x87f, 0x1000); dp_write_dsp_ram(0x723, 0x08); dp_write_dsp_ram(0x880, 0x4000); dp_write_dsp_ram(0x747, 0x14); dp_write_dsp_ram(0x86c, 0x20); // if (byte_68255) dp_write_dsp_ram(0x710, 0x4000);}voiddp_start_hdsp(void){ dp_start_spkphone(0); dp_write_dsp_ram(0x85, 0x905); dp_write_dsp_ram(0x85, 0x9205); // dp_set_speakerphone_gain(); dp_write_dsp_ram(0x725, 0xb6a);}voiddp_switch_fdsp(void){ dp_write_dsp_ram(0x97, 0); dp_init_fdsp(); dp_write_dsp_ram(0x85, 0x9f05); dp_write_dsp_ram(0x871, 0xc004); // dp_set_speakerphone_gain(); if (0x67d32 != 1) dp_fdsp_record_start();}/* * Ouch, speakerphone is _not_ what is interesting for us. * TAD mode (telephone answering device) IS! */voiddp_download_tad(void){ dp_download_dsp(wDspTad, 0x949); dp_modem_command(0x13, 0, 0);}voiddp_detect_dtmf(void){ /* This is actually pretty long function */ dp_write_dsp_ram(0x37, 0x50 /* dp_set_threshold() */ ); // dp_set_iirs(); dp_write_dsp_ram(0x27, 0); dp_write_dsp_ram(0x28, 0); dp_write_dsp_ram(0x26, 0x1e); if (0) { dp_write_dsp_ram(0x26, 0x2f); } if (0) { //dp_write_dsp_array(0x1c, 0x15e28, 0xa); /* ... */ } else { //dp_write_dsp_array(0x1c, 0x15e40, 0xa); dp_write_dsp_ram(0x24, 0x2a49); dp_write_dsp_ram(0xfc0, 0x28d5); } dp_modem_command(8, 0x0b, 0); /* ... = */ x_current_time(); x_current_time(); x_current_time(); /* ... */}voiddp_start_tad(int arg){ //int vsm2 = 0, var_30 = 0; int var_minus4 = 0; //int vsm; // Sampling mode, as set by AT+VSM int al; printf( "Starting dp_start_tad\n" ); if (dp_sleep == 1) dp_init_modem(); dp_modem_command(0x13, 0, 0); dp_vt_cntrl = arg; /* Strange: uninitialized! */ x_sleep(0x32); if (dp_tad_downloaded == 0) { x_output(0x07); /* Basically hangup */ dp_modem_command(0x13, 0, 0); dp_download_tad(); dp_vsp = 0; x_output(0x17); } dp_monitor_hec = 0; dp_dialtone_enable = 1; if (0 == x_dma_xfer && dp_vt_cntrl) { /* Hmm, if I do if (0), I basically crash the modem */ dp_write_dsp_ram(0x3d, 0x200); dp_regwrite(0xb6, 0xff); dp_regread(0xb0); dp_regread(0xb0); al = dp_vt_cntrl; } /* 38aa0: */ /* ecx = sampling mode, from 68229. 0x84 == ADPCM, confirmed now. 0x81 is 16-bit linear, which should be closest to native. ecx -= 0x80 */ switch (S (0x49)) { case 0x80: arg |= 0x0e; break; case 0x82: arg |= 0x09; break; case 0x81: case 0x83: break; default: arg |= 0x04; break; } al = S (0x4a); if (al!=1) { // L7: //PRINTF( "Sorry, I dunno what setne does\n" ); //if zero flag is clear (ne) then al = 1, else al = 0; if (al != 0x02) al = 1; else al = 0; al--; al &= 0x08; var_minus4 = al; } else var_minus4 = 0x04; /* This is 8kHz */ // L8: label not used! dp_apollo_command(0x20, arg, 0, 7, H_TAD_tx_level_dB -3, 0, 0, var_minus4 ); // dp_set_tad_speaker_gain(); // dp_set_tad_mic_gain(); // dp_detect_dtmf(); dp_write_dsp_ram(0x3c, 0x28); al = dp_vt_cntrl; if ((al == 0xc0) || (al == 0xe0) || (al == 0x40) || (al == 0x80)) { dp_write_dsp_ram(0x85, 0x105); dp_write_dsp_ram(0x85, 0x1305); } else dp_write_dsp_ram(0x85, 0x1205); /* bc2: */ al = dp_vt_cntrl; if (!(al & 0x80)) goto L13; if ((al == 0xa0) || (al == 0xf0)) /* bda */ dp_write_dsp_ram(0x87e, 0xa000); else dp_write_dsp_ram(0x87e, 0x8000); dp_write_dsp_ram(0x87c, 0x3000); /* bf0 */ goto L14; L13: dp_write_dsp_ram(0x87e, 0); L14: dp_write_dsp_ram(0xe0, 0x80); dp_write_dsp_ram(0xe4, 0x80); dp_write_dsp_ram(0xe5, 0xfff0); dp_dsp_data_in_progress = 0; dp_tad_downloaded = 1; printf( "dp_start_tad done\n" );}voiddp_synth_ring_freq1(void){ printf( "FAKE: I just selected one set of values\n" ); dp_write_dsp_ram(0x5, 0x24b5); dp_write_dsp_ram(0x6, 0x346c);}voiddp_synth_ring_freq2(void){ printf( "FAKE: I just selected one set of values\n" ); dp_write_dsp_ram(0x5, 0x2d41); dp_write_dsp_ram(0x6, 0x2d41);}voiddp_synth_ring_init(void){ dp_write_dsp_ram(0x11, 6+S_synthetic_ring_volume); dp_modem_command(0x13, 0, 0); dp_download_tad(); dp_write_dsp_ram(0x85, 0); dp_apollo_command(0x20, 0x20, 0, 0, 0, 0, 0, 0x40); x_output(0x17); dp_modem_command(0x7, 0x1, 0); dp_write_dsp_ram(0x17, 0xbb8); dp_synth_ring_freq1(); dp_write_dsp_ram(0x85, 0x20); x_output(0x17); dp_enable_ring_int();}voiddp_synth_ring_on(void){ dp_write_dsp_ram(0x11, S_synthetic_ring_volume); sleep(1); dp_synth_ring_freq2();}voiddp_synth_ring_off(void){ dp_write_dsp_ram(0x85, 0); dp_modem_command(0x13, 0, 0); x_output(0x18);}// Stuff robbed from jamie.cvoid dp_apollo_command(int a8, int aC, int a10, int a14, int a18, int a1c, int a20, int a24){ dp_regwrite(0xD8, 0x18); dp_regwrite(0x30, a24); dp_regwrite(0x31, a20); dp_regwrite(0x32, a1c); dp_regwrite(0x33, a18); dp_regwrite(0x34, a14); dp_regwrite(0x35, a10); dp_regwrite(0x36, aC); dp_regwrite(0x37, a8); wait_for_core_read();}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -