From: pa3gsb Date: Tue, 7 Nov 2017 16:09:55 +0000 (+0100) Subject: cw for radioberry X-Git-Url: https://git.rkrishnan.org/uri/%3C?a=commitdiff_plain;h=14f5a0faa91f221885c40bbadf0c8c889faa7f1e;p=pihpsdr.git cw for radioberry --- diff --git a/Makefile b/Makefile index f6d25ab..f2bbea0 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ GPIO_INCLUDE=GPIO #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 @@ -52,7 +52,7 @@ endif #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 @@ -115,13 +115,10 @@ endif 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 diff --git a/audio.c b/audio.c index 0a0fab6..b563af1 100644 --- a/audio.c +++ b/audio.c @@ -76,6 +76,9 @@ char *output_devices[16]; 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; @@ -156,6 +159,8 @@ fprintf(stderr,"audio_open_output: selected=%d:%s\n",rx->audio_device,selected); rx->playback_offset=0; rx->playback_buffer=(unsigned char *)malloc(OUTPUT_BUFFER_SIZE); + + playback_cw_buffer = (unsigned char *)malloc(OUTPUT_BUFFER_SIZE); return 0; } @@ -288,6 +293,56 @@ void audio_close_input() { 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) { diff --git a/beep.c b/beep.c index 7fd9669..9178873 100644 --- a/beep.c +++ b/beep.c @@ -339,6 +339,7 @@ static void* beep_thread(void *arg) { 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; @@ -353,7 +354,7 @@ static void* beep_thread(void *arg) { 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"); diff --git a/gpio.c b/gpio.c index d3ec303..8b16f11 100644 --- a/gpio.c +++ b/gpio.c @@ -382,8 +382,11 @@ static void lockAlert(int gpio, int level, uint32_t tick) { #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 @@ -781,6 +784,13 @@ int gpio_init() { 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); diff --git a/iambic.c b/iambic.c index aa94ecf..36f5611 100644 --- a/iambic.c +++ b/iambic.c @@ -77,13 +77,13 @@ #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) @@ -147,8 +147,7 @@ void keyer_update() { kdot = &kcwl; kdash = &kcwr; } - beep_vol(cw_keyer_sidetone_volume); - beep_freq = cw_keyer_sidetone_frequency; + } void keyer_event(int gpio, int level) { @@ -173,17 +172,18 @@ void set_keyer_out(int state) { 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); } } } @@ -193,7 +193,7 @@ static void* keyer_thread(void *arg) { 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); @@ -367,7 +367,6 @@ fprintf(stderr,"keyer_thread: EXIT\n"); void keyer_close() { running=0; - beep_close(); } int keyer_init() { @@ -385,21 +384,8 @@ 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); diff --git a/radio.c b/radio.c index bf571a5..3be4121 100644 --- a/radio.c +++ b/radio.c @@ -442,13 +442,16 @@ fprintf(stderr,"receiver %d: height=%d y=%d\n",receiver[i]->id,rx_height,y); #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 diff --git a/transmitter.c b/transmitter.c index 51c8264..ea37b2e 100644 --- a/transmitter.c +++ b/transmitter.c @@ -42,9 +42,13 @@ #define min(x,y) (xout_of_band=0; @@ -639,13 +643,21 @@ void add_mic_sample(TRANSMITTER *tx,short mic_sample) { 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++; @@ -665,3 +677,24 @@ fprintf(stderr,"start tx display update timer: %d\n", 1000/tx->fps); } } +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); +} + diff --git a/transmitter.h b/transmitter.h index c4eeda2..6ff50aa 100644 --- a/transmitter.h +++ b/transmitter.h @@ -87,4 +87,6 @@ extern void add_mic_sample(TRANSMITTER *tx,short mic_sample); extern void transmitter_save_state(TRANSMITTER *tx); extern void transmitter_set_out_of_band(TRANSMITTER *tx); + +extern void cw_sidetone_mute(int mute); #endif