Skip to content

Update Makefile #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Prev Previous commit
Next Next commit
add audio channel option for ptt (Windows only)
  • Loading branch information
va7yaa committed Jan 13, 2017
commit 3b59838237e3b9842f858f3050e53be43447f1fa
2 changes: 1 addition & 1 deletion Makefile.win
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_9600.o hd
hdlc_rec2.o multi_modem.o redecode.o rdq.o rrbb.o dlq.o \
fcs_calc.o ax25_pad.o \
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o \
gen_tone.o morse.o audio_win.o audio_ptt_win.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o \
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o nmea.o serial_port.o log.o telemetry.o \
dwgps.o dwgpsnmea.o dtime_now.o \
Expand Down
10 changes: 10 additions & 0 deletions audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,16 @@ struct audio_s {
int ptt_invert; /* Invert the output. */
int ptt_invert2; /* Invert the secondary output. */

int ptt_channel; /* Channel number for audio PTT. */
int ptt_frequency; /* Audio frequency for audio PTT. */
#if __WIN32__
HANDLE ptt_start; /* Handle for event that starts ptt tone. */
HANDLE ptt_stop; /* Handle for event that stops ptt tone. */
HANDLE ptt_close; /* Handle for event that closes ptt. */
#else

#endif

#ifdef USE_HAMLIB

int ptt_model; /* HAMLIB model. -1 for AUTO. 2 for rigctld. Others are radio model. */
Expand Down
20 changes: 20 additions & 0 deletions audio_ptt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//


11 changes: 11 additions & 0 deletions audio_ptt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

#ifndef AUDIO_PTT_H
#define AUDIO_PTT_H 1

#if __WIN32__
extern HANDLE start_ptt_thread ( struct audio_s *pa, int ch );
#else
extern int start_ptt_thread ( struct audio_s *pa, int ch );
#endif

#endif
193 changes: 193 additions & 0 deletions audio_ptt_win.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@

//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//


/*------------------------------------------------------------------
*
* Module: audio_ptt_win.c
*
* Purpose: Interface to audio device commonly called a "sound card" for
* historical reasons.
*
* This version uses the native Windows sound interface.
*
*---------------------------------------------------------------*/

#if __WIN32__
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <math.h>

#include <windows.h>
#include <mmsystem.h>

#ifndef WAVE_FORMAT_96M16
#define WAVE_FORMAT_96M16 0x40000
#define WAVE_FORMAT_96S16 0x80000
#endif

#include "direwolf.h"
#include "audio.h"
#include "audio_stats.h"
#include "textcolor.h"
#include "ptt.h"
#include "demod.h" /* for alevel_t & demod_get_audio_level() */
#include "audio_ptt.h"

static struct audio_s *save_audio_config_p;

static unsigned __stdcall ptt_thread ( void *arg );

HANDLE start_ptt_thread (struct audio_s *pa , int ch)
{
save_audio_config_p = pa;

return (HANDLE)_beginthreadex (NULL, 0, ptt_thread, (void*)(long)ch, 0, NULL);
}

unsigned __stdcall ptt_thread (void *arg)
{
WAVEFORMATEX wf;
HWAVEOUT hWaveOut;
int ch = (int)(long)arg; // channel number.
int channel = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_channel;
int freq = save_audio_config_p->achan[channel].octrl[OCTYPE_PTT].ptt_frequency;
int a = ACHAN2ADEV( channel );
int err;

if( save_audio_config_p->adev[a].defined ) {
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = save_audio_config_p->adev[a].num_channels;
wf.nSamplesPerSec = save_audio_config_p->adev[a].samples_per_sec;
wf.wBitsPerSample = save_audio_config_p->adev[a].bits_per_sample;
wf.nBlockAlign = ( wf.wBitsPerSample / 8 ) * wf.nChannels;
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
wf.cbSize = 0;

/*
* Open the audio output device.
* Soundcard is only possibility at this time.
*/

err = waveOutOpen ( &hWaveOut, atoi( save_audio_config_p->adev[a].adevice_out ), &wf, (DWORD_PTR)NULL, 0, CALLBACK_NULL );
if( err == MMSYSERR_NOERROR ) {
WAVEHDR waveHeader;
SHORT* pnData;
SHORT sample;
int nsamples = save_audio_config_p->adev[a].samples_per_sec / freq;
int i;

if( save_audio_config_p->adev[a].num_channels == 1 ) {
waveHeader.dwBufferLength = 1 * nsamples * sizeof( SHORT );
}
else {
waveHeader.dwBufferLength = 2 * nsamples * sizeof( SHORT );
}
waveHeader.lpData = malloc( waveHeader.dwBufferLength );
waveHeader.dwUser = 0;
waveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
waveHeader.dwLoops = 0xFFFF;

pnData = (SHORT*)waveHeader.lpData;

if( save_audio_config_p->adev[a].num_channels == 1 ) {
for( i = 0; i < nsamples; i++ ) {
sample = (SHORT)( 32000.0 * sin( ( (double)i / (double)nsamples ) * 2.0 * M_PI ) );
pnData[i] = sample;
}
}
else {
for( i = 0; i < nsamples; i++ ) {
sample = (SHORT)( 32000.0 * sin( ( (double)i / (double)nsamples ) * 2.0 * M_PI ) );
if( channel == ADEVFIRSTCHAN( a ) ) {

// Stereo, left channel.

pnData[i*2 + 0] = sample;
pnData[i*2 + 1] = 0;
}
else {

// Stereo, right channel.

pnData[i*2 + 0] = 0;
pnData[i*2 + 1] = sample;
}
}
}

err = waveOutPrepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
if( err == MMSYSERR_NOERROR ) {
HANDLE handles[3];
DWORD dwWait;

handles[0] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_start;
handles[1] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_stop;
handles[2] = save_audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_close;

while( 1 )
{
dwWait = WaitForMultipleObjects ( 3, handles, FALSE, INFINITE );

if( dwWait == WAIT_OBJECT_0 + 0 )
{
//
// ptt_set on
//

waveOutWrite ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );
}
else if( dwWait == WAIT_OBJECT_0 + 1 )
{
//
// ptt_set off
//

waveOutReset ( hWaveOut );
}
else if( dwWait == WAIT_OBJECT_0 + 2 )
{
//
// close
//

waveOutReset ( hWaveOut );
waveOutUnprepareHeader ( hWaveOut, &waveHeader, sizeof( WAVEHDR ) );

break;
}
}
}

waveOutClose ( hWaveOut );

free( waveHeader.lpData );
}
}

return 0;
}
#endif
50 changes: 48 additions & 2 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_audio_config->achan[channel].octrl[ot].ptt_lpt_bit = 0;
p_audio_config->achan[channel].octrl[ot].ptt_invert = 0;
p_audio_config->achan[channel].octrl[ot].ptt_invert2 = 0;
}
p_audio_config->achan[channel].octrl[ot].ptt_channel = 0;
p_audio_config->achan[channel].octrl[ot].ptt_frequency = PTT_FREQ_DEFAULT;
}

