#SX1509_INCLUDE=sx1509
# uncomment the line to below include support local CW keyer
-#LOCALCW_INCLUDE=LOCALCW
+LOCALCW_INCLUDE=LOCALCW
# uncomment the line below to include MCP23017 I2C
#I2C_INCLUDE=I2C
#LIMESDR_INCLUDE=LIMESDR
# uncomment the line below when Radioberry radio cape is plugged in
-#RADIOBERRY_INCLUDE=RADIOBERRY
+RADIOBERRY_INCLUDE=RADIOBERRY
ifeq ($(RADIOBERRY_INCLUDE),RADIOBERRY)
RADIOBERRY_OPTIONS=-D RADIOBERRY
ifeq ($(LOCALCW_INCLUDE),LOCALCW)
LOCALCW_OPTIONS=-D LOCALCW
LOCALCW_SOURCES= \
-beep.c \
iambic.c
LOCALCW_HEADERS= \
-beep.h \
iambic.h
LOCALCW_OBJS= \
-beep.o \
iambic.o
endif
int n_output_devices=0;
//int n_selected_output_device=-1;
+int playback_cw_offset = 0;
+unsigned char *playback_cw_buffer;
+
int audio_open_output(RECEIVER *rx) {
int err;
snd_pcm_hw_params_t *hw_params;
rx->playback_offset=0;
rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
+
+ playback_cw_buffer = (unsigned char *)malloc(OUTPUT_BUFFER_SIZE);
return 0;
}
free(mic_buffer);
mic_buffer=NULL;
}
+ if (playback_cw_buffer!=NULL) {
+ free(playback_cw_buffer);
+ playback_cw_buffer=NULL;
+ }
+}
+
+//write side tone for cw...
+int cw_audio_write(double sample){
+
+ snd_pcm_sframes_t delay;
+ int error;
+ long trim;
+ RECEIVER *rx = receiver[0];
+ //fprintf(stderr, "cw audio write \n");
+ if(rx->playback_handle!=NULL && playback_cw_buffer!=NULL) {
+
+ // convert double sample to short and assign sample to L and R channel.
+ short ssample = (short)(sample*32767.0);
+ playback_cw_buffer[playback_cw_offset++] = ssample;
+ playback_cw_buffer[playback_cw_offset++] = ssample>>8;
+ playback_cw_buffer[playback_cw_offset++] = ssample;
+ playback_cw_buffer[playback_cw_offset++] = ssample>>8;
+
+ if(playback_cw_offset==OUTPUT_BUFFER_SIZE) {
+ trim=0;
+
+ if(snd_pcm_delay(rx->playback_handle,&delay)==0) {
+ if(delay>2048) {
+ trim=delay-2048;
+ }
+ }
+
+ if ((error = snd_pcm_writei (rx->playback_handle, playback_cw_buffer, audio_buffer_size-trim)) != audio_buffer_size-trim) {
+ if(error==-EPIPE) {
+ if ((error = snd_pcm_prepare (rx->playback_handle)) < 0) {
+ fprintf (stderr, "audio_write: cannot prepare audio interface for use (%s)\n",
+ snd_strerror (error));
+ return -1;
+ }
+ if ((error = snd_pcm_writei (rx->playback_handle, playback_cw_buffer, audio_buffer_size-trim)) != audio_buffer_size) {
+ fprintf (stderr, "audio_write: write to audio interface failed (%s)\n",
+ snd_strerror (error));
+ return -1;
+ }
+ }
+ }
+ playback_cw_offset=0;
+ }
+ }
+ return 0;
}
int audio_write(RECEIVER *rx,short left_sample,short right_sample) {
return 0;
}
+
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
return 0;
printf("Setting of swparams failed: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
-
+
samples = malloc((period_size * channels * snd_pcm_format_physical_width(format)) / 8);
if (samples == NULL) {
printf("No enough memory\n");
#ifdef LOCALCW
static void cwAlert(int gpio, int level, uint32_t tick) {
- if (cw_keyer_internal == 0 && (mode==modeCWL || mode==modeCWU))
+ fprintf(stderr,"init cwAlert\n");
+ if (cw_keyer_internal == 0 ){
+ fprintf(stderr,"call keyer_event...\n");
keyer_event(gpio, cw_active_level == 0 ? level : (level==0));
+ }
}
#endif
fprintf(stderr,"Cannot initialize GPIO\n");
return -1;
}
+
+// required for softtone in iambic.c
+// if (wiringPiSetup () < 0) {
+// printf ("Unable to setup wiringPi: %s\n", strerror (errno));
+// return -1;
+// }
+
if(ENABLE_FUNCTION_BUTTON) {
setup_button(FUNCTION_BUTTON, functionAlert);
#include "radio.h"
#include "new_protocol.h"
#include "iambic.h"
-#include "beep.h"
+#include "transmitter.h"
static void* keyer_thread(void *arg);
static pthread_t keyer_thread_id;
// set to 0 to use the PI's hw:0 audio out for sidetone
-#define SIDETONE_GPIO 0 // this is in wiringPi notation
+#define SIDETONE_GPIO 0 // this is in wiringPi notation // tried 4 working great.
#define MY_PRIORITY (90)
#define MAX_SAFE_STACK (8*1024)
kdot = &kcwl;
kdash = &kcwr;
}
- beep_vol(cw_keyer_sidetone_volume);
- beep_freq = cw_keyer_sidetone_frequency;
+
}
void keyer_event(int gpio, int level) {
if (keyer_out != state) {
keyer_out = state;
if(protocol==NEW_PROTOCOL) schedule_high_priority(9);
+ fprintf(stderr,"set_keyer_out keyer_out= %d\n", keyer_out);
if (state)
if (SIDETONE_GPIO)
softToneWrite (SIDETONE_GPIO, cw_keyer_sidetone_frequency);
else {
- beep_mute(1);
+ cw_sidetone_mute(1);
}
else
if (SIDETONE_GPIO)
softToneWrite (SIDETONE_GPIO, 0);
else {
- beep_mute(0);
+ cw_sidetone_mute(0);
}
}
}
struct timespec loop_delay;
int interval = 1000000; // 1 ms
-fprintf(stderr,"keyer_thread\n");
+fprintf(stderr,"keyer_thread state running= %d\n", running);
while(running) {
sem_wait(&cw_event);
void keyer_close() {
running=0;
- beep_close();
}
int keyer_init() {
running = 0;
}
- //stack_prefault();
-
-
-/*
- if (wiringPiSetup () < 0) {
- fprintf(stderr,"pthread_create for keyer_thread failed %d\n", rc);
- exit(-1);
- }
-*/
-
- if (SIDETONE_GPIO)
+ if (SIDETONE_GPIO){
softToneCreate(SIDETONE_GPIO);
- else {
- beep_init();
- beep_vol(cw_keyer_sidetone_volume);
}
rc = sem_init(&cw_event, 0, 0);
#ifdef GPIO
+ fprintf(stderr,"keyer.....\n");
if(gpio_init()<0) {
fprintf(stderr,"GPIO failed to initialize\n");
}
#ifdef LOCALCW
// init local keyer if enabled
- else if (cw_keyer_internal == 0)
+ else if (cw_keyer_internal == 0) {
+ fprintf(stderr,"Initialize keyer.....\n");
keyer_update();
+ }
#endif
#endif
#define min(x,y) (x<y?x:y)
#define max(x,y) (x<y?y:x)
+double getNextSideToneSample();
+
static int filterLow;
static int filterHigh;
+int key = 0;
+
static gint update_out_of_band(gpointer data) {
TRANSMITTER *tx=(TRANSMITTER *)data;
tx->out_of_band=0;
break;
#endif
default:
- if(mode==modeCWL || mode==modeCWU || tune) {
- mic_sample_double=0.0;
+ if (tune) {
+ mic_sample_double=0.0;
+ }
+ else if(mode==modeCWL || mode==modeCWU) {
+ if (isTransmitting()) {
+ if (key == 1) {
+ mic_sample_double = getNextSideToneSample();
+ cw_audio_write(mic_sample_double * cw_keyer_sidetone_volume/ 127.0);
+ mic_sample_double = mic_sample_double * 200000; //* amplitude
+ } else mic_sample_double=0.0;
+ }
} else {
sample=mic_sample<<16;
mic_sample_double=(1.0 / 2147483648.0) * (double)(sample);
}
-//fprintf(stderr,"add_mic_sample: id=%d sample=%f (%d,%ld)\n",tx->id,mic_sample_double,mic_sample,sample);
tx->mic_input_buffer[tx->samples*2]=mic_sample_double;
tx->mic_input_buffer[(tx->samples*2)+1]=mic_sample_double;
tx->samples++;
}
}
+void cw_sidetone_mute(int mute){
+ key = mute;
+}
+
+int asteps = 0;
+double timebase = 0.0;
+#define TIMESTEP (1.0 / 48000)
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+double getNextSideToneSample() {
+ double angle = cw_keyer_sidetone_frequency * 2 * M_PI * timebase;
+ timebase += TIMESTEP;
+ asteps++;
+ if (asteps == 48000) {
+ timebase = 0.0;
+ asteps = 0;
+ }
+ return sin(angle);
+}
+
extern void transmitter_save_state(TRANSMITTER *tx);
extern void transmitter_set_out_of_band(TRANSMITTER *tx);
+
+extern void cw_sidetone_mute(int mute);
#endif