]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
cw for radioberry
authorpa3gsb <pa3gsb@gmail.com>
Tue, 7 Nov 2017 16:09:55 +0000 (17:09 +0100)
committerpa3gsb <pa3gsb@gmail.com>
Tue, 7 Nov 2017 16:09:55 +0000 (17:09 +0100)
Makefile
audio.c
beep.c
gpio.c
iambic.c
radio.c
transmitter.c
transmitter.h

index f6d25abbe304ae51a150efcc53ba2cfa9cb5d1c8..f2bbea0cf840cb4654ffeb29662cdc9b37751774 100644 (file)
--- 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 0a0fab659786d589a053399d45ebcb411481fcca..b563af1688780bfd4a593a7a5bccdc7b9d1efa98 100644 (file)
--- 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 7fd966946d19fc5a6066984e4766d081c58f8d5f..917887331f2e3315efda6d5f7b68b1e0d6cedecf 100644 (file)
--- 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 d3ec3034f4694f5c8da1f51e6b85984db5e72573..8b16f1122cdaf07ac46462a501f4d7f93d5bb2cc 100644 (file)
--- 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);
index aa94ecfbe8bbec98411d0c527941627c4230c08a..36f561144390a0ab0b2c709c72194a9cdfd19407 100644 (file)
--- a/iambic.c
+++ b/iambic.c
 #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 bf571a561c25ef9b1eb05bf4fddd7b8566077b84..3be4121056fb94dbc2bf2efa7cbb9e18578c1fc8 100644 (file)
--- 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
   
index 51c8264bce79d3b2159f75760952e71916b3c6b7..ea37b2e91699269d9aebd42648c693cb11e15370 100644 (file)
 #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;
@@ -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);
+}      
+
index c4eeda2cfb7644f4ace9b76b20304a74f504764d..6ff50aa30f5bbe64a2bb4a1eddb713032ef6d3f4 100644 (file)
@@ -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