p_audio_config->achan[channel].dwait = DEFAULT_DWAIT;
p_audio_config->achan[channel].slottime = DEFAULT_SLOTTIME;
Expand Down Expand Up @@ -1582,8 +1584,52 @@ void config_init (char *fname, struct audio_s *p_audio_config,
dw_printf ("Config file line %d: %s with RIG is only available when hamlib support is enabled.\n", line, otname);
#endif
}
else if (strcasecmp( t, "CHN") == 0) {
else if (strcasecmp( t, "CHANNEL") == 0) {
t = split(NULL, 0);
if (t == NULL) {
text_color_set( DW_COLOR_ERROR );
dw_printf ("Config file line %d: Missing channel number for %s.\n", line, otname);
continue;
}

int channel_ptt = atoi(t);

if (channel_ptt < 0 || channel_ptt >= MAX_CHANS) {
text_color_set( DW_COLOR_ERROR );
dw_printf ( "Config file line %d: Invalid PTT channel number for %s.\n", line, otname );
continue;
}

if (channel == channel_ptt) {
text_color_set( DW_COLOR_ERROR );
dw_printf ( "Config file line %d: PTT channel number must not be the same as the channel number itself.\n", line );
continue;
}

int freq_ptt = PTT_FREQ_DEFAULT;

t = split(NULL, 0);
if (t != NULL) {
freq_ptt = atoi(t);

if (freq_ptt < PTT_FREQ_MIN || freq_ptt > PTT_FREQ_MAX) {
text_color_set( DW_COLOR_ERROR );
dw_printf ("Config file line %d: Invalid value %d for PTT frequency. Using default of %d.\n",
line, freq_ptt, PTT_FREQ_DEFAULT );

freq_ptt = PTT_FREQ_DEFAULT;
}
}

p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_AUDIO;
p_audio_config->achan[channel].octrl[ot].ptt_channel = channel_ptt;
p_audio_config->achan[channel].octrl[ot].ptt_frequency = freq_ptt;
#ifdef __WIN32__
p_audio_config->achan[channel].octrl[ot].ptt_start = CreateEvent (NULL, FALSE, FALSE, NULL);
p_audio_config->achan[channel].octrl[ot].ptt_stop = CreateEvent (NULL, FALSE, FALSE, NULL);
p_audio_config->achan[channel].octrl[ot].ptt_close = CreateEvent (NULL, FALSE, FALSE, NULL);
#else
#endif
}
else {

Expand Down
8 changes: 8 additions & 0 deletions direwolf.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
#define MAX_RIGS MAX_CHANS
#endif

/*
* PTT frequency settings
*/

#define PTT_FREQ_MIN 50
#define PTT_FREQ_MAX 20000
#define PTT_FREQ_DEFAULT 1000

/*
* Get audio device number for given channel.
* and first channel for given device.
Expand Down
Loading