/* Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO This file is part of QtSoundModem QtSoundModem is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. QtSoundModem is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. newsamp You should have received a copy of the GNU General Public License along with QtSoundModem. If not, see http://www.gnu.org/licenses */ // UZ7HO Soundmodem Port by John Wiseman G8BPQ #include "UZ7HOStuff.h" void make_core_BPF(UCHAR snd_ch, short freq, short width); void make_core_TXBPF(UCHAR snd_ch, float freq, float width); void make_core_INTR(UCHAR snd_ch); void make_core_LPF(UCHAR snd_ch, short width); void wf_pointer(int snd_ch); char modes_name[modes_count][20] = { "AFSK AX.25 300bd","AFSK AX.25 1200bd","AFSK AX.25 600bd","AFSK AX.25 2400bd", "BPSK AX.25 1200bd","BPSK AX.25 600bd","BPSK AX.25 300bd","BPSK AX.25 2400bd", "QPSK AX.25 4800bd","QPSK AX.25 3600bd","QPSK AX.25 2400bd","BPSK FEC 4x100bd", "DW QPSK V26A 2400bd","DW 8PSK V27 4800bd","DW QPSK V26B 2400bd", "ARDOP Packet" }; typedef struct wavehdr_tag { unsigned short * lpData; /* pointer to locked data buffer */ int dwBufferLength; /* length of data buffer */ int dwBytesRecorded; /* used for input only */ int * dwUser; /* for client's use */ int dwFlags; /* assorted flags (see defines) */ int dwLoops; /* loop control counter */ struct wavehdr_tag *lpNext; /* reserved for driver */ int * reserved; /* reserved for driver */ } WAVEHDR, *PWAVEHDR, * NPWAVEHDR, * LPWAVEHDR; extern int pnt_change[5]; int debugmode = 0; extern float src_buf[5][2048]; extern Byte RCVR[5]; int SatelliteMode = 0; int UDPServerPort = 8884; int UDPClientPort = 8888; int TXPort = 8884; BOOL Firstwaterfall = 1; BOOL Secondwaterfall = 1; BOOL multiCore = FALSE; /* type TComboBox = class(StdCtrls.TComboBox) private procedure CMMouseWheel(var msg TCMMouseWheel); message CM_MOUSEWHEEL; end; TData16 = array [0..4095] of smallint; PData16 = ^TData16; TWaveHeader = record RIFF dword; ChunkLen integer; WAVE dword; fmt dword; FormatLen integer; Format word; Channels word; Frequency integer; BytesPS integer; BlockAlign word; BitsPS word; data dword; DataLen integer end; TForm1 = class(TForm) Panel5 TPanel; ServerSocket1 TServerSocket; MainMenu1 TMainMenu; Settings1 TMenuItem; OutputVolume1 TMenuItem; InputVolume1 TMenuItem; CoolTrayIcon1 TCoolTrayIcon; ImageList1 TImageList; ABout1 TMenuItem; Panel1 TPanel; Panel2 TPanel; View1 TMenuItem; Firstwaterfall1 TMenuItem; Secondwaterfall1 TMenuItem; Panel3 TPanel; StringGrid1 TStringGrid; Devices1 TMenuItem; Statustable1 TMenuItem; Monitor1 TMenuItem; Panel4 TPanel; PaintBox2 TPaintBox; Filters1 TMenuItem; Clearmonitor1 TMenuItem; RxRichEdit1 TRxRichEdit; MemoPopupMenu1 TPopupMenu; Copytext1 TMenuItem; Label1 TLabel; Label5 TLabel; ApplicationEvents1 TApplicationEvents; PaintBox1 TPaintBox; PaintBox3 TPaintBox; ServerSocket2 TServerSocket; Font1 TMenuItem; FontDialog1 TFontDialog; N1 TMenuItem; Calibration1 TMenuItem; Panel9 TPanel; Panel6 TPanel; Label4 TLabel; Shape2 TShape; ComboBox2 TComboBox; SpinEdit2 TSpinEdit; Panel7 TPanel; Label3 TLabel; Shape1 TShape; ComboBox1 TComboBox; SpinEdit1 TSpinEdit; Panel8 TPanel; Label2 TLabel; TrackBar1 TTrackBar; CheckBox1 TCheckBox; OpenDialog1 TOpenDialog; procedure FormCreate(Sender TObject); procedure TrackBar1Change(Sender TObject); procedure PaintBox1MouseMove(Sender TObject; Shift TShiftState; X, Y Integer); procedure PaintBox1MouseDown(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); procedure ServerSocket1ClientRead(Sender TObject; Socket TCustomWinSocket); procedure ServerSocket1ClientError(Sender TObject; Socket TCustomWinSocket; ErrorEvent TErrorEvent; var ErrorCode Integer); procedure OutputVolume1Click(Sender TObject); procedure InputVolume1Click(Sender TObject); procedure ServerSocket1ClientConnect(Sender TObject; Socket TCustomWinSocket); procedure ServerSocket1ClientDisconnect(Sender TObject; Socket TCustomWinSocket); procedure CoolTrayIcon1Click(Sender TObject); procedure CoolTrayIcon1Cycle(Sender TObject; NextIndex Integer); procedure ABout1Click(Sender TObject); procedure PaintBox3MouseDown(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); procedure PaintBox3MouseMove(Sender TObject; Shift TShiftState; X, Y Integer); procedure Firstwaterfall1Click(Sender TObject); procedure Secondwaterfall1Click(Sender TObject); procedure Devices1Click(Sender TObject); procedure Statustable1Click(Sender TObject); procedure Monitor1Click(Sender TObject); procedure FormPaint(Sender TObject); procedure Filters1Click(Sender TObject); procedure SpinEdit1Change(Sender TObject); procedure SpinEdit2Change(Sender TObject); procedure Clearmonitor1Click(Sender TObject); procedure Copytext1Click(Sender TObject); procedure PaintBox3MouseUp(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); procedure PaintBox1MouseUp(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); procedure ApplicationEvents1Minimize(Sender TObject); procedure ApplicationEvents1Restore(Sender TObject); procedure ServerSocket2ClientConnect(Sender TObject; Socket TCustomWinSocket); procedure ServerSocket2ClientDisconnect(Sender TObject; Socket TCustomWinSocket); procedure ServerSocket2ClientError(Sender TObject; Socket TCustomWinSocket; ErrorEvent TErrorEvent; var ErrorCode Integer); procedure ServerSocket2ClientRead(Sender TObject; Socket TCustomWinSocket); procedure Font1Click(Sender TObject); procedure Calibration1Click(Sender TObject); procedure ComboBox1Change(Sender TObject); procedure ComboBox1KeyDown(Sender TObject; var Key Word; Shift TShiftState); procedure ComboBox1KeyPress(Sender TObject; var Key Char); procedure ComboBox2Change(Sender TObject); procedure FormDestroy(Sender TObject); private { Private declarations } procedure BufferFull(var Msg TMessage); Message MM_WIM_DATA; procedure BufferFull1(var Msg TMessage); Message MM_WOM_DONE; procedure make_wave_buf(snd_ch byte; buf PChar); procedure disp2(snd_ch byte); procedure create_timer1; procedure free_timer1; procedure show_panels; procedure show_combobox; procedure Timer_Event2; procedure waterfall_init; procedure waterfall_free; public { Public declarations } function get_idx_by_name(name string) word; function frame_monitor(s,code string; tx_stat boolean) string; procedure ChangePriority; procedure put_frame(snd_ch byte; frame,code string; tx_stat,excluded boolean); procedure show_grid; procedure RX2TX(snd_ch byte); procedure TX2RX(snd_ch byte); procedure WriteIni; procedure ReadIni; procedure init_8P4800(snd_ch byte); procedure init_DW2400(snd_ch byte); procedure init_AE2400(snd_ch byte); procedure init_MP400(snd_ch byte); procedure init_Q4800(snd_ch byte); procedure init_Q3600(snd_ch byte); procedure init_Q2400(snd_ch byte); procedure init_P2400(snd_ch byte); procedure init_P1200(snd_ch byte); procedure init_P600(snd_ch byte); procedure init_P300(snd_ch byte); procedure init_300(snd_ch byte); procedure init_600(snd_ch byte); procedure init_1200(snd_ch byte); procedure init_2400(snd_ch byte); procedure init_speed(snd_ch byte); procedure get_filter_values(idx byte; var dbpf,dtxbpf,dbpftap,dlpf,dlpftap word); procedure show_mode_panels; procedure show_modes; procedure show_freq_a; procedure show_freq_b; procedure ChkSndDevName; procedure StartRx; procedure StartTx(snd_ch byte); procedure StopRx; procedure StopTx(snd_ch byte); procedure StartAGW; procedure StartKISS; procedure wf_scale; procedure wf_pointer(snd_ch byte); end; var /*/ BOOL MinOnStart = 0; //RS TReedSolomon; // Form1 TForm1; // WaveFormat TWaveFormatEx; int Channels = 2; int BitsPerSample = 16; float TX_Samplerate = 12000; float RX_Samplerate = 12000; int RX_SR = 11025; int TX_SR = 11025; int RX_PPM = 0; int TX_PPM = 0; int tx_bufsize = 512; int rx_bufsize = 512; int tx_bufcount = 16; int rx_bufcount = 16; int mouse_down[2] = {0, 0}; //UCHAR * RX_pBuf array[257]; // RX_header array[1..256] of TWaveHdr; // TX_pBuf array[1..4,1..256] of pointer; //TX_header array[1..4,1..256] of TWaveHdr; UCHAR calib_mode[5] = {0,0,0,0}; UCHAR snd_status [5] = {0,0,0,0}; UCHAR buf_status [5] = {0,0,0,0}; UCHAR tx_buf_num1 [5] = {0,0,0,0}; UCHAR tx_buf_num [5] = {0,0,0,0}; extern short active_rx_freq[5]; int speed[5] = {0,0,0,0}; int panels[6] = {1,1,1,1,1}; short fft_buf[5][4096]; UCHAR fft_disp[5][4096]; int fftCount = 0; // FTF samples collected // bm array[1..4] of TBitMap; // bm1,bm2,bm3 TBitMap; // WaveInHandle hWaveIn; // WaveOutHandle array[1..4] of hWaveOut; int RXBufferLength; int grid_time = 0; int fft_mult = 0; int fft_spd = 3; int grid_timer = 0; int stop_wf = 0; int raduga = DISP_RGB; char snd_rx_device_name[32] = ""; char snd_tx_device_name[32] = ""; int snd_rx_device = 0; int snd_tx_device = 0; UCHAR mod_icon_status = MOD_IDLE; UCHAR last_mod_icon_status = MOD_IDLE; UCHAR icon_timer = 0; // TelIni TIniFile; char cur_dir[] = ""; // TimerId1 cardinal; // TimerId2 cardinal; UCHAR TimerStat1 = TIMER_FREE; UCHAR TimerStat2 = TIMER_FREE; int stat_log = FALSE; int PTT_device = FALSE; int RX_device = FALSE; int TX_device = FALSE; int TX_rotate = FALSE; int UsingBothChannels = FALSE; int UsingLeft = FALSE; int UsingRight = FALSE; int SCO = FALSE; int DualPTT = TRUE; UCHAR DebugMode = 0; UCHAR TimerEvent = TIMER_EVENT_OFF; int nr_monitor_lines = 50; int UTC_Time = FALSE; int MainPriority = 0; // MainThreadHandle THandle; UCHAR w_state = WIN_MAXIMIZED; /* implementation {$R *.DFM} uses ax25_mod, ax25_demod, ax25, ax25_l2, ax25_ptt, ax25_agw, ax25_about, rgb_rad, AX25_set, ax25_filter, AX25_modem_set, kiss_mode, ax25_calibration; procedure TComboBox.CMMouseWheel(var msg TCMMouseWheel); begin if SendMessage(GetFocus, CB_GETDROPPEDSTATE, 0, 0) = 0 then msg.Result = 1; end; procedure TForm1.ChangePriority; begin case MainPriority of 0 SetThreadPriority(MainThreadHandle,THREAD_PRIORITY_NORMAL); 1 SetThreadPriority(MainThreadHandle,THREAD_PRIORITY_ABOVE_NORMAL); 2 SetThreadPriority(MainThreadHandle,THREAD_PRIORITY_HIGHEST); 3 SetThreadPriority(MainThreadHandle,THREAD_PRIORITY_TIME_CRITICAL); end; end; procedure TForm1.show_modes; var s string; begin s = MODEM_CAPTION+" - Ver "+MODEM_VERSION+" - ["+modes_name[Speed[1]]; if dualchan then s = s+" - "+modes_name[Speed[2]]; form1.Caption = s+"]"; end; procedure TForm1.show_freq_a; begin SpinEdit1.Value = round(rx_freq[1]); SpinEdit1.Refresh; end; procedure TForm1.show_freq_b; begin SpinEdit2.Value = round(rx_freq[2]); SpinEdit2.Refresh; end; */ void get_filter_values(UCHAR snd_ch) { //, unsigned short dbpf, //unsigned short dtxbpf, //unsigned short dbpftap, //unsigned short dlpf, //unsigned short dlpftap) // speed[snd_ch], bpf[snd_ch], txbpf[snd_ch], bpf_tap[snd_ch], lpf[snd_ch], lpf_tap[snd_ch]); switch (speed[snd_ch]) { case SPEED_8P4800: lpf[snd_ch] = MODEM_8P4800_LPF; bpf[snd_ch] = MODEM_8P4800_BPF; txbpf[snd_ch] = MODEM_8P4800_TXBPF; BPF_tap[snd_ch] = MODEM_8P4800_BPF_TAP; LPF_tap[snd_ch] = MODEM_8P4800_LPF_TAP; break; case SPEED_MP400: lpf[snd_ch] = MODEM_MP400_LPF; bpf[snd_ch] = MODEM_MP400_BPF; txbpf[snd_ch] = MODEM_MP400_TXBPF; BPF_tap[snd_ch] = MODEM_MP400_BPF_TAP; LPF_tap[snd_ch] = MODEM_MP400_LPF_TAP; break; case SPEED_Q4800: lpf[snd_ch] = MODEM_Q4800_LPF; bpf[snd_ch] = MODEM_Q4800_BPF; txbpf[snd_ch] = MODEM_Q4800_TXBPF; BPF_tap[snd_ch] = MODEM_Q4800_BPF_TAP; LPF_tap[snd_ch] = MODEM_Q4800_LPF_TAP; break; case SPEED_Q3600: lpf[snd_ch] = MODEM_Q3600_LPF; bpf[snd_ch] = MODEM_Q3600_BPF; txbpf[snd_ch] = MODEM_Q3600_TXBPF; BPF_tap[snd_ch] = MODEM_Q3600_BPF_TAP; LPF_tap[snd_ch] = MODEM_Q3600_LPF_TAP; break; case SPEED_Q2400: lpf[snd_ch] = MODEM_Q2400_LPF; bpf[snd_ch] = MODEM_Q2400_BPF; txbpf[snd_ch] = MODEM_Q2400_TXBPF; BPF_tap[snd_ch] = MODEM_Q2400_BPF_TAP; LPF_tap[snd_ch] = MODEM_Q2400_LPF_TAP; break; case SPEED_DW2400: case SPEED_AE2400: lpf[snd_ch] = MODEM_DW2400_LPF; bpf[snd_ch] = MODEM_DW2400_BPF; txbpf[snd_ch] = MODEM_DW2400_TXBPF; BPF_tap[snd_ch] = MODEM_DW2400_BPF_TAP; LPF_tap[snd_ch] = MODEM_DW2400_LPF_TAP; break; case SPEED_P2400: lpf[snd_ch] = MODEM_P2400_LPF; bpf[snd_ch] = MODEM_P2400_BPF; txbpf[snd_ch] = MODEM_P2400_TXBPF; BPF_tap[snd_ch] = MODEM_P2400_BPF_TAP; LPF_tap[snd_ch] = MODEM_P2400_LPF_TAP; break; case SPEED_P1200: lpf[snd_ch] = MODEM_P1200_LPF; bpf[snd_ch] = MODEM_P1200_BPF; txbpf[snd_ch] = MODEM_P1200_TXBPF; BPF_tap[snd_ch] = MODEM_P1200_BPF_TAP; LPF_tap[snd_ch] = MODEM_P1200_LPF_TAP; break; case SPEED_P600: lpf[snd_ch] = MODEM_P600_LPF; bpf[snd_ch] = MODEM_P600_BPF; txbpf[snd_ch] = MODEM_P600_TXBPF; BPF_tap[snd_ch] = MODEM_P600_BPF_TAP; LPF_tap[snd_ch] = MODEM_P600_LPF_TAP; break; case SPEED_P300: lpf[snd_ch] = MODEM_P300_LPF; bpf[snd_ch] = MODEM_P300_BPF; txbpf[snd_ch] = MODEM_P300_TXBPF; BPF_tap[snd_ch] = MODEM_P300_BPF_TAP; LPF_tap[snd_ch] = MODEM_P300_LPF_TAP; break; case SPEED_300: lpf[snd_ch] = MODEM_300_LPF; bpf[snd_ch] = MODEM_300_BPF; txbpf[snd_ch] = MODEM_300_TXBPF; BPF_tap[snd_ch] = MODEM_300_BPF_TAP; LPF_tap[snd_ch] = MODEM_300_LPF_TAP; break; case SPEED_600: lpf[snd_ch] = MODEM_600_LPF; bpf[snd_ch] = MODEM_600_BPF; txbpf[snd_ch] = MODEM_600_TXBPF; BPF_tap[snd_ch] = MODEM_600_BPF_TAP; LPF_tap[snd_ch] = MODEM_600_LPF_TAP; break; case SPEED_1200: lpf[snd_ch] = MODEM_1200_LPF; bpf[snd_ch] = MODEM_1200_BPF; txbpf[snd_ch] = MODEM_1200_TXBPF; BPF_tap[snd_ch] = MODEM_1200_BPF_TAP; LPF_tap[snd_ch] = MODEM_1200_LPF_TAP; break; case SPEED_2400: lpf[snd_ch] = MODEM_2400_LPF; bpf[snd_ch] = MODEM_2400_BPF; txbpf[snd_ch] = MODEM_2400_TXBPF; BPF_tap[snd_ch] = MODEM_2400_BPF_TAP; LPF_tap[snd_ch] = MODEM_2400_LPF_TAP; break; } } void init_2400(int snd_ch) { modem_mode[snd_ch] = MODE_FSK; rx_shift[snd_ch] = 1805; rx_baudrate[snd_ch] = 2400; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_1200(int snd_ch) { modem_mode[snd_ch] = MODE_FSK; rx_shift[snd_ch] = 1000; if (stdtones) rx_freq[snd_ch] = 1700; rx_baudrate[snd_ch] = 1200; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_600(int snd_ch) { modem_mode[snd_ch] = MODE_FSK; rx_shift[snd_ch] = 450; rx_baudrate[snd_ch] = 600; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_300(int snd_ch) { modem_mode[snd_ch] = MODE_FSK; rx_shift[snd_ch] = 200; rx_baudrate[snd_ch] = 300; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_MP400(int snd_ch) { modem_mode[snd_ch] = MODE_MPSK; rx_shift[snd_ch] = 175 /*sbc*/ * 3; rx_baudrate[snd_ch] = 100; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_8P4800(int snd_ch) { modem_mode[snd_ch] = MODE_8PSK; if (stdtones) rx_freq[snd_ch] = 1800; rx_shift[snd_ch] = 1600; rx_baudrate[snd_ch] = 1600; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_AE2400(int snd_ch) { qpsk_set[snd_ch].mode = QPSK_V26; modem_mode[snd_ch] = MODE_PI4QPSK; if (stdtones) rx_freq[snd_ch] = 1800; rx_shift[snd_ch] = 1200; rx_baudrate[snd_ch] = 1200; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_DW2400(int snd_ch) { qpsk_set[snd_ch].mode = QPSK_V26; modem_mode[snd_ch] = MODE_QPSK; if (stdtones) rx_freq[snd_ch] = 1800; rx_shift[snd_ch] = 1200; rx_baudrate[snd_ch] = 1200; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_Q4800(int snd_ch) { qpsk_set[snd_ch].mode = QPSK_SM; modem_mode[snd_ch] = MODE_QPSK; rx_shift[snd_ch] = 2400; rx_baudrate[snd_ch] = 2400; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_Q3600(int snd_ch) { qpsk_set[snd_ch].mode = QPSK_SM; modem_mode[snd_ch] = MODE_QPSK; rx_shift[snd_ch] = 1800; rx_baudrate[snd_ch] = 1800; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_Q2400(int snd_ch) { qpsk_set[snd_ch].mode = QPSK_SM; modem_mode[snd_ch] = MODE_QPSK; rx_shift[snd_ch] = 1200; rx_baudrate[snd_ch] = 1200; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_P2400(int snd_ch) { modem_mode[snd_ch] = MODE_BPSK; rx_shift[snd_ch] = 2400; rx_baudrate[snd_ch] = 2400; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_P1200(int snd_ch) { modem_mode[snd_ch] = MODE_BPSK; rx_shift[snd_ch] = 1200; rx_baudrate[snd_ch] = 1200; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_P600(int snd_ch) { modem_mode[snd_ch] = MODE_BPSK; rx_shift[snd_ch] = 600; rx_baudrate[snd_ch] = 600; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_P300(int snd_ch) { modem_mode[snd_ch] = MODE_BPSK; rx_shift[snd_ch] = 300; rx_baudrate[snd_ch] = 300; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_ARDOP(int snd_ch) { modem_mode[snd_ch] = MODE_ARDOP; rx_shift[snd_ch] = 500; rx_freq[snd_ch] = 1500; rx_baudrate[snd_ch] = 500; if (modem_def[snd_ch]) get_filter_values(snd_ch); } void init_speed(int snd_ch); void set_speed(int snd_ch, int Modem) { speed[snd_ch] = Modem; init_speed(snd_ch); } void init_speed(int snd_ch) { int low, high; /* if (BPF[snd_ch]>round(rx_samplerate/2) then BPF[snd_ch] = round(rx_samplerate/2); if TXBPF[snd_ch]>round(rx_samplerate/2) then TXBPF[snd_ch] = round(rx_samplerate/2); if LPF[snd_ch]>round(rx_samplerate/2) then LPF[snd_ch] = round(rx_samplerate/2); if BPF[snd_ch]<1 then BPF[snd_ch] = 1; if TXBPF[snd_ch]<1 then TXBPF[snd_ch] = 1; if LPF[snd_ch]<1 then LPF[snd_ch] = 1; if TXDelay[snd_ch]<1 then TXDelay[snd_ch] = 1; if TXTail[snd_ch]<1 then TXTail[snd_ch] = 1; if BPF_tap[snd_ch]>1024 then BPF_tap[snd_ch] = 1024; if LPF_tap[snd_ch]>512 then LPF_tap[snd_ch] = 512; if BPF_tap[snd_ch]<8 then BPF_tap[snd_ch] = 8; if LPF_tap[snd_ch]<8 then LPF_tap[snd_ch] = 8; if not (RCVR[snd_ch] in [0..8]) then RCVR[snd_ch] = 0; if not (rcvr_offset[snd_ch] in [0..100]) then rcvr_offset[snd_ch] = 30; if not (speed[snd_ch] in [0..modes_count]) then speed[snd_ch] = SPEED_300; */ switch (speed[snd_ch]) { case SPEED_8P4800: init_8P4800(snd_ch); break; case SPEED_AE2400: init_AE2400(snd_ch); break; case SPEED_DW2400: init_DW2400(snd_ch); break; case SPEED_MP400: init_MP400(snd_ch); break; case SPEED_Q4800: init_Q4800(snd_ch); break; case SPEED_Q3600: init_Q3600(snd_ch); break; case SPEED_Q2400: init_Q2400(snd_ch); break; case SPEED_P2400: init_P2400(snd_ch); break; case SPEED_P1200: init_P1200(snd_ch); break; case SPEED_P600: init_P600(snd_ch); break; case SPEED_P300: init_P300(snd_ch); break; case SPEED_300: init_300(snd_ch); break; case SPEED_600: init_600(snd_ch); break; case SPEED_1200: init_1200(snd_ch); break; case SPEED_2400: init_2400(snd_ch); break; case SPEED_ARDOP: init_ARDOP(snd_ch); break; } //QPSK_SM: begin move(#0#1#2#3, tx[0], 4); move(#0#32#64#96, rx[0], 4); end; //QPSK_V26: begin move(#2#3#1#0, tx[0], 4); move(#96#64#0#32, rx[0], 4); end; if (modem_mode[snd_ch] == MODE_QPSK || modem_mode[snd_ch] == MODE_PI4QPSK) { switch (qpsk_set[snd_ch].mode) { case QPSK_SM: memcpy(&qpsk_set[snd_ch].tx[0], "\0\1\2\3", 4); memcpy(&qpsk_set[snd_ch].rx[0], "\x0\x20\x40\x60", 4); break; case QPSK_V26: memcpy(&qpsk_set[snd_ch].tx[0], "\2\3\1\0", 4); memcpy(&qpsk_set[snd_ch].rx[0], "\x60\x40\0\x20", 4); break; } } tx_shift[snd_ch] = rx_shift[snd_ch]; tx_baudrate[snd_ch] = rx_baudrate[snd_ch]; low = roundf(rx_shift[snd_ch] / 2 + RCVR[snd_ch] * rcvr_offset[snd_ch] + 1); high = roundf(RX_Samplerate / 2 - (rx_shift[snd_ch] / 2 + RCVR[snd_ch] * rcvr_offset[snd_ch])); if (rx_freq[snd_ch] - low < 0) rx_freq[snd_ch] = low; if (high - rx_freq[snd_ch] < 0) rx_freq[snd_ch] = high; tx_freq[snd_ch] = rx_freq[snd_ch]; make_core_BPF(snd_ch, rx_freq[snd_ch], bpf[snd_ch]); make_core_TXBPF(snd_ch, tx_freq[snd_ch], txbpf[snd_ch]); make_core_INTR(snd_ch); make_core_LPF(snd_ch, lpf[snd_ch]); /* for i = 0 to 16 do for j = 0 to nr_emph do with DET[j,i] do begin minamp[snd_ch] = 0; maxamp[snd_ch] = 0; ones[snd_ch] = 0; zeros[snd_ch] = 0; sample_cnt[snd_ch] = 0; bit_cnt[snd_ch] = 0; bit_osc[snd_ch] = 0; frame_status[snd_ch] = FRAME_WAIT; end; form1.show_modes; form1.show_freq_a; form1.show_freq_b; */ wf_pointer(soundChannel[snd_ch]); } /* procedure TForm1.show_combobox; var i word; begin for i = 0 to length(modes_name)-1 do begin ComboBox1.Items.Add(modes_name[i]); ComboBox2.Items.Add(modes_name[i]); end; ComboBox1.ItemIndex = ComboBox1.Items.IndexOf(modes_name[Speed[1]]); ComboBox2.ItemIndex = ComboBox2.Items.IndexOf(modes_name[Speed[2]]); end; function TForm1.get_idx_by_name(name string) word; var i word; found boolean; begin i = 0; found = FALSE; result = 0; repeat if name = modes_name[i] then begin found = TRUE; result = i; end else inc(i); until found or (i = length(modes_name)); end; procedure TForm1.ReadIni; var snd_ch byte; begin TelIni = TIniFile.Create(cur_dir+"soundmodem.ini"); with TelIni do begin UTC_Time = ReadBool("Init","UTCTime",FALSE); MainPriority = ReadInteger("Init","Priority",2); nr_monitor_lines = ReadInteger("Init","NRMonitorLines",500); ptt = ReadString("Init","PTT","NONE"); stop_wf = ReadBool("Init","StopWF",FALSE); raduga = ReadBool("Init","DispMode",DISP_MONO); stat_log = ReadBool("Init","StatLog",FALSE); SND_RX_DEVICE = ReadInteger("Init","SndRXDevice",0); SND_TX_DEVICE = ReadInteger("Init","SndTXDevice",0); snd_rx_device_name = ReadString("Init","SndRXDeviceName",""); snd_tx_device_name = ReadString("Init","SndTXDeviceName",""); RX_SR = ReadInteger("Init","RXSampleRate",11025); TX_SR = ReadInteger("Init","TXSampleRate",11025); RX_PPM = ReadInteger("Init","RX_corr_PPM",0); TX_PPM = ReadInteger("Init","TX_corr_PPM",0); tx_bufcount = ReadInteger("Init","TXBufNumber",32); rx_bufcount = ReadInteger("Init","RXBufNumber",32); DebugMode = ReadInteger("Init","DisableUnit",0); TX_rotate = ReadBool("Init","TXRotate",FALSE); DualChan = ReadBool("Init","DualChan",FALSE); DualPTT = ReadBool("Init","DualPTT",TRUE); SCO = ReadBool("Init","SCO",FALSE); stdtones = ReadBool("Init","UseStandardTones",TRUE); // Channel A settings maxframe[1] = ReadInteger("AX25_A","Maxframe",3); fracks[1] = ReadInteger("AX25_A","Retries",15); frack_time[1] = ReadInteger("AX25_A","FrackTime",5); idletime[1] = ReadInteger("AX25_A","IdleTime",180); slottime[1] = ReadInteger("AX25_A","SlotTime",100); persist[1] = ReadInteger("AX25_A","Persist",128); resptime[1] = ReadInteger("AX25_A","RespTime",1500); TXFrmMode[1] = ReadInteger("AX25_A","TXFrmMode",1); max_frame_collector[1] = ReadInteger("AX25_A","FrameCollector",6); exclude_callsigns[1] = ReadString("AX25_A","ExcludeCallsigns",""); exclude_APRS_frm[1] = ReadString("AX25_A","ExcludeAPRSFrmType",""); KISS_opt[1] = ReadBool("AX25_A","KISSOptimization",FALSE); dyn_frack[1] = ReadBool("AX25_A","DynamicFrack",FALSE); recovery[1] = ReadInteger("AX25_A","BitRecovery",0); NonAX25[1] = ReadBool("AX25_A","NonAX25Frm",FALSE); MEMRecovery[1] = ReadInteger("AX25_A","MEMRecovery",200); IPOLL[1] = ReadInteger("AX25_A","IPOLL",80); MyDigiCall[1] = ReadString("AX25_A","MyDigiCall",""); tx_hitoneraisedb[1] = ReadInteger("AX25_A","HiToneRaise",0); // Channel B settings maxframe[2] = ReadInteger("AX25_B","Maxframe",3); fracks[2] = ReadInteger("AX25_B","Retries",15); frack_time[2] = ReadInteger("AX25_B","FrackTime",5); idletime[2] = ReadInteger("AX25_B","IdleTime",180); slottime[2] = ReadInteger("AX25_B","SlotTime",100); persist[2] = ReadInteger("AX25_B","Persist",128); resptime[2] = ReadInteger("AX25_B","RespTime",1500); TXFrmMode[2] = ReadInteger("AX25_B","TXFrmMode",1); max_frame_collector[2] = ReadInteger("AX25_B","FrameCollector",6); exclude_callsigns[2] = ReadString("AX25_B","ExcludeCallsigns",""); exclude_APRS_frm[2] = ReadString("AX25_B","ExcludeAPRSFrmType",""); KISS_opt[2] = ReadBool("AX25_B","KISSOptimization",FALSE); dyn_frack[2] = ReadBool("AX25_B","DynamicFrack",FALSE); recovery[2] = ReadInteger("AX25_B","BitRecovery",0); NonAX25[2] = ReadBool("AX25_B","NonAX25Frm",FALSE); MEMRecovery[2] = ReadInteger("AX25_B","MEMRecovery",200); IPOLL[2] = ReadInteger("AX25_B","IPOLL",80); MyDigiCall[2] = ReadString("AX25_B","MyDigiCall",""); tx_hitoneraisedb[2] = ReadInteger("AX25_B","HiToneRaise",0); // Modem settings pkt_raw_min_len = ReadInteger("Modem","RawPktMinLen",17); swap_ptt = ReadBool("Modem","SwapPTTPins",FALSE); inv_ptt = ReadBool("Modem","InvPTTPins",FALSE); Emph_all[1] = ReadBool("Modem","PreEmphasisAll1",TRUE); Emph_all[2] = ReadBool("Modem","PreEmphasisAll2",TRUE); emph_db[1] = ReadInteger("Modem","PreEmphasisDB1",0); emph_db[2] = ReadInteger("Modem","PreEmphasisDB2",0); txbpf[1] = ReadInteger("Modem","TXBPF1",500); txbpf[2] = ReadInteger("Modem","TXBPF2",500); bpf[1] = ReadInteger("Modem","BPF1",500); bpf[2] = ReadInteger("Modem","BPF2",500); lpf[1] = ReadInteger("Modem","LPF1",150); lpf[2] = ReadInteger("Modem","LPF2",150); BPF_tap[1] = ReadInteger("Modem","BPFTap1",256); BPF_tap[2] = ReadInteger("Modem","BPFTap2",256); LPF_tap[1] = ReadInteger("Modem","LPFTap1",128); LPF_tap[2] = ReadInteger("Modem","LPFTap2",128); DCD_threshold = ReadInteger("Modem","DCDThreshold",32); rx_freq[1] = ReadFloat("Modem","RXFreq1",1700); rx_freq[2] = ReadFloat("Modem","RXFreq2",1700); CheckBox1.Checked = ReadBool("Modem","HoldPnt",FALSE); BIT_AFC = ReadInteger("Modem","AFC",32); txdelay[1] = ReadInteger("Modem","TxDelay1",250); txdelay[2] = ReadInteger("Modem","TxDelay2",250); txtail[1] = ReadInteger("Modem","TxTail1",50); txtail[2] = ReadInteger("Modem","TxTail2",50); diddles = ReadInteger("Modem","Diddles",0); RCVR[1] = ReadInteger("Modem","NRRcvrPairs1",0); RCVR[2] = ReadInteger("Modem","NRRcvrPairs2",0); rcvr_offset[1] = ReadInteger("Modem","RcvrShift1",30); rcvr_offset[2] = ReadInteger("Modem","RcvrShift2",30); speed[1] = ReadInteger("Modem","ModemType1",SPEED_1200); speed[2] = ReadInteger("Modem","ModemType2",SPEED_1200); modem_def[1] = ReadBool("Modem","Default1",TRUE); modem_def[2] = ReadBool("Modem","Default2",TRUE); AGWServ = ReadBool("AGWHost","Server",TRUE); AGWPort = ReadInteger("AGWHost","Port",8000); KISSServ = ReadBool("KISS","Server",FALSE); KISSPort = ReadInteger("KISS","Port",8100); Form1.Top = ReadInteger("Window","Top",0); Form1.Left = ReadInteger("Window","Left",0); Form1.Height = ReadInteger("Window","Height",656); Form1.Width = ReadInteger("Window","Width",764); MinOnStart = ReadBool("Window","MinimizedOnStartup",FALSE); Firstwaterfall1.checked = ReadBool("Window","Waterfall1",TRUE); Secondwaterfall1.checked = ReadBool("Window","Waterfall2",FALSE); Statustable1.checked = ReadBool("Window","StatTable",TRUE); Monitor1.checked = ReadBool("Window","Monitor",TRUE); RXRichEdit1.Font.Size = ReadInteger("Font","Size",RXRichEdit1.Font.Size); RXRichEdit1.Font.Name = ReadString("Font","Name",RXRichEdit1.Font.Name); end; TelIni.Free; newAGWPort = AGWPort; newAGWServ = AGWServ; newKISSPort = KISSPort; newKISSServ = KISSServ; RX_SampleRate = RX_SR+RX_SR*0.000001*RX_PPM; TX_SampleRate = TX_SR+TX_SR*0.000001*TX_PPM; panels[4] = Monitor1.Checked; panels[3] = Statustable1.Checked; panels[2] = Firstwaterfall1.Checked; panels[1] = Secondwaterfall1.Checked; if tx_bufcount>255 then tx_bufcount = 255; if tx_bufcount<2 then tx_bufcount = 2; if rx_bufcount>255 then rx_bufcount = 255; if rx_bufcount<2 then rx_bufcount = 2; if not (diddles in [0..2]) then diddles = 0; if nr_monitor_lines>65535 then nr_monitor_lines = 65535; if nr_monitor_lines<10 then nr_monitor_lines = 10; if not (MainPriority in [0..3]) then MainPriority = 2; for snd_ch = 1 to 2 do begin tx_hitoneraise[snd_ch] = power(10,-abs(tx_hitoneraisedb[snd_ch])/20); if IPOLL[snd_ch]<0 then IPOLL[snd_ch] = 0; if IPOLL[snd_ch]>65535 then IPOLL[snd_ch] = 65535; if MEMRecovery[snd_ch]<1 then MEMRecovery[snd_ch] = 1; if MEMRecovery[snd_ch]>65535 then MEMRecovery[snd_ch] = 65535; get_exclude_list(AnsiUpperCase(MyDigiCall[snd_ch]),list_digi_callsigns[snd_ch]); get_exclude_list(AnsiUpperCase(exclude_callsigns[snd_ch]),list_exclude_callsigns[snd_ch]); get_exclude_frm(exclude_APRS_frm[snd_ch],list_exclude_APRS_frm[snd_ch]); if resptime[snd_ch]<0 then resptime[snd_ch] = 0; if resptime[snd_ch]>65535 then resptime[snd_ch] = 65535; if persist[snd_ch]>255 then persist[snd_ch] = 255; if persist[snd_ch]<32 then persist[snd_ch] = 32; if fracks[snd_ch]<1 then fracks[snd_ch] = 1; if frack_time[snd_ch]<1 then frack_time[snd_ch] = 1; if idletime[snd_ch]0 then for k = 0 to numdevs-1 do begin waveOutGetDevCaps(k,@DevOutCaps,sizeof(DevOutCaps)); TXDevList.Add(DevOutCaps.szpname); end; numdevs = WaveInGetNumDevs; if numdevs>0 then for k = 0 to numdevs-1 do begin waveInGetDevCaps(k,@DevInCaps,sizeof(DevInCaps)); RXDevList.Add(DevInCaps.szpname); end; // TX Dev if (snd_tx_device<0) or (snd_tx_device> = TXDevList.Count) then snd_tx_device = 0; if TXDevList.Count>0 then if TXDevList.Strings[snd_tx_device]<>snd_tx_device_name then begin i = TXDevList.IndexOf(snd_tx_device_name); if i> = 0 then snd_tx_device = i else snd_tx_device_name = TXDevList.Strings[snd_tx_device]; end; // RX Dev if (snd_rx_device<0) or (snd_rx_device> = RXDevList.Count) then snd_rx_device = 0; if RXDevList.Count>0 then if RXDevList.Strings[snd_rx_device]<>snd_rx_device_name then begin i = RXDevList.IndexOf(snd_rx_device_name); if i> = 0 then snd_rx_device = i else snd_rx_device_name = RXDevList.Strings[snd_rx_device]; end; RXDevList.Free; TXDevList.Free; end; procedure TForm1.startrx; var OpenResult MMRESULT; Loop integer; ErrorText string; Begin RX_device = TRUE; RXBufferLength = rx_bufsize * Channels * (BitsPerSample div 8); with WaveFormat do begin wFormatTag = WAVE_FORMAT_PCM; nChannels = Channels; nSamplesPerSec = RX_SR; nAvgBytesPerSec = RX_SR * Channels * (BitsPerSample div 8); nBlockAlign = Channels * (BitsPerSample div 8); wBitsPerSample = BitsPerSample; cbSize = 0; end; OpenResult = waveInOpen (@WaveInHandle,SND_RX_DEVICE,@WaveFormat,integer(Self.Handle),0,CALLBACK_WINDOW); if OpenResult = MMSYSERR_NOERROR then begin for Loop = 1 to rx_bufcount do begin GetMem(RX_pbuf[Loop], RXBufferLength); RX_header[Loop].lpData = RX_pbuf[Loop]; RX_header[Loop].dwBufferLength = RXBufferLength; RX_header[Loop].dwUser = Loop; RX_header[Loop].dwFlags = 0; RX_header[Loop].dwLoops = 0; OpenResult = WaveInPrepareHeader(WaveInhandle, @RX_header[Loop], sizeof(TWaveHdr)); if OpenResult = MMSYSERR_NOERROR then WaveInAddBuffer(WaveInHandle, @RX_header[Loop], sizeof(TWaveHdr)) else begin case OpenResult of MMSYSERR_INVALHANDLE ErrorText = "device handle is invalid"; MMSYSERR_NODRIVER ErrorText = "no device driver present"; MMSYSERR_NOMEM ErrorText = "memory allocation error, could be incorrect samplerate"; else ErrorText = "unknown error"; end; MessageDlg(format("Error adding buffer %d device (%s)",[Loop, ErrorText]), mtError, [mbOk], 0); end; end; WaveInStart(WaveInHandle); end else begin case OpenResult of MMSYSERR_ERROR ErrorText = "unspecified error"; MMSYSERR_BADDEVICEID ErrorText = "device ID out of range"; MMSYSERR_NOTENABLED ErrorText = "driver failed enable"; MMSYSERR_ALLOCATED ErrorText = "device already allocated"; MMSYSERR_INVALHANDLE ErrorText = "device handle is invalid"; MMSYSERR_NODRIVER ErrorText = "no device driver present"; MMSYSERR_NOMEM ErrorText = "memory allocation error, could be incorrect samplerate"; MMSYSERR_NOTSUPPORTED ErrorText = "function isn""t supported"; MMSYSERR_BADERRNUM ErrorText = "error value out of range"; MMSYSERR_INVALFLAG ErrorText = "invalid flag passed"; MMSYSERR_INVALPARAM ErrorText = "invalid parameter passed"; MMSYSERR_HANDLEBUSY ErrorText = "handle being used simultaneously on another thread (eg callback)"; MMSYSERR_INVALIDALIAS ErrorText = "specified alias not found"; MMSYSERR_BADDB ErrorText = "bad registry database"; MMSYSERR_KEYNOTFOUND ErrorText = "registry key not found"; MMSYSERR_READERROR ErrorText = "registry read error"; MMSYSERR_WRITEERROR ErrorText = "registry write error"; MMSYSERR_DELETEERROR ErrorText = "registry delete error"; MMSYSERR_VALNOTFOUND ErrorText = "registry value not found"; MMSYSERR_NODRIVERCB ErrorText = "driver does not call DriverCallback"; else ErrorText = "unknown error"; end; MessageDlg(format("Error opening wave input device (%s)",[ErrorText]), mtError, [mbOk], 0); RX_device = FALSE; end; end; procedure TForm1.stoprx; var Loop integer; begin if not RX_device then exit; WaveInStop(WaveInHandle); WaveInReset(WaveInHandle); for Loop = 1 to rx_bufcount do WaveInUnPrepareHeader(WaveInHandle, @RX_header[Loop], sizeof(TWaveHdr)); WaveInClose(WaveInHandle); for Loop = 1 to rx_bufcount do begin if RX_pbuf[Loop]<>nil then begin FreeMem(RX_pbuf[Loop]); RX_pbuf[Loop] = nil; end; end; RX_device = FALSE; end; procedure TForm1.make_wave_buf(snd_ch byte; buf PChar); const amplitude = 22000; var i word; begin modulator(snd_ch,audio_buf[snd_ch],tx_bufsize); if tx_status[snd_ch] = TX_NO_DATA then buf_status[snd_ch] = BUF_EMPTY; for i = 0 to tx_bufsize-1 do begin case snd_ch of 1 begin // left channel PSmallInt(buf)^ = round(amplitude*audio_buf[snd_ch][i]); Inc(PSmallInt(Buf)); // right channel if SCO then PSmallInt(buf)^ = round(amplitude*audio_buf[snd_ch][i]) else PSmallInt(buf)^ = 0; Inc(PSmallInt(Buf)); end; 2 begin // left channel if SCO then PSmallInt(buf)^ = round(amplitude*audio_buf[snd_ch][i]) else PSmallInt(buf)^ = 0; Inc(PSmallInt(Buf)); // right channel PSmallInt(buf)^ = round(amplitude*audio_buf[snd_ch][i]); Inc(PSmallInt(Buf)); end; end; end; end; procedure TForm1.starttx(snd_ch byte); var OpenResult MMRESULT; Loop integer; ErrorText string; BufferLength longint; Begin if snd_status[snd_ch]<>SND_IDLE then exit; BufferLength = tx_bufsize * Channels * (BitsPerSample div 8); with WaveFormat do begin wFormatTag = WAVE_FORMAT_PCM; nChannels = Channels; nSamplesPerSec = TX_SR; nAvgBytesPerSec = TX_SR * Channels * (BitsPerSample div 8); nBlockAlign = Channels * (BitsPerSample div 8); wBitsPerSample = BitsPerSample; cbSize = 0; end; OpenResult = WaveOutOpen (@WaveOutHandle[snd_ch],SND_TX_DEVICE,@WaveFormat,integer(Self.Handle),0,CALLBACK_WINDOW); if OpenResult = MMSYSERR_NOERROR then begin snd_status[snd_ch] = SND_TX; buf_status[snd_ch] = BUF_FULL; tx_status[snd_ch] = TX_SILENCE; tx_buf_num[snd_ch] = 0; tx_buf_num1[snd_ch] = 0; for Loop = 1 to tx_bufcount do begin GetMem(TX_pbuf[snd_ch][Loop], BufferLength); TX_header[snd_ch][Loop].lpData = TX_pbuf[snd_ch][Loop]; TX_header[snd_ch][Loop].dwBufferLength = BufferLength; TX_header[snd_ch][Loop].dwUser = 0; TX_header[snd_ch][Loop].dwFlags = 0; TX_header[snd_ch][Loop].dwLoops = 0; OpenResult = WaveOutPrepareHeader(WaveOuthandle[snd_ch], @TX_header[snd_ch][Loop], sizeof(TWaveHdr)); if OpenResult = MMSYSERR_NOERROR then begin // Заполнить буфер на передачу if buf_status[snd_ch] = BUF_FULL then begin make_wave_buf(snd_ch,TX_pbuf[snd_ch][Loop]); WaveOutWrite(WaveOutHandle[snd_ch],@TX_header[snd_ch][Loop],sizeof(TWaveHdr)); inc(tx_buf_num1[snd_ch]); end; end else begin case OpenResult of MMSYSERR_INVALHANDLE ErrorText = "device handle is invalid"; MMSYSERR_NODRIVER ErrorText = "no device driver present"; MMSYSERR_NOMEM ErrorText = "memory allocation error, could be incorrect samplerate"; else ErrorText = "unknown error"; end; MessageDlg(format("Error adding buffer %d device (%s)",[Loop, ErrorText]), mtError, [mbOk], 0); end; end; end else begin case OpenResult of MMSYSERR_ERROR ErrorText = "unspecified error"; MMSYSERR_BADDEVICEID ErrorText = "device ID out of range"; MMSYSERR_NOTENABLED ErrorText = "driver failed enable"; MMSYSERR_ALLOCATED ErrorText = "device already allocated"; MMSYSERR_INVALHANDLE ErrorText = "device handle is invalid"; MMSYSERR_NODRIVER ErrorText = "no device driver present"; MMSYSERR_NOMEM ErrorText = "memory allocation error, could be incorrect samplerate"; MMSYSERR_NOTSUPPORTED ErrorText = "function isn""t supported"; MMSYSERR_BADERRNUM ErrorText = "error value out of range"; MMSYSERR_INVALFLAG ErrorText = "invalid flag passed"; MMSYSERR_INVALPARAM ErrorText = "invalid parameter passed"; MMSYSERR_HANDLEBUSY ErrorText = "handle being used simultaneously on another thread (eg callback)"; MMSYSERR_INVALIDALIAS ErrorText = "specified alias not found"; MMSYSERR_BADDB ErrorText = "bad registry database"; MMSYSERR_KEYNOTFOUND ErrorText = "registry key not found"; MMSYSERR_READERROR ErrorText = "registry read error"; MMSYSERR_WRITEERROR ErrorText = "registry write error"; MMSYSERR_DELETEERROR ErrorText = "registry delete error"; MMSYSERR_VALNOTFOUND ErrorText = "registry value not found"; MMSYSERR_NODRIVERCB ErrorText = "driver does not call DriverCallback"; else ErrorText = "unknown error"; end; MessageDlg(format("Error opening wave output device (%s)",[ErrorText]), mtError, [mbOk], 0); end; end; procedure TForm1.stoptx(snd_ch byte); var Loop integer; begin if snd_status[snd_ch]<>SND_TX then exit; WaveOutReset(WaveOutHandle[snd_ch]); for Loop = 1 to tx_bufcount do WaveOutUnPrepareHeader(WaveOutHandle[snd_ch], @TX_header[snd_ch][Loop], sizeof(TWaveHdr)); WaveOutClose(WaveOutHandle[snd_ch]); for Loop = 1 to tx_bufcount do begin if TX_pbuf[snd_ch][Loop]<>nil then begin FreeMem(TX_pbuf[snd_ch][Loop]); TX_pbuf[snd_ch][Loop] = nil; end; end; WaveOutHandle[snd_ch] = 0; snd_status[snd_ch] = SND_IDLE; end; procedure show_grid_title; const title array [0..10] of string = ("MyCall","DestCall","Status","Sent pkts","Sent bytes","Rcvd pkts","Rcvd bytes","Rcvd FC","CPS TX","CPS RX","Direction"); var i byte; begin for i = 0 to 10 do Form1.StringGrid1.Cells[i,0] = title[i]; end; */ /* procedure disp1(src1,src2 array of single); var i,n word; k,k1,amp1,amp2,amp3,amp4 single; bm TBitMap; begin bm = TBitMap.Create; bm.pixelformat = pf32bit; //bm.pixelformat = pf24bit; bm.Width = Form1.PaintBox2.Width; bm.Height = Form1.PaintBox2.Height; amp1 = 0; amp3 = 0; //k = 0.20; k = 50000; k1 = 0; //k = 1000; //k = 0.00001; bm.Canvas.MoveTo(0,50); bm.Canvas.LineTo(512,50); n = 0; for i = 0 to RX_Bufsize-1 do begin begin amp2 = src1[i]; amp4 = src2[i]; bm.Canvas.Pen.Color = clRed; bm.Canvas.MoveTo(n,50-round(amp1*k1)); bm.Canvas.LineTo(n+1,50-round(amp2*k1)); bm.Canvas.Pen.Color = clBlue; bm.Canvas.MoveTo(n,50-round(amp3*k)); bm.Canvas.LineTo(n+1,50-round(amp4*k)); bm.Canvas.Pen.Color = clBlack; inc(n); amp1 = amp2; amp3 = amp4; end; end; Form1.PaintBox2.Canvas.Draw(0,0,bm); bm.Free; end; */ /* procedure TForm1.wf_pointer(snd_ch byte); var x single; x1,x2,y,k,pos1,pos2,pos3 word; begin k = 24; x = FFTSize/RX_SampleRate; pos1 = round((rx_freq[snd_ch]-0.5*rx_shift[snd_ch])*x)-5; pos2 = round((rx_freq[snd_ch]+0.5*rx_shift[snd_ch])*x)-5; pos3 = round(rx_freq[snd_ch]*x); x1 = pos1+5; x2 = pos2+5; y = k+5; with bm3.Canvas do begin Draw(0,20,bm[snd_ch]); Pen.Color = clWhite; Brush.Color = clRed; Polygon([Point(x1+3,y),Point(x1,y-7),Point(x1-3,y),Point(x2+3,y),Point(x2,y-7),Point(x2-3,y)]); Brush.Color = clBlue; Polygon([Point(x1+3,y),Point(x1,y+7),Point(x1-3,y),Point(x2+3,y),Point(x2,y+7),Point(x2-3,y)]); Polyline([Point(pos3,k+1),Point(pos3,k+9)]); Pen.Color = clBlack; end; case snd_ch of 1 PaintBox1.Canvas.Draw(0,0,bm3); 2 PaintBox3.Canvas.Draw(0,0,bm3); end; end; procedure TForm1.wf_Scale; var k single; max_freq,x,i word; begin max_freq = round(RX_SampleRate*0.005); k = 100*FFTSize/RX_SampleRate; with bm1.Canvas do begin Brush.Color = clBlack; FillRect(ClipRect); Pen.Color = clWhite; Font.Color = clWhite; Font.Size = 8; for i = 0 to max_freq do begin x = round(k*i); if x<1025 then begin if (i mod 5) = 0 then PolyLine([Point(x,20),Point(x,13)]) else PolyLine([Point(x,20),Point(x,16)]); if (i mod 10) = 0 then TextOut(x-12,1,inttostr(i*100)); end; end; Pen.Color = clBlack; end; bm3.Canvas.Draw(0,0,bm1); end; */ void chk_snd_buf(float * buf, int len) { word i; boolean good; single prev_amp; if (len < 2) return; good = FALSE; i = 1; prev_amp = buf[0]; do { if (buf[i++] != prev_amp) good = TRUE; } while (good == FALSE && i < len); // Make noise if (!good) for (i = 0; i < len; i++) buf[i] = rand(); } #ifdef WIN32 typedef void *HANDLE; typedef unsigned long DWORD; #define WINAPI __stdcall __declspec(dllimport) DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds ); #define pthread_t uintptr_t uintptr_t _beginthread(void(__cdecl *start_address)(void *), unsigned stack_size, void *arglist); #else #include pthread_t _beginthread(void(*start_address)(void *), unsigned stack_size, void * arglist) { pthread_t thread; if (pthread_create(&thread, NULL, (void * (*)(void *))start_address, (void*)arglist) != 0) perror("New Thread"); return thread; } #endif void runModemthread(void * param); void runModems() { int snd_ch, res; pthread_t thread[4] = { 0,0,0,0 }; for (snd_ch = 0; snd_ch < 4; snd_ch++) { if (soundChannel[snd_ch] == 0) // Unused channed continue; if (modem_mode[snd_ch] == MODE_ARDOP) continue; // Processed above // do we need to do this again ?? // make_core_BPF(snd_ch, rx_freq[snd_ch], bpf[snd_ch]); if (multiCore) // Run modems in separate threads thread[snd_ch] = _beginthread(runModemthread, 0, (void *)(size_t)snd_ch); else runModemthread((void *)(size_t)snd_ch); } if (multiCore) { #ifdef WIN32 if (thread[0]) WaitForSingleObject(&thread[0], 2000); if (thread[1]) WaitForSingleObject(&thread[1], 2000); if (thread[2]) WaitForSingleObject(&thread[2], 2000); if (thread[3]) WaitForSingleObject(&thread[3], 2000); #else if (thread[0]) pthread_join(thread[0], &res); if (thread[1]) pthread_join(thread[1], &res); if (thread[2]) pthread_join(thread[2], &res); if (thread[3]) pthread_join(thread[3], &res); #endif } } Byte rcvr_idx; void runModemthread(void * param) { int snd_ch = (int)(size_t)param; // I want to run lowest to highest to simplify my display int offset = -(RCVR[snd_ch] * rcvr_offset[snd_ch]); // lowest int lastrx = RCVR[snd_ch] * 2; if (soundChannel[snd_ch] == 0) // Unused channed return; for (rcvr_idx = 0; rcvr_idx <= lastrx; rcvr_idx++) { active_rx_freq[snd_ch] = rxOffset + chanOffset[snd_ch] + rx_freq[snd_ch] + offset; offset += rcvr_offset[snd_ch]; Demodulator(snd_ch, rcvr_idx, src_buf[modemtoSoundLR[snd_ch]], rcvr_idx == lastrx, offset == 0); } } // I think this processes a buffer of samples void BufferFull(short * Samples, int nSamples) // These are Stereo Samples { word i, i1; Byte snd_ch, rcvr_idx; int buf_offset; int Needed; short * data1; short * data2 = 0; // if UDP server active send as UDP Datagram if (UDPServ) // Extract just left { short Buff[1024]; i1 = 0; for (i = 0; i < rx_bufsize; i++) { Buff[i] = Samples[i1]; i1 += 2; } sendSamplestoUDP(Buff, 512, TXPort); } // Do RSID processing (can we also use this for waterfall?? RSIDProcessSamples(Samples, nSamples); // Do FFT on every 4th buffer (2048 samples) // if in Satellite Mode look for a Tuning signal // if (SatelliteMode) // { // doTuning(Samples, nSamples); // } for (snd_ch = 0; snd_ch < 4; snd_ch++) { if (soundChannel[snd_ch] == 0) // Unused channed continue; if (pnt_change[snd_ch]) { make_core_BPF(snd_ch, rx_freq[snd_ch], bpf[snd_ch]); make_core_TXBPF(snd_ch, tx_freq[snd_ch], txbpf[snd_ch]); pnt_change[snd_ch] = FALSE; } } // I don't think we should process RX if either is sending if (snd_status[0] != SND_TX && snd_status[1] != SND_TX && snd_status[2] != SND_TX && snd_status[3] != SND_TX) { for (snd_ch = 0; snd_ch < 4; snd_ch++) { if (soundChannel[snd_ch] == 0) // Unused channed continue; if (modem_mode[snd_ch] == MODE_ARDOP) { short ardopbuff[1200]; i1 = 0; for (i = 0; i < rx_bufsize; i++) { ardopbuff[i] = Samples[i1]; i1++; i1++; } ARDOPProcessNewSamples(ardopbuff, nSamples); } } // extract mono samples from data. data1 = Samples; i1 = 0; // src_buf[0] is left data,. src_buf[1] right // We could skip extracting other channel if only one in use - is it worth it?? if (UsingBothChannels) { for (i = 0; i < rx_bufsize; i++) { src_buf[0][i] = data1[i1]; i1++; src_buf[1][i] = data1[i1]; i1++; } } else if (UsingRight) { // Extract just right i1 = 1; for (i = 0; i < rx_bufsize; i++) { src_buf[1][i] = data1[i1]; i1 += 2; } } else { // Extract just left for (i = 0; i < rx_bufsize; i++) { src_buf[0][i] = data1[i1]; i1 += 2; } } // Run modems before waterfall so fft buffer has values from before sync was detected runModems(); // Do whichever waterfall is needed // We need to run the waterfall FFT for the frequency guessing to work int FirstWaterfallChan = 0; short * ptr1 = &fft_buf[0][fftCount]; short * ptr2 = &fft_buf[1][fftCount]; int remainingSamples = rx_bufsize; if (UsingLeft == 0) { FirstWaterfallChan = 1; data1++; // to Right Samples } if (UsingBothChannels) // Second is always Right data2 = &Samples[1]; // to Right Samples // FFT size isn't necessarily a multiple of rx_bufsize, so this is a bit more complicated // Save FFTSize samples then process. Put the unused bits back in the fft buffer // Collect samples for both channels if needed Needed = FFTSize - fftCount; if (Needed <= rx_bufsize) { // add Needed samples to fft_buf and process. Copy rest to start of fft_buf for (i = 0; i < Needed; i++) { *ptr1++ = *data1; data1 += 2; } doWaterfall(FirstWaterfallChan); if (data2) { for (i = 0; i < Needed; i++) { *ptr2++ = *data2; data2 += 2; } doWaterfall(1); } remainingSamples = rx_bufsize - Needed; fftCount = 0; ptr1 = &fft_buf[0][0]; ptr2 = &fft_buf[1][0]; } for (i = 0; i < remainingSamples; i++) { *ptr1++ = *data1; data1 += 2; } if (data2) { for (i = 0; i < remainingSamples; i++) { *ptr2++ = *data2; data2 += 2; } } fftCount += remainingSamples; } if (TimerEvent == TIMER_EVENT_ON) { timer_event(); // timer_event2(); } } /* procedure TForm1.BufferFull1(var Msg TMessage); var i,snd_ch byte; begin for snd_ch = 1 to 2 do if pnt_change[snd_ch] then begin make_core_BPF(snd_ch,rx_freq[snd_ch],bpf[snd_ch]); make_core_TXBPF(snd_ch,tx_freq[snd_ch],txbpf[snd_ch]); pnt_change[snd_ch] = FALSE; end; snd_ch = 0; for i = 1 to 2 do if msg.WParam = WaveOutHandle[i] then snd_ch = i; if (snd_ch = 0) then exit; if (snd_status[snd_ch]<>SND_TX) then exit; inc(tx_buf_num[snd_ch]); if tx_buf_num[snd_ch]>tx_bufcount then tx_buf_num[snd_ch] = 1; if (buf_status[snd_ch] = BUF_EMPTY) and (tx_buf_num[snd_ch] = tx_buf_num1[snd_ch]) then TX2RX(snd_ch); if buf_status[snd_ch] = BUF_FULL then beginf make_wave_buf(snd_ch,TX_pbuf[snd_ch][tx_buf_num[snd_ch]]); WaveOutWrite(WaveOutHandle[snd_ch],@TX_header[snd_ch][tx_buf_num[snd_ch]],sizeof(TWaveHdr)); inc(tx_buf_num1[snd_ch]); if tx_buf_num1[snd_ch]>tx_bufcount then tx_buf_num1[snd_ch] = 1; end; end; procedure TForm1.TX2RX(snd_ch byte); begin if snd_status[snd_ch] = SND_TX then stoptx(snd_ch); if snd_status[snd_ch] = SND_IDLE then begin pttoff(snd_ch); end; end; */ // Monitor Code - from moncode.asm #define CMDBIT 4 // CURRENT MESSAGE IS A COMMAND #define RESP 2 // CURRENT MSG IS RESPONSE #define VER1 1 // CURRENT MSG IS VERSION 1 #define UI 3 #define SABM 0x2F #define DISC 0x43 #define DM 0x0F #define UA 0x63 #define FRMR 0x87 #define RR 1 #define RNR 5 #define REJ 9 #define SREJ 0x0D #define SABME 0x6F #define XID 0xAF #define TEST 0xE3 #define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE #define NETROM_PID 0xCF #define IP_PID 0xCC #define ARP_PID 0xCD #define NODES_SIG 0xFF char FrameData[1024] = ""; char * frame_monitor(string * frame, char * code, int tx_stat) { char mon_frm[512]; char AGW_path[256]; string * AGW_data; const Byte * frm = "???"; Byte * datap; Byte _data[512] = ""; Byte * p_data = _data; int _datalen; char agw_port; char CallFrom[10], CallTo[10], Digi[80]; char TR = 'R'; char codestr[64] = ""; integer i; char time_now[32]; int len; AGWUser * AGW; Byte pid, nr, ns, f_type, f_id; Byte rpt, cr, pf; Byte path[80]; char c; const char * p; string * data = newString(); if (code[0] && strlen(code) < 60) sprintf(codestr, "[%s]", code); if (tx_stat) TR = 'T'; decode_frame(frame->Data, frame->Length, path, data, &pid, &nr, &ns, &f_type, &f_id, &rpt, &pf, &cr); datap = data->Data; len = data->Length; // if (pid == 0xCF) // data = parse_NETROM(data, f_id); // IP parsing // else if (pid == 0xCC) // data = parse_IP(data); // ARP parsing // else if (pid == 0xCD) // data = parse_ARP(data); // if (len > 0) { for (i = 0; i < len; i++) { if (datap[i] > 31 || datap[i] == 13 || datap[i] == 9) *(p_data++) = datap[i]; } } _datalen = p_data - _data; if (_datalen) { Byte * ptr = _data; i = 0; // remove successive cr or cr on end while (i < _datalen) while (i < _datalen) { if ((_data[i] == 13) && (_data[i + 1] == 13)) i++; else *(ptr++) = _data[i++]; } if (*(ptr - 1) == 13) ptr--; *ptr = 0; _datalen = ptr - _data; } get_monitor_path(path, CallTo, CallFrom, Digi); if (cr) { c = 'C'; if (pf) p = " P"; else p = ""; } else { c = 'R'; if (pf) p = " F"; else p = ""; } switch (f_id) { case I_I: frm = "I"; break; case S_RR: frm = "RR"; break; case S_RNR: frm = "RNR"; break; case S_REJ: frm = "REJ"; break; case S_SREJ: frm = "SREJ"; break; case U_SABM: frm = "SABM"; break; case SABME: frm = "SABME"; break; case U_DISC: frm = "DISC"; break; case U_DM: frm = "DM"; break; case U_UA: frm = "UA"; break; case U_FRMR: frm = "FRMR"; break; case U_UI: frm = "UI"; } if (Digi[0]) sprintf(AGW_path, "Fm %s To %s Via %s <%s %c%s",CallFrom, CallTo, Digi, frm, c, p); else sprintf(AGW_path, "Fm %s To %s <%s %c %s", CallFrom, CallTo, frm, c, p); switch (f_type) { case I_FRM: //mon_frm = AGW_path + ctrl + ' R' + inttostr(nr) + ' S' + inttostr(ns) + ' pid=' + dec2hex(pid) + ' Len=' + inttostr(len) + ' >' + time_now + #13 + _data + #13#13; sprintf(mon_frm, "%s R%d S%d pid=%X Len=%d>[%s%c]%s\r%s\r", AGW_path, nr, ns, pid, len, ShortDateTime(), TR, codestr, _data); break; case U_FRM: if (f_id == U_UI) { sprintf(mon_frm, "%s pid=%X Len=%d>[%s%c]%s\r%s\r", AGW_path, pid, len, ShortDateTime(), TR, codestr, _data); // "= AGW_path + ctrl + '>' + time_now + #13; } else if (f_id == U_FRMR) { sprintf(mon_frm, "%s>%02x %02x %02x[%s]\r", AGW_path, datap[0], datap[1], datap[2], ShortDateTime()); // "= AGW_path + ctrl + '>' + time_now + #13; } else sprintf(mon_frm, "%s>[%s%c]%s\r", AGW_path, ShortDateTime(), TR, codestr); // "= AGW_path + ctrl + '>' + time_now + #13; break; case S_FRM: // mon_frm = AGW_path + ctrl + ' R' + inttostr(nr) + ' >' + time_now + #13; sprintf(mon_frm, "%s R%d>[%s%c]%s\r", AGW_path, nr, ShortDateTime(), TR, codestr); // "= AGW_path + ctrl + '>' + time_now + #13; break; } sprintf(FrameData, "%s", mon_frm); return FrameData; } /* procedure TForm1.RX2TX(snd_ch byte); begin if snd_status[snd_ch] = SND_IDLE then begin ptton(snd_ch); starttx(snd_ch); end; end; function TForm1.frame_monitor(s,code string; tx_stat boolean) string; var len word; s_tx_stat string; time_now,s1,c,p string; callfrom,callto,digi,path,data,frm string; frm_body string; pid,nr,ns,f_type,f_id byte; rpt,cr,pf boolean; i word; begin decode_frame(s,path,data,pid,nr,ns,f_type,f_id,rpt,pf,cr); len = length(data); // NETROM parsing if pid = $CF then data = parse_NETROM(data,f_id); // IP parsing if pid = $CC then data = parse_IP(data); // ARP parsing if pid = $CD then data = parse_ARP(data); // get_monitor_path(path,CallTo,CallFrom,Digi); if cr then begin c = "C"; if pf then p = " P" else p = ""; end else begin c = "R"; if pf then p = " F" else p = ""; end; frm = "UNKN"; case f_id of I_I frm = "I"; S_RR frm = "RR"; S_RNR frm = "RNR"; S_REJ frm = "REJ"; U_SABM frm = "SABM"; U_DISC frm = "DISC"; U_DM frm = "DM"; U_UA frm = "UA"; U_FRMR frm = "FRMR"; U_UI frm = "UI"; end; case tx_stat of TRUE s_tx_stat = "T"; FALSE s_tx_stat = "R"; end; s1 = ""; if code<>"" then code = " ["+code+"]"; if UTC_Time then time_now = " [UTC"+get_UTC_time+s_tx_stat+"]" else time_now = " ["+FormatDateTime("hhmmss",now)+s_tx_stat+"]"; if digi = "" then frm_body = "Fm "+CallFrom+" To "+CallTo+" <"+frm+" "+c+p else frm_body = "Fm "+CallFrom+" To "+CallTo+" Via "+Digi+" <"+frm+" "+c+p; case f_type of I_FRM frm_body = frm_body+" R"+inttostr(nr)+" S"+inttostr(ns)+" Pid = "+dec2hex(pid)+" Len = "+inttostr(len)+">"+time_now+code+#13+data; U_FRM if f_id = U_UI then frm_body = frm_body+" Pid = "+dec2hex(pid)+" Len = "+inttostr(len)+">"+time_now+code+#13+data else if f_id = U_FRMR then begin data = copy(data+#0#0#0,1,3); frm_body = frm_body+">"+time_now+code+#13+inttohex((byte(data[1]) shl 16) or (byte(data[2]) shl 8) or byte(data[3]),6) end else frm_body = frm_body+">"+time_now+code; S_FRM frm_body = frm_body+" R"+inttostr(nr)+">"+time_now+code; end; for i = 1 to length(frm_body) do begin if frm_body[i]>#31 then s1 = s1+frm_body[i]; if frm_body[i] = #13 then s1 = s1+#13#10; if frm_body[i] = #10 then s1 = s1+""; if frm_body[i] = #9 then s1 = s1+#9; end; result = s1; end; procedure TForm1.waterfall_init; begin bm[1] = TBitMap.Create; bm[2] = TBitMap.Create; bm1 = TBitMap.Create; bm2 = TBitMap.Create; bm3 = TBitMap.Create; bm[1].pixelformat = pf32bit; bm[2].pixelformat = pf32bit; bm1.pixelformat = pf32bit; bm2.pixelformat = pf32bit; bm3.pixelformat = pf32bit; bm[1].Height = PaintBox1.Height-20; bm[1].Width = PaintBox1.width; bm[2].Height = PaintBox1.Height-20; bm[2].Width = PaintBox1.width; bm1.Height = 20; bm1.Width = PaintBox1.width; bm3.Height = PaintBox1.Height; bm3.Width = PaintBox1.width; end; procedure TForm1.waterfall_free; begin bm[1].Free; bm[2].Free; bm1.Free; bm2.Free; bm3.Free; end; procedure TForm1.StartAGW; begin try ServerSocket1.Port = AGWPort; ServerSocket1.Active = AGWServ; except ServerSocket1.Active = FALSE; MessageDlg("AGW host port is busy!", mtWarning,[mbOk],0); end; end; procedure TForm1.StartKISS; begin try ServerSocket2.Port = KISSPort; ServerSocket2.Active = KISSServ; except ServerSocket2.Active = FALSE; MessageDlg("KISS port is busy!", mtWarning,[mbOk],0); end; end; procedure fft_window_init; var mag single; i word; begin mag = 2*pi/(FFTSize-1); for i = 0 to FFTSize-1 do fft_window_arr[i] = 0.5-0.5*cos(i*mag); //hann end; procedure TForm1.FormCreate(Sender TObject); begin if hPrevInst <> 0 then begin MessageDlg("Программа уже запущена!", mtError, [mbOk], 0); Application.Terminate; end; RS = TReedSolomon.Create(Self); MainThreadHandle = GetCurrentThread; form1.Caption = MODEM_CAPTION+" - Ver "+MODEM_VERSION; cur_dir = ExtractFilePath(Application.ExeName); fft_window_init; detector_init; kiss_init; agw_init; ax25_init; init_raduga; waterfall_init; ReadIni; show_combobox; show_grid_title; show_mode_panels; show_panels; wf_pointer(1); wf_pointer(2); wf_Scale; ChangePriority; Visible = TRUE; StartAGW; StartKISS; PTTOpen; startrx; TimerEvent = TIMER_EVENT_OFF; if (debugmode and DEBUG_TIMER) = 0 then create_timer1; if MinOnStart then WindowState = wsMinimized; end; procedure TForm1.TrackBar1Change(Sender TObject); begin dcd_threshold = TrackBar1.position; end; */ void Timer_Event2() { if (TimerStat2 == TIMER_BUSY || TimerStat2 == TIMER_OFF) return; TimerStat2 = TIMER_BUSY; // show_grid(); /* if (mod_icon_status = MOD_WAIT) then inc(icon_timer); if icon_timer = 10 then mod_icon_status = MOD_IDLE; if (mod_icon_status<>MOD_WAIT) and (mod_icon_status<>last_mod_icon_status) then begin icon_timer = 0; case mod_icon_status of MOD_IDLE form1.CoolTrayIcon1.IconIndex = 0; MOD_RX begin form1.CoolTrayIcon1.IconIndex = 1; mod_icon_status = MOD_WAIT; end; MOD_TX form1.CoolTrayIcon1.IconIndex = 2; end; last_mod_icon_status = mod_icon_status; end; //*/ TimerStat2 = TIMER_FREE; } /* procedure TimeProc1(uTimerId, uMesssage UINT; dwUser, dw1, dw2 DWORD); stdcall; begin TimerEvent = TIMER_EVENT_ON; end; procedure TForm1.create_timer1; var TimeEpk cardinal; begin TimeEpk = 100; TimerId1 = TimeSetEvent(TimeEpk,0,@TimeProc1,0,TIME_PERIODIC); end; procedure TForm1.free_timer1; begin TimerStat1 = TIMER_OFF; timeKillEvent(TimerId1); end; */ /* procedure TForm1.PaintBox1MouseMove(Sender TObject; Shift TShiftState; X, Y Integer); var low,high word; begin if CheckBox1.Checked then exit; if not mouse_down[1] then Exit; rx_freq[1] = round(x*RX_SampleRate/FFTSize); low = round(rx_shift[1]/2+Rcvr[1]*rcvr_offset[1]+1); high = round(rx_samplerate/2-(rx_shift[1]/2+Rcvr[1]*rcvr_offset[1])); if (rx_freq[1]-low)<0 then rx_freq[1] = low; if (high-rx_freq[1])<0 then rx_freq[1] = high; tx_freq[1] = rx_freq[1]; show_freq_a; end; procedure TForm1.PaintBox3MouseMove(Sender TObject; Shift TShiftState; X, Y Integer); var low,high word; begin if CheckBox1.Checked then exit; if not mouse_down[2] then Exit; rx_freq[2] = round(x*RX_SampleRate/FFTSize); low = round(rx_shift[2]/2+Rcvr[2]*rcvr_offset[2]+1); high = round(rx_samplerate/2-(rx_shift[2]/2+Rcvr[2]*rcvr_offset[2])); if (rx_freq[2]-low)<0 then rx_freq[2] = low; if (high-rx_freq[2])<0 then rx_freq[2] = high; tx_freq[2] = rx_freq[2]; show_freq_b; end; procedure TForm1.PaintBox1MouseUp(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); begin mouse_down[1] = FALSE; end; procedure TForm1.PaintBox3MouseUp(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); begin mouse_down[2] = FALSE; end; procedure TForm1.PaintBox1MouseDown(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); var low,high word; begin if CheckBox1.Checked then exit; if not (ssLeft in shift) then Exit; mouse_down[1] = TRUE; rx_freq[1] = round(x*RX_SampleRate/FFTSize); low = round(rx_shift[1]/2+Rcvr[1]*rcvr_offset[1]+1); high = round(rx_samplerate/2-(rx_shift[1]/2+Rcvr[1]*rcvr_offset[1])); if (rx_freq[1]-low)<0 then rx_freq[1] = low; if (high-rx_freq[1])<0 then rx_freq[1] = high; tx_freq[1] = rx_freq[1]; show_freq_a; end; procedure TForm1.PaintBox3MouseDown(Sender TObject; Button TMouseButton; Shift TShiftState; X, Y Integer); var low,high word; begin if CheckBox1.Checked then exit; if not (ssLeft in shift) then Exit; mouse_down[2] = TRUE; rx_freq[2] = round(x*RX_SampleRate/FFTSize); low = round(rx_shift[2]/2+Rcvr[2]*rcvr_offset[2]+1); high = round(rx_samplerate/2-(rx_shift[2]/2+Rcvr[2]*rcvr_offset[2])); if (rx_freq[2]-low)<0 then rx_freq[2] = low; if (high-rx_freq[2])<0 then rx_freq[2] = high; tx_freq[2] = rx_freq[2]; show_freq_b; end; procedure TForm1.ServerSocket1ClientRead(Sender TObject; Socket TCustomWinSocket); var s string; begin s = Socket.ReceiveText; AGW_explode_frame(Socket.sockethandle,s); end; procedure TForm1.ServerSocket1ClientDisconnect(Sender TObject; Socket TCustomWinSocket); begin del_incoming_mycalls_by_sock(socket.SocketHandle); AGW_del_socket(socket.SocketHandle); end; procedure TForm1.ServerSocket1ClientError(Sender TObject; Socket TCustomWinSocket; ErrorEvent TErrorEvent; var ErrorCode Integer); begin del_incoming_mycalls_by_sock(socket.SocketHandle); AGW_del_socket(socket.SocketHandle); ErrorCode = 0; end; procedure TForm1.ServerSocket1ClientConnect(Sender TObject; Socket TCustomWinSocket); begin agw_add_socket(Socket.sockethandle); end; procedure TForm1.OutputVolume1Click(Sender TObject); var s string; begin s = "SndVol32.exe -D"+inttostr(SND_TX_DEVICE); WinExec(pchar(s),SW_SHOWNORMAL); end; procedure TForm1.InputVolume1Click(Sender TObject); var s string; begin s = "SndVol32.exe -R -D"+inttostr(SND_RX_DEVICE); WinExec(pchar(s),SW_SHOWNORMAL); end; procedure TForm1.CoolTrayIcon1Click(Sender TObject); begin CoolTrayIcon1.ShowMainForm; end; procedure TForm1.CoolTrayIcon1Cycle(Sender TObject; NextIndex Integer); begin CoolTrayIcon1.IconIndex = 2; CoolTrayIcon1.CycleIcons = FALSE; end; procedure TForm1.ABout1Click(Sender TObject); begin Form2.ShowModal; end; procedure TForm1.put_frame(snd_ch byte; frame,code string; tx_stat,excluded boolean); var s string; begin if RxRichedit1.Focused then Windows.SetFocus(0); if code = "NON-AX25" then s = inttostr(snd_ch)+" ["+FormatDateTime("hhmmss",now)+"R]" else s = inttostr(snd_ch)+""+frame_monitor(frame,code,tx_stat); //RxRichedit1.Lines.BeginUpdate; RxRichedit1.SelStart = length(RxRichedit1.text); RxRichEdit1.SelLength = length(s); case tx_stat of TRUE RxRichEdit1.SelAttributes.Color = clMaroon; FALSE RxRichEdit1.SelAttributes.Color = clBlack; end; if excluded then RxRichEdit1.SelAttributes.Color = clGreen; RxRichedit1.SelText = s+#10; if RxRichedit1.Lines.Count>nr_monitor_lines then repeat RxRichedit1.Lines.Delete(0); until RxRichedit1.Lines.Count = nr_monitor_lines; RxRichedit1.HideSelection = FALSE; RxRichedit1.SelStart = length(RxRichedit1.text); RxRichedit1.SelLength = 0; RxRichedit1.HideSelection = TRUE; //RxRichedit1.Lines.EndUpdate; end; procedure TForm1.show_mode_panels; begin panel8.Align = alNone; panel6.Align = alNone; if dualchan then panel6.Visible = TRUE else panel6.Visible = FALSE; panel8.Align = alLeft; panel6.Align = alLeft; end; procedure TForm1.show_panels; var i byte; begin panel1.Align = alNone; panel2.Align = alNone; panel3.Align = alNone; panel4.Align = alNone; panel5.Align = alNone; for i = 1 to 5 do case i of 1 panel1.Visible = panels[i]; 2 panel5.Visible = panels[i]; 3 panel3.Visible = panels[i]; 4 panel4.Visible = panels[i]; 5 panel2.Visible = panels[i]; end; panel1.Align = alBottom; panel5.Align = alBottom; panel3.Align = alBottom; panel2.Align = alTop; panel4.Align = alClient; end; procedure TForm1.Secondwaterfall1Click(Sender TObject); begin case Secondwaterfall1.Checked of TRUE Secondwaterfall1.Checked = FALSE; FALSE Secondwaterfall1.Checked = TRUE; end; panels[1] = Secondwaterfall1.Checked; show_panels; end; procedure TForm1.Firstwaterfall1Click(Sender TObject); begin case Firstwaterfall1.Checked of TRUE Firstwaterfall1.Checked = FALSE; FALSE Firstwaterfall1.Checked = TRUE; end; panels[2] = Firstwaterfall1.Checked; show_panels; end; procedure TForm1.Statustable1Click(Sender TObject); begin case Statustable1.Checked of TRUE Statustable1.Checked = FALSE; FALSE Statustable1.Checked = TRUE; end; panels[3] = Statustable1.Checked; show_panels; end; procedure TForm1.Monitor1Click(Sender TObject); begin case Monitor1.Checked of TRUE Monitor1.Checked = FALSE; FALSE Monitor1.Checked = TRUE; end; panels[4] = Monitor1.Checked; show_panels; end; procedure TForm1.Devices1Click(Sender TObject); begin if (ptt = "EXT") or (ptt = "CAT") then Form3.Button3.Enabled = TRUE else Form3.Button3.Enabled = FALSE; Form3.GetDeviceInfo; form3.ShowModal; end; procedure TForm1.FormPaint(Sender TObject); begin RxRichedit1.HideSelection = FALSE; RxRichedit1.SelStart = length(RxRichedit1.text); RxRichedit1.SelLength = 0; RxRichedit1.HideSelection = TRUE; end; procedure TForm1.Filters1Click(Sender TObject); begin Form5.Show_modem_settings; end; procedure TForm1.Clearmonitor1Click(Sender TObject); begin RxRichEdit1.Clear; frame_count = 0; single_frame_count = 0; end; procedure TForm1.Copytext1Click(Sender TObject); begin RxRichEdit1.CopyToClipboard; end; procedure TForm1.ApplicationEvents1Minimize(Sender TObject); begin if stop_wf then w_state = WIN_MINIMIZED; end; procedure TForm1.ApplicationEvents1Restore(Sender TObject); begin w_state = WIN_MAXIMIZED; end; procedure TForm1.ServerSocket2ClientConnect(Sender TObject; Socket TCustomWinSocket); begin KISS_add_stream(socket.sockethandle); end; procedure TForm1.ServerSocket2ClientDisconnect(Sender TObject; Socket TCustomWinSocket); begin KISS_del_stream(socket.sockethandle); end; procedure TForm1.ServerSocket2ClientError(Sender TObject; Socket TCustomWinSocket; ErrorEvent TErrorEvent; var ErrorCode Integer); begin KISS_del_stream(socket.sockethandle); ErrorCode = 0; end; procedure TForm1.ServerSocket2ClientRead(Sender TObject; Socket TCustomWinSocket); var data string; begin data = socket.ReceiveText; KISS_on_data_in(socket.sockethandle,data); end; procedure TForm1.Font1Click(Sender TObject); begin FontDialog1.Font = RXRichEdit1.Font; if FontDialog1.Execute then begin RXRichEdit1.SelStart = 0; RXRichEdit1.SelLength = Length(RXRichEdit1.Text); RXRichEdit1.SelAttributes.Size = FontDialog1.Font.Size; RXRichEdit1.SelAttributes.Name = FontDialog1.Font.Name; RXRichEdit1.Font.Size = FontDialog1.Font.Size; RXRichEdit1.Font.Name = FontDialog1.Font.Name; WriteIni; end; end; procedure TForm1.Calibration1Click(Sender TObject); begin Form6.ShowModal; end; procedure TForm1.ComboBox1Change(Sender TObject); begin Speed[1] = get_idx_by_name(ComboBox1.Text); init_speed(1); windows.setfocus(0); end; procedure TForm1.ComboBox1KeyDown(Sender TObject; var Key Word; Shift TShiftState); begin key = 0; windows.SetFocus(0); end; procedure TForm1.ComboBox1KeyPress(Sender TObject; var Key Char); begin key = #0; windows.SetFocus(0); end; procedure TForm1.ComboBox2Change(Sender TObject); begin Speed[2] = get_idx_by_name(ComboBox2.Text); init_speed(2); windows.setfocus(0); end; procedure TForm1.FormDestroy(Sender TObject); var snd_ch byte; begin stoprx; for snd_ch = 1 to 2 do if snd_status[snd_ch] = SND_TX then stoptx(snd_ch); if (debugmode and DEBUG_TIMER) = 0 then free_timer1; TimerStat2 = TIMER_OFF; PTTClose; ax25_free; agw_free; kiss_free; detector_free; RS.Free; waterfall_free; WriteIni; end; end. */