]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
spandsp DSP tweaks to avoid problems with the LPC10 code compiled with the latest...
authorSteve Underwood <steveu@x240.coppice.org>
Thu, 13 Jul 2017 23:29:20 +0000 (00:29 +0100)
committerSteve Underwood <steveu@x240.coppice.org>
Thu, 13 Jul 2017 23:29:20 +0000 (00:29 +0100)
33 files changed:
libs/spandsp/configure.ac
libs/spandsp/m4/ac_func_memmove.m4 [moved from libs/spandsp/m4/memmove.m4 with 100% similarity]
libs/spandsp/src/at_interpreter.c
libs/spandsp/src/awgn.c
libs/spandsp/src/data_modems.c
libs/spandsp/src/hdlc.c
libs/spandsp/src/image_translate.c
libs/spandsp/src/lpc10_analyse.c
libs/spandsp/src/lpc10_decode.c
libs/spandsp/src/lpc10_encdecs.h
libs/spandsp/src/lpc10_voicing.c
libs/spandsp/src/make_at_dictionary.c
libs/spandsp/src/make_cielab_luts.c
libs/spandsp/src/make_math_fixed_tables.c
libs/spandsp/src/make_modem_filter.c
libs/spandsp/src/make_t43_gray_code_tables.c
libs/spandsp/src/spandsp/at_interpreter.h
libs/spandsp/src/spandsp/data_modems.h
libs/spandsp/src/spandsp/g711.h
libs/spandsp/src/spandsp/private/awgn.h
libs/spandsp/src/spandsp/private/data_modems.h
libs/spandsp/src/spandsp/private/v18.h
libs/spandsp/src/spandsp/stdbool.h
libs/spandsp/src/spandsp/telephony.h
libs/spandsp/src/spandsp/v18.h
libs/spandsp/src/t30_logging.c
libs/spandsp/src/v17rx.c
libs/spandsp/src/v18.c
libs/spandsp/src/v8.c
libs/spandsp/tests/data_modems_tests.c
libs/spandsp/tests/dummy_modems_tests.c
libs/spandsp/tests/socket_harness.c
libs/spandsp/tests/socket_harness.h

index 4ec89525588f524d8a7675205c587374dc2fa2b6..b26b7927589c59d9d4a0c677f9c6755281a4e3dd 100644 (file)
@@ -37,7 +37,7 @@ m4_include(m4/ax_c99_features.m4)
 m4_include(m4/ax_check_export_capability.m4)
 m4_include(m4/ax_check_arm_neon.m4)
 m4_include(m4/ax_func_aligned_alloc.m4)
-m4_include(m4/memmove.m4)
+m4_include(m4/ac_func_memmove.m4)
 
 AC_CONFIG_SRCDIR([src/tone_generate.c])
 AC_CONFIG_AUX_DIR([config])
index 5d6dc4204354d88a7f066a06df81fc4548446b93..50f1df11d548b29a02ffa0ebde9d5b089a6ab9d5 100644 (file)
@@ -5594,6 +5594,15 @@ SPAN_DECLARE(void) at_set_modem_control_handler(at_state_t *s,
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(void) at_set_at_tx_handler(at_state_t *s,
+                                        at_tx_handler_t at_tx_handler,
+                                        void *at_tx_user_data)
+{
+    s->at_tx_handler = at_tx_handler;
+    s->at_tx_user_data = at_tx_user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(logging_state_t *) at_get_logging_state(at_state_t *s)
 {
     return &s->logging;
index fa33b1b4c5923794914efad13674947bb4a13764..04edfff3b4ae2b3076661d5b8a37cc5cdfe3a668 100644 (file)
 #if defined(HAVE_MATH_H)
 #include <math.h>
 #endif
+#if defined(HAVE_STDBOOL_H)
+#include <stdbool.h>
+#else
+#include "spandsp/stdbool.h"
+#endif
 #include "floating_fudge.h"
 
 #include "spandsp/telephony.h"
 
 #include "spandsp/private/awgn.h"
 
-/* Gaussian noise generator constants */
+/* Random number generator constants */
 #define M1 259200
 #define IA1 7141
 #define IC1 54773
-#define RM1 (1.0/M1)
+#define RM1 (1.0/(double) M1)
 #define M2 134456
 #define IA2 8121
 #define IC2 28411
-#define RM2 (1.0/M2)
+#define RM2 (1.0/(double) M2)
 #define M3 243000
 #define IA3 4561
 #define IC3 51349
 
-static double ran1(awgn_state_t *s)
+static void ran_init(awgn_state_t *s, int idum)
+{
+    int j;
+
+    if (idum < 0)
+        idum = -idum;
+    s->ix1 = (IC1 + (int32_t) idum)%M1;
+    s->ix1 = (IA1*s->ix1 + IC1)%M1;
+    s->ix2 = s->ix1%M2;
+    s->ix1 = (IA1*s->ix1 + IC1)%M1;
+    s->ix3 = s->ix1%M3;
+    for (j = 0;  j < 97;  j++)
+    {
+        s->ix1 = (IA1*s->ix1 + IC1)%M1;
+        s->ix2 = (IA2*s->ix2 + IC2)%M2;
+        s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+static double ran(awgn_state_t *s)
 {
     double temp;
     int j;
 
+    /* This produces evenly spread random numbers between 0.0 and 1.0 */
     s->ix1 = (IA1*s->ix1 + IC1)%M1;
     s->ix2 = (IA2*s->ix2 + IC2)%M2;
     s->ix3 = (IA3*s->ix3 + IC3)%M3;
-    j = 1 + ((97*s->ix3)/M3);
-    if (j > 97  ||  j < 1)
+    j = (97*s->ix3)/M3;
+    if (j > 96  ||  j < 0)
     {
         /* Error */
-        return -1;
+        temp = -1.0;
+    }
+    else
+    {
+        temp = s->r[j];
+        s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
     }
-    temp = s->r[j];
-    s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
     return temp;
 }
 /*- End of function --------------------------------------------------------*/
 
 SPAN_DECLARE(awgn_state_t *) awgn_init_dbov(awgn_state_t *s, int idum, float level)
 {
-    int j;
-
     if (s == NULL)
     {
         if ((s = (awgn_state_t *) span_alloc(sizeof(*s))) == NULL)
             return NULL;
     }
-    if (idum < 0)
-        idum = -idum;
 
-    s->rms = pow(10.0, level/20.0)*32768.0;
+    ran_init(s, idum);
 
-    s->ix1 = (IC1 + idum)%M1;
-    s->ix1 = (IA1*s->ix1 + IC1)%M1;
-    s->ix2 = s->ix1%M2;
-    s->ix1 = (IA1*s->ix1 + IC1)%M1;
-    s->ix3 = s->ix1%M3;
-    s->r[0] = 0.0;
-    for (j = 1;  j <= 97;  j++)
-    {
-        s->ix1 = (IA1*s->ix1 + IC1)%M1;
-        s->ix2 = (IA2*s->ix2 + IC2)%M2;
-        s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
-    }
-    s->gset = 0.0;
-    s->iset = 0;
+    s->rms = pow(10.0, level/20.0)*32768.0;
+    s->amp2 = 0.0;
+    s->odd = true;
     return s;
 }
 /*- End of function --------------------------------------------------------*/
@@ -148,31 +162,30 @@ SPAN_DECLARE(int) awgn_free(awgn_state_t *s)
 
 SPAN_DECLARE(int16_t) awgn(awgn_state_t *s)
 {
-    double fac;
     double r;
     double v1;
     double v2;
     double amp;
 
-    if (s->iset == 0)
+    /* The polar method of generating a Gaussian distribution */
+    if ((s->odd = !s->odd))
+    {
+        amp = s->amp2;
+    }
+    else
     {
         do
         {
-            v1 = 2.0*ran1(s) - 1.0;
-            v2 = 2.0*ran1(s) - 1.0;
+            v1 = 2.0*ran(s) - 1.0;
+            v2 = 2.0*ran(s) - 1.0;
             r = v1*v1 + v2*v2;
         }
         while (r >= 1.0);
-        fac = sqrt(-2.0*log(r)/r);
-        s->gset = v1*fac;
-        s->iset = 1;
-        amp = v2*fac*s->rms;
-    }
-    else
-    {
-        s->iset = 0;
-        amp = s->gset*s->rms;
+        r = sqrt(-2.0*log(r)/r);
+        s->amp2 = v1*r;
+        amp = v2*r;
     }
+    amp *= s->rms;
     return fsaturate(amp);
 }
 /*- End of function --------------------------------------------------------*/
index 44af2ae400613e6c94da4fdca3332e9a3726c9a8..3c0ee3e9c34bfdbf2e21b946c37a2f680c950c0d 100644 (file)
@@ -63,6 +63,7 @@
 #include "spandsp/tone_detect.h"
 #include "spandsp/tone_generate.h"
 #include "spandsp/async.h"
+#include "spandsp/at_interpreter.h"
 #include "spandsp/silence_gen.h"
 #include "spandsp/fsk.h"
 #include "spandsp/v29rx.h"
@@ -86,6 +87,7 @@
 #include "spandsp/data_modems.h"
 
 #include "spandsp/private/logging.h"
+#include "spandsp/private/at_interpreter.h"
 #include "spandsp/private/silence_gen.h"
 #include "spandsp/private/power_meter.h"
 #include "spandsp/private/fsk.h"
@@ -139,6 +141,7 @@ SPAN_DECLARE(const char *) data_modems_modulation_to_str(int modulation_scheme)
     case DATA_MODEM_V34:
         return "V.34 duplex";
     }
+    /*endswitch*/
     return "???";
 }
 /*- End of function --------------------------------------------------------*/
@@ -149,6 +152,13 @@ SPAN_DECLARE(logging_state_t *) data_modems_get_logging_state(data_modems_state_
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(void) data_modems_call_event(data_modems_state_t *s, int event)
+{
+    span_log(&s->logging, SPAN_LOG_FLOW, "Call event %s (%d) received\n", at_call_state_to_str(event), event);
+    at_call_event(&s->at_state, event);
+}
+/*- End of function --------------------------------------------------------*/
+
 static int async_get_byte(void *user_data)
 {
     data_modems_state_t *s;
@@ -169,6 +179,7 @@ static void async_put_byte(void *user_data, int byte)
     msg[0] = byte;
     if (byte < 0)
         s->put_msg(s->user_data,  msg, byte);
+    /*endif*/
     s->put_msg(s->user_data,  msg, 1);
 }
 /*- End of function --------------------------------------------------------*/
@@ -193,7 +204,9 @@ static void log_supported_modulations(data_modems_state_t *s, int modulation_sch
             span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s%s", comma, v8_modulation_to_str(modulation_schemes & (1 << i)));
             comma = ", ";
         }
+        /*endif*/
     }
+    /*endfor*/
     span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " supported\n");
 }
 /*- End of function --------------------------------------------------------*/
@@ -385,6 +398,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
             v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
         else
             v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
+        /*endif*/
         v8_parms.send_ci = false;
         v8_parms.v92 = -1;
         v8_parms.call_function = V8_CALL_V_SERIES;
@@ -396,6 +410,9 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
                              | V8_MOD_V23
                              | V8_MOD_V27TER
                              | V8_MOD_V29
+#if defined(SPANDSP_SUPPORT_V34)
+                             | V8_MOD_V34HDX
+#endif
                              | 0;
         v8_parms.protocol = V8_PROTOCOL_LAPM_V42;
 #elif 1
@@ -417,10 +434,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
         v8_parms.nsf = -1;
         v8_parms.t66 = -1;
         v8_init(&s->modems.v8, s->calling_party, &v8_parms, v8_handler, (void *) s);
-    logging = v8_get_logging_state(&s->modems.v8);
-    level = span_log_get_level(&s->logging);
-    span_log_set_level(logging, level);
-    span_log_set_tag(logging, "V.8");
+        logging = v8_get_logging_state(&s->modems.v8);
+        level = span_log_get_level(&s->logging);
+        span_log_set_level(logging, level);
+        span_log_set_tag(logging, "V.8");
         break;
     case DATA_MODEM_BELL103:
         s->rx_handler = (span_rx_handler_t) &fsk_rx;
@@ -438,6 +455,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
             fsk_rx_spec = &preset_fsk_specs[FSK_BELL103CH1];
             fsk_tx_spec = &preset_fsk_specs[FSK_BELL103CH2];
         }
+        /*endif*/
         fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
         fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
         break;
@@ -457,6 +475,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
             fsk_rx_spec = &preset_fsk_specs[FSK_V21CH1];
             fsk_tx_spec = &preset_fsk_specs[FSK_V21CH2];
         }
+        /*endif*/
         fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
         fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
         break;
@@ -487,6 +506,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
             fsk_rx_spec = &preset_fsk_specs[FSK_V23CH1];
             fsk_tx_spec = &preset_fsk_specs[FSK_V23CH2];
         }
+        /*endif*/
         fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
         fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
         break;
@@ -497,10 +517,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
         s->tx_handler = (span_tx_handler_t) &v22bis_tx;
         s->tx_user_data = &s->modems.v22bis;
         v22bis_init(&s->modems.v22bis, bit_rate, 0, s->calling_party, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
-    logging = v22bis_get_logging_state(&s->modems.v22bis);
-    level = span_log_get_level(&s->logging);
-    span_log_set_level(logging, level);
-    span_log_set_tag(logging, "V.22bis");
+        logging = v22bis_get_logging_state(&s->modems.v22bis);
+        level = span_log_get_level(&s->logging);
+        span_log_set_level(logging, level);
+        span_log_set_tag(logging, "V.22bis");
         break;
 #if defined(SPANDSP_SUPPORT_V32BIS)
     case DATA_MODEM_V32BIS:
@@ -510,10 +530,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
         s->tx_handler = (span_tx_handler_t) &v32bis_tx;
         s->tx_user_data = &s->modems.v32bis;
         v32bis_init(&s->modems.v32bis, bit_rate, s->calling_party, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
-    logging = v32bis_get_logging_state(&s->modems.v32bis);
-    level = span_log_get_level(&s->logging);
-    span_log_set_level(logging, level);
-    span_log_set_tag(logging, "V.32bis");
+        logging = v32bis_get_logging_state(&s->modems.v32bis);
+        level = span_log_get_level(&s->logging);
+        span_log_set_level(logging, level);
+        span_log_set_tag(logging, "V.32bis");
         break;
 #endif
 #if defined(SPANDSP_SUPPORT_V34)
@@ -524,13 +544,14 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
         s->tx_handler = (span_tx_handler_t) &v34_tx;
         s->tx_user_data = &s->modems.v34;
         v34_init(&s->modems.v34, baud_rate, bit_rate, s->calling_party, true, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
-    logging = v34_get_logging_state(&s->modems.v34);
-    level = span_log_get_level(&s->logging);
-    span_log_set_level(logging, level);
-    span_log_set_tag(logging, "V.34");
+        logging = v34_get_logging_state(&s->modems.v34);
+        level = span_log_get_level(&s->logging);
+        span_log_set_level(logging, level);
+        span_log_set_tag(logging, "V.34");
         break;
 #endif
     }
+    /*endswitch*/
     s->current_modem = which;
 }
 /*- End of function --------------------------------------------------------*/
@@ -541,9 +562,11 @@ SPAN_DECLARE(int) data_modems_rx(data_modems_state_t *s, const int16_t amp[], in
 
     if (s->rx_handler == NULL)
         return len;
+    /*endif*/
     res = s->rx_handler(s->rx_user_data, amp, len);
     if (s->current_modem != s->queued_modem)
         data_modems_set_modem_type(s, s->queued_modem, s->queued_baud_rate, s->queued_bit_rate);
+    /*endif*/
     return res;
 }
 /*- End of function --------------------------------------------------------*/
@@ -552,6 +575,7 @@ SPAN_DECLARE(int) data_modems_rx_fillin(data_modems_state_t *s, int len)
 {
     if (s->rx_fillin_handler == NULL)
         return len;
+    /*endif*/
     return s->rx_fillin_handler(s->rx_user_data, len);
 }
 /*- End of function --------------------------------------------------------*/
@@ -564,12 +588,52 @@ SPAN_DECLARE(int) data_modems_tx(data_modems_state_t *s, int16_t amp[], int max_
     {
         if (s->tx_handler == NULL)
             break;
+        /*endif*/
         len += s->tx_handler(s->tx_user_data, &amp[len], max_len - len);
     }
+    /*endfor*/
     return len;
 }
 /*- End of function --------------------------------------------------------*/
 
+static int data_modems_control_handler(void *user_data, int op, const char *num)
+{
+    data_modems_state_t *s;
+
+    s = (data_modems_state_t *) user_data;
+    switch (op)
+    {
+    case AT_MODEM_CONTROL_CALL:
+        s->call_samples = 0;
+        break;
+    case AT_MODEM_CONTROL_ANSWER:
+        s->call_samples = 0;
+        break;
+    case AT_MODEM_CONTROL_ONHOOK:
+        if (s->at_state.rx_signal_present)
+        {
+            s->at_state.rx_data_bytes = 0;
+        }
+        /*endif*/
+        break;
+    case AT_MODEM_CONTROL_RESTART:
+        return 0;
+    case AT_MODEM_CONTROL_DTE_TIMEOUT:
+        return 0;
+    }
+    /*endswitch*/
+    return s->modem_control_handler(s, s->modem_control_user_data, op, num);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) data_modems_set_at_tx_handler(data_modems_state_t *s,
+                                                 at_tx_handler_t at_tx_handler,
+                                                 void *at_tx_user_data)
+{
+    at_set_at_tx_handler(&s->at_state, at_tx_handler, at_tx_user_data);
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s)
 {
     return 0;
@@ -578,21 +642,34 @@ SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s)
 
 SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
                                                      bool calling_party,
+                                                     at_tx_handler_t at_tx_handler,
+                                                     void *at_tx_user_data,
+                                                     data_modems_control_handler_t modem_control_handler,
+                                                     void *modem_control_user_data,
                                                      put_msg_func_t put_msg,
                                                      get_msg_func_t get_msg,
                                                      void *user_data)
 {
+    if (at_tx_handler == NULL  ||  modem_control_handler == NULL)
+        return NULL;
+    /*endif*/
+
     if (s == NULL)
     {
         if ((s = (data_modems_state_t *) span_alloc(sizeof(*s))) == NULL)
             return NULL;
+        /*endif*/
     }
+    /*endif*/
     memset(s, 0, sizeof(*s));
     span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
     span_log_set_protocol(&s->logging, "Modem");
 
     dc_restore_init(&s->dc_restore);
 
+    s->modem_control_handler = modem_control_handler;
+    s->modem_control_user_data = modem_control_user_data;
+
     s->put_msg = put_msg;
     s->get_msg = get_msg;
     s->user_data = user_data;
@@ -602,6 +679,8 @@ SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
 
     data_modems_set_async_mode(s, 8, 1, 1);
 
+    at_init(&s->at_state, at_tx_handler, at_tx_user_data, data_modems_control_handler, s);
+
     s->get_bit = async_tx_get_bit;
     s->get_user_data = &s->async_tx;
     s->put_bit = async_rx_put_bit;
@@ -627,6 +706,7 @@ SPAN_DECLARE(int) data_modems_free(data_modems_state_t *s)
 {
     if (s)
         span_free(s);
+    /*endif*/
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
index 80062fe4c7030e1fb2d998a9a94c0d01579a4735..feefa5ad7d335a0ea5ca0343fbc504e6ab003d04 100644 (file)
@@ -89,6 +89,7 @@ static __inline__ void octet_set_and_count(hdlc_rx_state_t *s)
 {
     if (s->octet_count_report_interval == 0)
         return;
+    /*endif*/
 
     /* If we are not in octet counting mode, we start it.
        If we are in octet counting mode, we update it. */
@@ -625,6 +626,7 @@ SPAN_DECLARE(int) hdlc_tx_get_byte(hdlc_tx_state_t *s)
         /* An input byte will generate between 8 and 10 output bits */
         return (s->octets_in_progress >> s->num_bits) & 0xFF;
     }
+    /*endif*/
     /* Untimed idling on flags */
     if (s->tx_end)
     {
@@ -644,8 +646,10 @@ SPAN_DECLARE(int) hdlc_tx_get_bit(hdlc_tx_state_t *s)
     {
         if ((s->byte = hdlc_tx_get_byte(s)) < 0)
             return s->byte;
+        /*endif*/
         s->bits = 8;
     }
+    /*endif*/
     s->bits--;
     txbit = (s->byte >> s->bits) & 0x01;
     return txbit;
@@ -661,8 +665,10 @@ SPAN_DECLARE(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
     {
         if ((x = hdlc_tx_get_byte(s)) == SIG_STATUS_END_OF_DATA)
             return i;
+        /*endif*/
         buf[i] = (uint8_t) x;
     }
+    /*endfor*/
     return (int) i;
 }
 /*- End of function --------------------------------------------------------*/
index 64a45d04959096c99ae42025c29dba01b2c1a59c..ecb218bb85b1792363b915cefdfcf2ef4e685831 100644 (file)
@@ -532,7 +532,7 @@ static int floyd_steinberg_dither_row(image_translate_state_t *s, uint8_t buf[])
                 s->output_row = -1;
         }
     }
-    /* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophodontic
+    /* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophedontic
        scan, to reduce the grayscale image to pure black and white */
     /* The first and last pixels in each row need special treatment, so we do not
        step outside the row. */
index 082dbbb3aca48a6dd7d9045f40b5f53a456f3a6c..74125aa8c4131bbb9435e6c68b95787b072ca44c 100644 (file)
@@ -564,7 +564,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
     static const float precoef = 0.9375f;
 
     float amdf[60];
-    float abuf[156];
+    float abuf[LPC10_MIN_PITCH];
     float ivrc[2];
     float temp;
     float phi[100]    /* was [10][10] */;
@@ -634,7 +634,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
     s->zpre = preemp(&s->inbuf[i - 181], &s->pebuf[i - 181], LPC10_SAMPLES_PER_FRAME, precoef, s->zpre);
     onset(s, s->pebuf, s->osbuf, &s->osptr, 10, 181, 720, LPC10_SAMPLES_PER_FRAME);
 
-    lpc10_placev(s->osbuf, &s->osptr, 10, &s->obound[2], s->vwin, 3, LPC10_SAMPLES_PER_FRAME, 90, 156, 307, 462);
+    lpc10_placev(s->osbuf, &s->osptr, 10, &s->obound[2], s->vwin, 3, LPC10_SAMPLES_PER_FRAME, 90, LPC10_MIN_PITCH, 307, 462);
     /* The Pitch Extraction algorithm estimates the pitch for a frame
        of speech by locating the minimum of the average magnitude difference
        function (AMDF).  The AMDF operates on low-pass, inverse filtered
@@ -655,7 +655,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
     /* eval_highres_amdf reads indices PWINL = 229 through
        (PWINL-1)+MAXWIN+(TAU(LTAU)-TAU(1))/2 = 452 of IVBUF, and writes
        indices 1 through LTAU = 60 of AMDF. */
-    eval_highres_amdf(s->ivbuf, 156, tau, 60, amdf, &minptr, &maxptr, &mintau);
+    eval_highres_amdf(s->ivbuf, LPC10_MIN_PITCH, tau, 60, amdf, &minptr, &maxptr, &mintau);
     /* Voicing decisions are made for each half frame of input speech.
        An initial voicing classification is made for each half of the
        analysis frame, and the voicing decisions for the present frame
@@ -688,7 +688,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
     dynamic_pitch_tracking(s, amdf, 60, &minptr, s->voibuf[3][1], pitch, &midx);
     ipitch = tau[midx - 1];
     /* Place spectrum analysis and energy windows */
-    lpc10_placea(&ipitch, s->voibuf, &s->obound[2], 3, s->vwin, s->awin, ewin, LPC10_SAMPLES_PER_FRAME, 156);
+    lpc10_placea(&ipitch, s->voibuf, &s->obound[2], 3, s->vwin, s->awin, ewin, LPC10_SAMPLES_PER_FRAME, LPC10_MIN_PITCH);
     /* Remove short term DC bias over the analysis window. */
     lanal = s->awin[2][1] + 1 - s->awin[2][0];
     remove_dc_bias(&s->pebuf[s->awin[2][0] - 181], lanal, abuf);
index e56b16ecf0643ea8a79c87a28edc15dabebc1894..6b7f7ebb2ecadec9788fcba8fe79756bce13213b 100644 (file)
@@ -54,7 +54,7 @@
 #include "spandsp/lpc10.h"
 #include "spandsp/private/lpc10.h"
 
-#define LPC10_ORDER     10
+#include "lpc10_encdecs.h"
 
 #if !defined(min)
 #define min(a,b) ((a) <= (b) ? (a) : (b))
@@ -81,32 +81,6 @@ static int32_t lpc10_random(lpc10_decode_state_t *s)
 }
 /*- End of function --------------------------------------------------------*/
 
-static __inline__ int32_t pow_ii(int32_t x, int32_t n)
-{
-    int32_t pow;
-    uint32_t u;
-
-    if (n <= 0)
-    {
-        if (n == 0  ||  x == 1)
-            return 1;
-        if (x != -1)
-            return (x != 0)  ?  1/x  :  0;
-        n = -n;
-    }
-    u = n;
-    for (pow = 1;  ;  )
-    {
-        if ((u & 1))
-            pow *= x;
-        if ((u >>= 1) == 0)
-            break;
-        x *= x;
-    }
-    return pow;
-}
-/*- End of function --------------------------------------------------------*/
-
 /* Synthesize one pitch epoch */
 static void bsynz(lpc10_decode_state_t *s,
                   float coef[],
@@ -127,7 +101,7 @@ static void bsynz(lpc10_decode_state_t *s,
     int32_t j;
     int32_t k;
     int32_t px;
-    float noise[166];
+    float noise[LPC10_MIN_PITCH];
     float pulse;
     float r1;
     float gain;
@@ -177,14 +151,13 @@ static void bsynz(lpc10_decode_state_t *s,
         }
         for (i = 0;  i < ip;  i++)
         {
-            noise[LPC10_ORDER + i] = lpc10_random(s)/64.0f;
-            hpi0 = noise[LPC10_ORDER + i];
-            noise[LPC10_ORDER + i] = noise[LPC10_ORDER + i]*-0.125f + s->hpi[0]*0.25f + s->hpi[1]*-0.125f;
+            hpi0 = lpc10_random(s)/64.0f;
+            noise[i] = hpi0*-0.125f + s->hpi[0]*0.25f + s->hpi[1]*-0.125f;
             s->hpi[1] = s->hpi[0];
             s->hpi[0] = hpi0;
         }
         for (i = 0;  i < ip;  i++)
-            s->exc[LPC10_ORDER + i] += noise[LPC10_ORDER + i];
+            s->exc[LPC10_ORDER + i] += noise[i];
     }
     /* Synthesis filters: */
     /* Modify the excitation with all-zero filter 1 + G*SUM */
@@ -224,20 +197,17 @@ static void bsynz(lpc10_decode_state_t *s,
 
 /* Synthesize a single pitch epoch */
 static int pitsyn(lpc10_decode_state_t *s,
-                  int voice[],
+                  int voice[2],
                   int32_t *pitch,
-                  float *rms,
-                  float *rc,
-                  int32_t ivuv[],
-                  int32_t ipiti[],
-                  float *rmsi,
-                  float *rci,
+                  float rms,
+                  float rc[LPC10_ORDER],
+                  int32_t ivuv[16],
+                  int32_t ipiti[16],
+                  float rmsi[16],
+                  float rci[16*LPC10_ORDER],
                   int32_t *nout,
                   float *ratio)
 {
-    int32_t rci_dim1;
-    int32_t rci_offset;
-    int32_t i1;
     int32_t i;
     int32_t j;
     int32_t vflag;
@@ -257,16 +227,12 @@ static int pitsyn(lpc10_decode_state_t *s,
     float xxy;
     float msix;
 
-    rci_dim1 = LPC10_ORDER;
-    rci_offset = rci_dim1 + 1;
-    rci -= rci_offset;
-
-    if (*rms < 1.0f)
-        *rms = 1.0f;
+    if (rms < 1.0f)
+        rms = 1.0f;
     if (s->rmso < 1.0f)
         s->rmso = 1.0f;
     uvpit = 0.0f;
-    *ratio = *rms/(s->rmso + 8.0f);
+    *ratio = rms/(s->rmso + 8.0f);
     if (s->first_pitsyn)
     {
         ivoice = voice[1];
@@ -275,14 +241,13 @@ static int pitsyn(lpc10_decode_state_t *s,
         *nout = LPC10_SAMPLES_PER_FRAME / *pitch;
         s->jsamp = LPC10_SAMPLES_PER_FRAME - *nout * *pitch;
 
-        i1 = *nout;
-        for (i = 0;  i < i1;  i++)
+        for (i = 0;  i < *nout;  i++)
         {
             for (j = 0;  j < LPC10_ORDER;  j++)
-                rci[j + (i + 1)*rci_dim1 + 1] = rc[j];
+                rci[j + i*LPC10_ORDER] = rc[j];
             ivuv[i] = ivoice;
             ipiti[i] = *pitch;
-            rmsi[i] = *rms;
+            rmsi[i] = rms;
         }
         s->first_pitsyn = false;
     }
@@ -301,7 +266,7 @@ static int pitsyn(lpc10_decode_state_t *s,
                 *pitch = LPC10_SAMPLES_PER_FRAME/4;
                 s->ipito = *pitch;
                 if (*ratio > 8.0f)
-                    s->rmso = *rms;
+                    s->rmso = rms;
             }
             /* SSVC - -   1  ,  1  ,  1 */
             slope = (*pitch - s->ipito)/(float) lsamp;
@@ -329,8 +294,8 @@ static int pitsyn(lpc10_decode_state_t *s,
                 rmsi[1] = s->rmso;
                 for (i = 0;  i < LPC10_ORDER;  i++)
                 {
-                    rci[i + rci_dim1 + 1] = s->rco[i];
-                    rci[i + (rci_dim1 << 1) + 1] = s->rco[i];
+                    rci[i] = s->rco[i];
+                    rci[i + LPC10_ORDER] = s->rco[i];
                     s->rco[i] = rc[i];
                 }
                 *nout = 2;
@@ -434,10 +399,9 @@ static int pitsyn(lpc10_decode_state_t *s,
                     ip = (int32_t) uvpit;
                 if (ip <= i - jused)
                 {
-                    ++(*nout);
-                    ipiti[*nout - 1] = ip;
+                    ipiti[*nout] = ip;
                     *pitch = ip;
-                    ivuv[*nout - 1] = ivoice;
+                    ivuv[*nout] = ivoice;
                     jused += ip;
                     prop = (jused - ip/2)/(float) lsamp;
                     for (j = 0;  j < LPC10_ORDER;  j++)
@@ -446,12 +410,13 @@ static int pitsyn(lpc10_decode_state_t *s,
                         alrn = logf((rc[j] + 1)/(1 - rc[j]));
                         xxy = alro + prop*(alrn - alro);
                         xxy = expf(xxy);
-                        rci[j + *nout*rci_dim1 + 1] = (xxy - 1.0f)/(xxy + 1.0f);
+                        rci[j + *nout*LPC10_ORDER] = (xxy - 1.0f)/(xxy + 1.0f);
                     }
-                    msix = logf(*rms) - logf(s->rmso);
+                    msix = logf(rms) - logf(s->rmso);
                     msix = prop*msix;
                     msix = logf(s->rmso) + msix;
-                    rmsi[*nout - 1] = expf(msix);
+                    rmsi[*nout] = expf(msix);
+                    (*nout)++;
                 }
             }
             if (vflag != 1)
@@ -465,7 +430,7 @@ static int pitsyn(lpc10_decode_state_t *s,
             uvpit = (float) ((lsamp - istart)/2);
             if (uvpit > 90.0f)
                 uvpit /= 2;
-            s->rmso = *rms;
+            s->rmso = rms;
             for (i = 0;  i < LPC10_ORDER;  i++)
             {
                 rc[i] = yarc[i];
@@ -478,7 +443,7 @@ static int pitsyn(lpc10_decode_state_t *s,
     {
         s->ivoico = voice[1];
         s->ipito = *pitch;
-        s->rmso = *rms;
+        s->rmso = rms;
         for (i = 0;  i < LPC10_ORDER;  i++)
             s->rco[i] = rc[i];
     }
@@ -532,13 +497,12 @@ static float reflection_coeffs_to_predictor_coeffs(float rc[], float pc[], float
 /*- End of function --------------------------------------------------------*/
 
 static int synths(lpc10_decode_state_t *s,
-                  int voice[],
+                  int voice[2],
                   int32_t *pitch,
-                  float *rms,
-                  float *rc,
+                  float rms,
+                  float rc[LPC10_ORDER],
                   float speech[])
 {
-    int32_t i1;
     int32_t ivuv[16];
     int32_t ipiti[16];
     int32_t nout;
@@ -547,11 +511,10 @@ static int synths(lpc10_decode_state_t *s,
     float rmsi[16];
     float ratio;
     float g2pass;
-    float pc[10];
-    float rci[160];
+    float pc[LPC10_ORDER];
+    float rci[16*LPC10_ORDER];
 
-    i1 = min(*pitch, 156);
-    *pitch = max(i1, 20);
+    *pitch = max(min(*pitch, LPC10_MIN_PITCH), LPC10_MAX_PITCH);
     for (i = 0;  i < LPC10_ORDER;  i++)
         rc[i] = max(min(rc[i], 0.99f), -0.99f);
     pitsyn(s, voice, pitch, rms, rc, ivuv, ipiti, rmsi, rci, &nout, &ratio);
@@ -560,14 +523,13 @@ static int synths(lpc10_decode_state_t *s,
         for (j = 0;  j < nout;  j++)
         {
             /* Add synthesized speech for pitch period J to the end of s->buf. */
-            g2pass = reflection_coeffs_to_predictor_coeffs(&rci[j*10], pc, 0.7f);
+            g2pass = reflection_coeffs_to_predictor_coeffs(&rci[j*LPC10_ORDER], pc, 0.7f);
             bsynz(s, pc, ipiti[j], &ivuv[j], &s->buf[s->buflen], rmsi[j], ratio, g2pass);
             deemp(s, &s->buf[s->buflen], ipiti[j]);
             s->buflen += ipiti[j];
         }
         /* Copy first MAXFRM samples from BUF to output array speech (scaling them),
            and then remove them from the beginning of s->buf. */
-
         for (i = 0;  i < LPC10_SAMPLES_PER_FRAME;  i++)
             speech[i] = s->buf[i]/4096.0f;
         s->buflen -= LPC10_SAMPLES_PER_FRAME;
@@ -709,7 +671,7 @@ static int32_t median(int32_t d1, int32_t d2, int32_t d3)
 
 static void decode(lpc10_decode_state_t *s,
                    lpc10_frame_t *t,
-                   int voice[],
+                   int voice[2],
                    int32_t *pitch,
                    float *rms,
                    float rc[])
@@ -1110,7 +1072,7 @@ SPAN_DECLARE(int) lpc10_decode(lpc10_decode_state_t *s, int16_t amp[], const uin
     {
         lpc10_unpack(&frame, &code[i*7]);
         decode(s, &frame, voice, &pitch, &rms, rc);
-        synths(s, voice, &pitch, &rms, rc, speech);
+        synths(s, voice, &pitch, rms, rc, speech);
         base = i*LPC10_SAMPLES_PER_FRAME;
         for (j = 0;  j < LPC10_SAMPLES_PER_FRAME;  j++)
             amp[base + j] = (int16_t) lfastrintf(32768.0f*speech[j]);
index 05dd87f118085f780ce48209d4b5784c75aabc0a..f8aa85c2ebe81783f9c5b8cb74a2c103217919e3 100644 (file)
@@ -23,7 +23,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define LPC10_ORDER     10
+#define LPC10_ORDER         10
+#define LPC10_MAX_PITCH     20
+#define LPC10_MIN_PITCH     156
 
 #if !defined(min)
 #define min(a,b) ((a) <= (b) ? (a) : (b))
index e41f26a2694804102952b3c698b795a99a72c3b4..cb668a5acc6f8bfe4ddad8ba0b43689e9b3419b5 100644 (file)
@@ -353,10 +353,6 @@ void lpc10_voicing(lpc10_encode_state_t *s,
     /* Voicing decision for current half-frame:  1 = Voiced; 0 = Unvoiced */
     s->voibuf[3][half] = (s->voice[2][half] > 0.0f)  ?  1  :  0;
     /* Skip voicing decision smoothing in first half-frame: */
-    /* Give a value to VSTATE, so that trace statements below will print */
-    /* a consistent value from one call to the next when HALF .EQ. 1. */
-    /* The value of VSTATE is not used for any other purpose when this is */
-    /* true. */
     if (half != 0)
     {
         /* Voicing decision smoothing rules (override of linear combination): */
index 974f1b22ab970f23e3a1f5812dfde085ab201384..de50294ed14981eae1f6595933a39f2c04284478 100644 (file)
@@ -646,7 +646,7 @@ int main(int argc, char *argv[])
         exit(2);
     /*endif*/
 
-    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
+    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
     printf("   FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
     printf("\n");
 
@@ -661,7 +661,7 @@ int main(int argc, char *argv[])
     trie_recursive_build_packed_trie(s->root);
 
     dump_trie();
-     
+
     trie_free(s);
 
     return 0;
index b780355543d6c229170dc31bb8d9e470737527a2..151c94cfbcd1f1f5c815e7bc5af36d318e814408 100644 (file)
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
     uint8_t srgb;
     int i;
 
-    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
+    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
     printf("   FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
     printf("\n");
 
index 1f568286f72602d85433f950fce39e7356c6a021..642deff74357ed2a526e28c90d9ce59cc983931f 100644 (file)
@@ -37,7 +37,7 @@ int main(int argc, char *argv[])
     double val;
     int ival;
 
-    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
+    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
     printf("   FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
     printf("\n");
 
index 2579461db154b059d84013021f4bf56b9aea570c..87e71b50ac263bd20ab9cf8eebe9cd0809137671 100644 (file)
 #include <time.h>
 #include <fcntl.h>
 #include <math.h>
-#if defined(HAVE_STDBOOL_H)
 #include <stdbool.h>
-#else
-#include "spandsp/stdbool.h"
-#endif
 #if defined(__sunos)  ||  defined(__solaris)  ||  defined(__sun)
 #include <getopt.h>
 #endif
@@ -103,7 +99,7 @@ static void make_tx_filter(int coeff_sets,
 
     /* Churn out the data as a C source code header file, which can be directly included by the
        modem code. */
-    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
+    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
     printf("   FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
     printf("\n");
     printf("#if defined(SPANDSP_USE_FIXED_POINT)\n");
index 0016c988a08254ac088b62e2053d7043c40604bf..9fd1befd5c652ed52d7d4beed63c9e273467bbdf 100644 (file)
@@ -39,7 +39,7 @@ int main(int argc, char *argv[])
     int new_gray;
     int restore;
 
-    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
+    printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
     printf("   FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
     printf("\n");
 
index 67ca4c0b771602c71c4403ac38a3640e3f4d7e57..f645f708927818734d594f7f30212ffb55431b58 100644 (file)
@@ -177,6 +177,10 @@ SPAN_DECLARE(void) at_set_modem_control_handler(at_state_t *s,
                                                 at_modem_control_handler_t modem_control_handler,
                                                 void *modem_control_user_data);
 
+SPAN_DECLARE(void) at_set_at_tx_handler(at_state_t *s,
+                                        at_tx_handler_t at_tx_handler,
+                                        void *at_tx_user_data);
+
 /*! Initialise an AT interpreter context.
     \brief Initialise an AT interpreter context.
     \param s The AT context.
index 36f0176c761e96391b60f526f94346d3466f39f9..7dd09f153748e30156b2633ab436e15ec021ba79 100644 (file)
@@ -50,6 +50,8 @@ enum
 */
 typedef struct data_modems_state_s data_modems_state_t;
 
+typedef int (*data_modems_control_handler_t)(data_modems_state_t *s, void *user_data, int op, const char *num);
+
 #if defined(__cplusplus)
 extern "C"
 {
@@ -62,6 +64,8 @@ SPAN_DECLARE(void) data_modems_set_tep_mode(data_modems_state_t *s, int use_tep)
 
 SPAN_DECLARE(logging_state_t *) data_modems_get_logging_state(data_modems_state_t *s);
 
+SPAN_DECLARE(void) data_modems_call_event(data_modems_state_t *s, int event);
+
 SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s);
 
 SPAN_DECLARE(void) data_modems_set_async_mode(data_modems_state_t *s,
@@ -77,8 +81,16 @@ SPAN_DECLARE(int) data_modems_rx_fillin(data_modems_state_t *s, int len);
 
 SPAN_DECLARE(int) data_modems_tx(data_modems_state_t *s, int16_t amp[], int max_len);
 
+SPAN_DECLARE(void) data_modems_set_at_tx_handler(data_modems_state_t *s,
+                                                 at_tx_handler_t at_tx_handler,
+                                                 void *at_tx_user_data);
+
 SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
                                                      bool calling_party,
+                                                     at_tx_handler_t at_tx_handler,
+                                                     void *at_tx_user_data,
+                                                     data_modems_control_handler_t modem_control_handler,
+                                                     void *modem_control_user_data,
                                                      put_msg_func_t put_msg,
                                                      get_msg_func_t get_msg,
                                                      void *user_data);
index 62e537acff5cd5e2cff77e1124b248c4271c225b..fa670c5de7b9cd73125cf794dad71d3cd29bb6b0 100644 (file)
@@ -115,7 +115,7 @@ extern "C"
 /* Enable the trap as per the MIL-STD */
 //#define G711_ULAW_ZEROTRAP
 /*! Bias for u-law encoding from linear. */
-#define G711_ULAW_BIAS      0x84
+#define G711_ULAW_BIAS              0x84
 
 /*! \brief Encode a linear sample to u-law
     \param linear The sample to encode.
index 908a465f9f949f6a7088cf12f95597a8131de41c..dbca521131e60e7e61a941e446cc740ad5bccdd3 100644 (file)
  */
 struct awgn_state_s
 {
+    /* Scaling factor */
     double rms;
-    long int ix1;
-    long int ix2;
-    long int ix3;
-    double r[98];
-    double gset;
-    int iset;
+    /* Working data for the Gaussian generator */
+    bool odd;
+    double amp2;
+    /* Working data for the random number generator */
+    int32_t ix1;
+    int32_t ix2;
+    int32_t ix3;
+    double r[97];
 };
 
 #endif
index 7e4a28b5cc5564f66db7b99b96dbaba80be35759..f47f8f259a263d05a72e30b50796518f6419f220 100644 (file)
@@ -43,6 +43,9 @@ struct data_modems_state_s
         silent audio. */
     bool transmit_on_idle;
 
+    at_state_t at_state;
+    data_modems_control_handler_t modem_control_handler;
+    void *modem_control_user_data;
     get_bit_func_t get_bit;
     void *get_user_data;
     put_bit_func_t put_bit;
@@ -60,6 +63,9 @@ struct data_modems_state_s
     async_tx_state_t async_tx;
     async_rx_state_t async_rx;
 
+    /*! \brief Samples elapsed in the current call */
+    int64_t call_samples;
+
     union
     {
         v8_state_t v8;
index a7575b870b5cdb738614bc843641f60205312d7b..7a82e71df762d17dcb510b8d6fef1d3738fe15e0 100644 (file)
@@ -31,10 +31,13 @@ struct v18_state_s
     /*! \brief True if we are the calling modem */
     bool calling_party;
     int mode;
+    int initial_mode;
+    int current_mode;
     int nation;
     put_msg_func_t put_msg;
     void *user_data;
-    int repeat_shifts;
+    bool repeat_shifts;
+    bool autobauding;
 
     union
     {
@@ -48,10 +51,38 @@ struct v18_state_s
     async_tx_state_t async_tx;
     int baudot_tx_shift;
     int tx_signal_on;
+    bool tx_draining;
     uint8_t next_byte;
 
     fsk_rx_state_t fsk_rx;
     dtmf_rx_state_t dtmf_rx;
+
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    /*! Minimum acceptable tone level for detection. */
+    int32_t threshold;
+    /*! The accumlating total energy on the same period over which the Goertzels work. */
+    int32_t energy;
+#else
+    /*! Minimum acceptable tone level for detection. */
+    float threshold;
+    /*! The accumlating total energy on the same period over which the Goertzels work. */
+    float energy;
+#endif
+    goertzel_state_t tone_390;
+    goertzel_state_t tone_980;
+    goertzel_state_t tone_1180;
+    goertzel_state_t tone_1270;
+    goertzel_state_t tone_1300;
+    goertzel_state_t tone_1400;
+    goertzel_state_t tone_1650;
+    goertzel_state_t tone_1800;
+    /*! The current sample number within a processing block. */
+    int current_sample;
+    /*! Tone state duration */
+    int duration;
+    int target_duration;
+    int in_tone;
+
     int baudot_rx_shift;
     int consecutive_ones;
     uint8_t rx_msg[256 + 1];
@@ -59,6 +90,7 @@ struct v18_state_s
     int bit_pos;
     int in_progress;
     int rx_suppression;
+    int tx_suppression;
 
     /*! \brief Error and flow logging control */
     logging_state_t logging;
index faceaac3f97642ac871b8518641fadf627980d0b..492f9c2ec62044405d375d06e1be5be7098a6245 100644 (file)
 
 #if !defined(__cplusplus)
 
-#define _Bool   int
-#define bool    int
+typedef int     _Bool;
+typedef int     bool;
 #define false   0
 #define true    (!false)
 
 #else
 
-#define _Bool   bool
-#define bool    bool
+typedef bool    _Bool;
 #define false   false
 #define true    true
 
index 0d0f306fe1088db21f0f52fd0ea28913ae7a9d30..fb338e48e25edcd4f719b7f0409cae644ade1f6d 100644 (file)
@@ -67,60 +67,64 @@ typedef int (*span_rx_fillin_handler_t)(void *s, int len);
 /*! \brief A handler for transmit, where the buffer will be filled. */
 typedef int (*span_tx_handler_t)(void *s, int16_t amp[], int max_len);
 
+#define seconds_to_samples(t)       ((t)*SAMPLE_RATE)
+#define milliseconds_to_samples(t)  ((t)*(SAMPLE_RATE/1000))
+#define microseconds_to_samples(t)  ((t)/(1000000/SAMPLE_RATE))
+
 #define ms_to_samples(t)            ((t)*(SAMPLE_RATE/1000))
 #define us_to_samples(t)            ((t)/(1000000/SAMPLE_RATE))
 
 /* Fixed point constant macros for 16 bit values */
-#define FP_Q16_0(x) ((int16_t) (1.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q15_1(x) ((int16_t) (2.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q14_2(x) ((int16_t) (4.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q13_3(x) ((int16_t) (8.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q12_4(x) ((int16_t) (16.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q11_5(x) ((int16_t) (32.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q10_6(x) ((int16_t) (64.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q9_7(x) ((int16_t) (128.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q8_8(x) ((int16_t) (256.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q7_9(x) ((int16_t) (512.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q6_10(x) ((int16_t) (1024.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q5_11(x) ((int16_t) (2048.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q4_12(x) ((int16_t) (4096.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q3_13(x) ((int16_t) (8192.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q2_14(x) ((int16_t) (16384.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q1_15(x) ((int16_t) (32768.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q16_0(x) ((int16_t) (1.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q15_1(x) ((int16_t) (2.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q14_2(x) ((int16_t) (4.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q13_3(x) ((int16_t) (8.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q12_4(x) ((int16_t) (16.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q11_5(x) ((int16_t) (32.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q10_6(x) ((int16_t) (64.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q9_7(x) ((int16_t) (128.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q8_8(x) ((int16_t) (256.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q7_9(x) ((int16_t) (512.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q6_10(x) ((int16_t) (1024.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q5_11(x) ((int16_t) (2048.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q4_12(x) ((int16_t) (4096.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q3_13(x) ((int16_t) (8192.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q2_14(x) ((int16_t) (16384.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q1_15(x) ((int16_t) (32768.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
 
 /* Fixed point constant macros for 32 bit values */
-#define FP_Q32_0(x) ((int32_t) (1.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q31_1(x) ((int32_t) (2.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q30_2(x) ((int32_t) (4.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q29_3(x) ((int32_t) (8.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q28_4(x) ((int32_t) (16.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q27_5(x) ((int32_t) (32.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q26_6(x) ((int32_t) (64.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q25_7(x) ((int32_t) (128.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q24_8(x) ((int32_t) (256.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q23_9(x) ((int32_t) (512.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q22_10(x) ((int32_t) (1024.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q21_11(x) ((int32_t) (2048.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q20_12(x) ((int32_t) (4096.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q19_13(x) ((int32_t) (8192.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q18_14(x) ((int32_t) (16384.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q17_15(x) ((int32_t) (32768.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q16_16(x) ((int32_t) (65536.0*1.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q15_17(x) ((int32_t) (65536.0*2.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q14_18(x) ((int32_t) (65536.0*4.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q13_19(x) ((int32_t) (65536.0*8.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q12_20(x) ((int32_t) (65536.0*16.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q11_21(x) ((int32_t) (65536.0*32.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q10_22(x) ((int32_t) (65536.0*64.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q9_23(x) ((int32_t) (65536.0*128.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q8_24(x) ((int32_t) (65536.0*256.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q7_25(x) ((int32_t) (65536.0*512.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q6_26(x) ((int32_t) (65536.0*1024.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q5_27(x) ((int32_t) (65536.0*2048.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q4_28(x) ((int32_t) (65536.0*4096.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q3_29(x) ((int32_t) (65536.0*8192.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q2_30(x) ((int32_t) (65536.0*16384.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
-#define FP_Q1_31(x) ((int32_t) (65536.0*32768.0*x + ((x >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q32_0(x) ((int32_t) (1.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q31_1(x) ((int32_t) (2.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q30_2(x) ((int32_t) (4.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q29_3(x) ((int32_t) (8.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q28_4(x) ((int32_t) (16.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q27_5(x) ((int32_t) (32.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q26_6(x) ((int32_t) (64.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q25_7(x) ((int32_t) (128.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q24_8(x) ((int32_t) (256.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q23_9(x) ((int32_t) (512.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q22_10(x) ((int32_t) (1024.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q21_11(x) ((int32_t) (2048.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q20_12(x) ((int32_t) (4096.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q19_13(x) ((int32_t) (8192.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q18_14(x) ((int32_t) (16384.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q17_15(x) ((int32_t) (32768.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q16_16(x) ((int32_t) (65536.0*1.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q15_17(x) ((int32_t) (65536.0*2.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q14_18(x) ((int32_t) (65536.0*4.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q13_19(x) ((int32_t) (65536.0*8.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q12_20(x) ((int32_t) (65536.0*16.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q11_21(x) ((int32_t) (65536.0*32.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q10_22(x) ((int32_t) (65536.0*64.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q9_23(x) ((int32_t) (65536.0*128.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q8_24(x) ((int32_t) (65536.0*256.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q7_25(x) ((int32_t) (65536.0*512.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q6_26(x) ((int32_t) (65536.0*1024.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q5_27(x) ((int32_t) (65536.0*2048.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q4_28(x) ((int32_t) (65536.0*4096.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q3_29(x) ((int32_t) (65536.0*8192.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q2_30(x) ((int32_t) (65536.0*16384.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
+#define FP_Q1_31(x) ((int32_t) (65536.0*32768.0*(x) + (((x) >= 0.0)  ?  0.5  :  -0.5)))
 
 #if defined(__cplusplus)
 /* C++ doesn't seem to have sane rounding functions/macros yet */
index 50aa5ab260b7c5b579ccaaf1a0fa401f8cd3593c..f0bd66d48ae31ff272a6d45adc47aaedfc3db50d 100644 (file)
@@ -66,6 +66,8 @@ enum
 {
     V18_AUTOMODING_GLOBAL = 0,
 
+    V18_AUTOMODING_NONE,
+
     /* 5-bit, V.21, V.23, EDT, DTMF, Bell 103 */
     V18_AUTOMODING_AUSTRALIA,
     V18_AUTOMODING_IRELAND,
@@ -173,6 +175,11 @@ SPAN_DECLARE(int) v18_rx_fillin(v18_state_t *s, int len);
             invalid, this function will return -1. */
 SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len);
 
+/*! \brief Get the current mode of a V.18 connection.
+    \param s The V.18 context.
+    \return The mode. */
+SPAN_DECLARE(int) v18_get_current_mode(v18_state_t *s);
+
 /*! \brief Return a short name for an V.18 mode
     \param mode The code for the V.18 mode.
     \return A pointer to the name.
index 0ef46b9f31f88ed0c1e756a7fd51084e4754306b..9e7d99f3308f4b44f6b29b0357fdc23ad0c99787 100644 (file)
@@ -959,6 +959,7 @@ SPAN_DECLARE(void) t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *pkt, in
     octet_bit_field(log, pkt, 96, "Extension indicator", NULL, NULL);
     if (!(pkt[14] & DISBIT8))
         return;
+    /*endif*/
     if (len <= 15)
     {
         span_log(log, SPAN_LOG_FLOW, "  Frame is short\n");
index cda544990e2349a88d9d8fb99d3aa90c49cc77fa..19ae7ccf48e6b43b41dca64f24a7a6c8af619cce 100644 (file)
@@ -202,6 +202,7 @@ static void report_status_change(v17_rx_state_t *s, int status)
         s->status_handler(s->status_user_data, status);
     else if (s->put_bit)
         s->put_bit(s->put_bit_user_data, status);
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -360,6 +361,7 @@ static int descramble(v17_rx_state_t *s, int in_bit)
         s->scramble_reg |= out_bit;
     else
         s->scramble_reg |= (in_bit & 1);
+    /*endif*/
     return out_bit;
 }
 /*- End of function --------------------------------------------------------*/
@@ -382,6 +384,7 @@ static __inline__ void put_bit(v17_rx_state_t *s, int bit)
            testing for ones, but just rely on a constellation mismatch measurement. */
         //span_log(&s->logging, SPAN_LOG_FLOW, "A 1 is really %d\n", out_bit);
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -437,6 +440,8 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
     int re;
     int im;
     int raw;
+    int min_index;
+    int set;
     int constellation_state;
 #if defined(SPANDSP_USE_FIXED_POINTx)
 #define DIST_FACTOR 1024    /* Something less than sqrt(0xFFFFFFFF/10)/10 */
@@ -462,20 +467,23 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
         re = 35;
     else if (re < 0)
         re = 0;
+    /*endif*/
     if (im > 35)
         im = 35;
     else if (im < 0)
         im = 0;
+    /*endif*/
     if (s->bits_per_symbol == 2)
     {
         /* 4800bps V.32bis mode, without trellis coding */
-        nearest = constel_map_4800[re][im];
-        raw = v32bis_4800_differential_decoder[s->diff][nearest];
-        s->diff = nearest;
+        constellation_state = constel_map_4800[re][im];
+        raw = v32bis_4800_differential_decoder[s->diff][constellation_state];
+        s->diff = constellation_state;
         put_bit(s, raw);
         put_bit(s, raw >> 1);
-        return nearest;
+        return constellation_state;
     }
+    /*endif*/
 
     /* Find a set of 8 candidate constellation positions, that are the closest
        to the target, with different patterns in the last 3 bits. */
@@ -485,7 +493,7 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
 #else
     min = 9999999.0f;
 #endif
-    j = 0;
+    min_index = 0;
     for (i = 0;  i < 8;  i++)
     {
         nearest = constel_maps[s->space_map][re][im][i];
@@ -499,13 +507,16 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
         if (min > distances[i])
         {
             min = distances[i];
-            j = i;
+            min_index = i;
         }
+        /*endif*/
     }
-    /* Use the nearest of these soft-decisions as the basis for DFE */
-    constellation_state = constel_maps[s->space_map][re][im][j];
-    /* Control the equalizer, carrier tracking, etc. based on the non-trellis
-       corrected information. The trellis correct stuff comes out a bit late. */
+    /*endfor*/
+    /* Use the nearest of these soft-decisions as the basis for DFE and carrier
+       tracking. This is a compromise. It means we will use the correct error
+       less often, but using the output of the traceback would put more lag
+       into the feedback path. */
+    constellation_state = constel_maps[s->space_map][re][im][min_index];
     track_carrier(s, z, &s->constellation[constellation_state]);
     //tune_equalizer(s, z, &s->constellation[constellation_state]);
 
@@ -517,70 +528,62 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
     /* Update the minimum accumulated distance to each of the 8 states */
     if (++s->trellis_ptr >= V17_TRELLIS_STORAGE_DEPTH)
         s->trellis_ptr = 0;
-    for (i = 0;  i < 4;  i++)
+    /*endif*/
+    for (i = 0;  i < 8;  i++)
     {
-        min = distances[tcm_paths[i][0]] + s->distances[0];
-        k = 0;
+        set = i >> 2;
+        min = distances[tcm_paths[i][0]] + s->distances[set];
+        min_index = 0;
         for (j = 1;  j < 4;  j++)
         {
-            if (min > distances[tcm_paths[i][j]] + s->distances[j << 1])
+            k = (j << 1) + set;
+            if (min > distances[tcm_paths[i][j]] + s->distances[k])
             {
-                min = distances[tcm_paths[i][j]] + s->distances[j << 1];
-                k = j;
+                min = distances[tcm_paths[i][j]] + s->distances[k];
+                min_index = j;
             }
+            /*endif*/
         }
+        /*endfor*/
+        k = (min_index << 1) + set;
         /* Use an elementary IIR filter to track the distance to date. */
 #if defined(SPANDSP_USE_FIXED_POINTx)
-        new_distances[i] = s->distances[k << 1]*9/10 + distances[tcm_paths[i][k]]*1/10;
-#else
-        new_distances[i] = s->distances[k << 1]*0.9f + distances[tcm_paths[i][k]]*0.1f;
-#endif
-        s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][k]];
-        s->past_state_locations[s->trellis_ptr][i] = k << 1;
-    }
-    for (i = 4;  i < 8;  i++)
-    {
-        min = distances[tcm_paths[i][0]] + s->distances[1];
-        k = 0;
-        for (j = 1;  j < 4;  j++)
-        {
-            if (min > distances[tcm_paths[i][j]] + s->distances[(j << 1) + 1])
-            {
-                min = distances[tcm_paths[i][j]] + s->distances[(j << 1) + 1];
-                k = j;
-            }
-        }
-#if defined(SPANDSP_USE_FIXED_POINTx)
-        new_distances[i] = s->distances[(k << 1) + 1]*9/10 + distances[tcm_paths[i][k]]*1/10;
+        new_distances[i] = s->distances[k]*9/10 + distances[tcm_paths[i][min_index]]*1/10;
 #else
-        new_distances[i] = s->distances[(k << 1) + 1]*0.9f + distances[tcm_paths[i][k]]*0.1f;
+        new_distances[i] = s->distances[k]*0.9f + distances[tcm_paths[i][min_index]]*0.1f;
 #endif
-        s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][k]];
-        s->past_state_locations[s->trellis_ptr][i] = (k << 1) + 1;
+        s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][min_index]];
+        s->past_state_locations[s->trellis_ptr][i] = k;
     }
+    /*endfor*/
     memcpy(s->distances, new_distances, sizeof(s->distances));
 
     /* Find the minimum distance to date. This is the start of the path back to the result. */
     min = s->distances[0];
-    k = 0;
+    min_index = 0;
     for (i = 1;  i < 8;  i++)
     {
         if (min > s->distances[i])
         {
             min = s->distances[i];
-            k = i;
+            min_index = i;
         }
+        /*endif*/
     }
+    /*endfor*/
     /* Trace back through every time step, starting with the current one, and find the
        state from which the path came one step before. At the end of this search, the
        last state found also points to the constellation point at that state. This is the
        output of the trellis. */
+    k = min_index;
     for (i = 0, j = s->trellis_ptr;  i < V17_TRELLIS_LOOKBACK_DEPTH - 1;  i++)
     {
         k = s->past_state_locations[j][k];
         if (--j < 0)
             j = V17_TRELLIS_STORAGE_DEPTH - 1;
+        /*endif*/
     }
+    /*endfor*/
     nearest = s->full_path_to_past_state_locations[j][k] >> 1;
 
     /* Differentially decode */
@@ -591,6 +594,7 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
         put_bit(s, raw);
         raw >>= 1;
     }
+    /*endfor*/
     return constellation_state;
 }
 /*- End of function --------------------------------------------------------*/
@@ -645,10 +649,12 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
         i = (v > FP_SYNC_SCALE_32(1000.0f))  ?  15  :  1;
         if (s->baud_phase < FP_SYNC_SCALE_32(0.0f))
             i = -i;
+        /*endif*/
         //printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
         s->eq_put_step += i;
         s->total_baud_timing_correction += i;
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -696,10 +702,12 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
     s->eq_buf[s->eq_step] = *sample;
     if (++s->eq_step >= V17_EQUALIZER_LEN)
         s->eq_step = 0;
+    /*endif*/
 
     /* On alternate insertions we have a whole baud and must process it. */
     if ((s->baud_half ^= 1))
         return;
+    /*endif*/
 
     /* Symbol timing synchronisation */
     symbol_sync(s);
@@ -725,7 +733,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->last_angles[0] = arctan2(z.im, z.re);
             if (s->agc_scaling_save == FP_SCALE(0.0f))
                 s->agc_scaling_save = s->agc_scaling;
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_LOG_PHASE:
         /* Record the current alternate phase angle */
@@ -749,6 +759,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 s->last_angles[0] = DDS_PHASE(180.0f + 18.433f);
                 s->last_angles[1] = DDS_PHASE(270.0f + 18.433f);
             }
+            /*endif*/
             /* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
                buffer, as well as the carrier phase, for this to play out nicely. */
             /* angle is now the difference between where A is, and where it should be */
@@ -759,6 +770,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             z16 = complex_seti16(fixed_cos(ip), -fixed_sin(ip));
             for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mul_q1_15(&s->eq_buf[i], &z16);
+            /*endfor*/
             s->carrier_track_p = 500000;
 #else
             p = dds_phase_to_radians(phase_step);
@@ -766,6 +778,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             zz = complex_setf(cosf(p), -sinf(p));
             for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
+            /*endfor*/
             s->carrier_track_p = 500000.0f;
 #endif
             s->carrier_phase += phase_step;
@@ -776,6 +789,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->last_angles[1] = angle;
             s->training_stage = TRAINING_STAGE_WAIT_FOR_CDBA;
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_WAIT_FOR_CDBA:
         target = &zero;
@@ -803,6 +817,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 s->carrier_phase_rate += 3*16*(ang/20);
                 span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, dist %d\n", s->last_angles[0], s->last_angles[1], i);
             }
+            /*endif*/
             span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
             /* Check if the carrier frequency is plausible */
             if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
@@ -816,6 +831,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
                 break;
             }
+            /*endif*/
 
             /* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer buffer,
                as well as the carrier phase, for this to play out nicely. */
@@ -827,12 +843,14 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             z16 = complex_seti16(fixed_cos(ip), -fixed_sin(ip));
             for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mul_q1_15(&s->eq_buf[i], &z16);
+            /*endfor*/
 #else
             p = dds_phase_to_radians(phase_step);
             span_log(&s->logging, SPAN_LOG_FLOW, "Spin (long) by %.5f rads\n", p);
             zz = complex_setf(cosf(p), -sinf(p));
             for (i = 0;  i < V17_EQUALIZER_LEN;  i++)
                 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
+            /*endfor*/
 #endif
             s->carrier_phase += phase_step;
 
@@ -845,6 +863,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
             break;
         }
+        /*endif*/
         if (++s->training_count > V17_TRAINING_SEG_1_LEN)
         {
             /* This is bogus. There are not this many bits in this section
@@ -855,6 +874,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->training_stage = TRAINING_STAGE_PARKED;
             report_status_change(s, SIG_STATUS_TRAINING_FAILED);
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_COARSE_TRAIN_ON_CDBA:
         /* Train on the scrambled CDBA section. */
@@ -886,6 +906,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #endif
             s->training_stage = TRAINING_STAGE_FINE_TRAIN_ON_CDBA;
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_FINE_TRAIN_ON_CDBA:
         /* Train on the scrambled CDBA section. */
@@ -907,6 +928,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #endif
             s->training_stage = TRAINING_STAGE_TRAIN_ON_CDBA_AND_TEST;
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_TRAIN_ON_CDBA_AND_TEST:
         /* Continue training on the scrambled CDBA section, but measure the quality of training too. */
@@ -950,7 +972,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
             }
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_BRIDGE:
         descramble(s, V17_BRIDGE_WORD >> ((s->training_count & 0x7) << 1));
@@ -972,7 +996,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 /* Wait for the trellis to wind up */
                 s->training_stage = TRAINING_STAGE_TCM_WINDUP;
             }
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA:
         /* Look for the initial ABAB sequence to display a phase reversal, which will
@@ -989,19 +1015,23 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->training_error = FP_SCALE(0.0f);
             s->training_count = 1;
             s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
-            break;
         }
-        target = &cdba[(s->training_count & 1) + 2];
-        track_carrier(s, &z, target);
-        if (++s->training_count > V17_TRAINING_SEG_1_LEN)
+        else
         {
-            /* This is bogus. There are not this many bits in this section
-               of a real training sequence. Note that this might be TEP. */
-            span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
-            /* Park this modem */
-            s->training_stage = TRAINING_STAGE_PARKED;
-            report_status_change(s, SIG_STATUS_TRAINING_FAILED);
+            target = &cdba[(s->training_count & 1) + 2];
+            track_carrier(s, &z, target);
+            if (++s->training_count > V17_TRAINING_SEG_1_LEN)
+            {
+                /* This is bogus. There are not this many bits in this section
+                   of a real training sequence. Note that this might be TEP. */
+                span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
+                /* Park this modem */
+                s->training_stage = TRAINING_STAGE_PARKED;
+                report_status_change(s, SIG_STATUS_TRAINING_FAILED);
+            }
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST:
         /* Short retrain on the scrambled CDBA section, but measure the quality of training too. */
@@ -1022,6 +1052,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->training_error += powerf(&zz);
 #endif
         }
+        /*endif*/
         if (++s->training_count >= V17_TRAINING_SHORT_SEG_2_LEN)
         {
 #if defined(SPANDSP_USE_FIXED_POINTx)
@@ -1052,6 +1083,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                     /* Wait for the trellis to wind up */
                     s->training_stage = TRAINING_STAGE_TCM_WINDUP;
                 }
+                /*endif*/
                 report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
             }
             else
@@ -1061,7 +1093,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
             }
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_TCM_WINDUP:
         /* We need to wait 15 bauds while the trellis fills up. */
@@ -1084,6 +1118,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             s->diff = (s->short_train)  ?  0  :  1;
             s->training_stage = TRAINING_STAGE_TEST_ONES;
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_TEST_ONES:
         /* We are in the test phase, where we check that we can receive reliably.
@@ -1128,10 +1163,13 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
 #endif
                 if (!s->short_train)
                     s->agc_scaling_save = FP_SCALE(0.0f);
+                /*endif*/
                 s->training_stage = TRAINING_STAGE_PARKED;
                 report_status_change(s, SIG_STATUS_TRAINING_FAILED);
             }
+            /*endif*/
         }
+        /*endif*/
         break;
     case TRAINING_STAGE_PARKED:
     default:
@@ -1140,6 +1178,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         target = &zero;
         break;
     }
+    /*endswitch*/
     if (s->qam_report)
     {
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -1155,6 +1194,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         s->qam_report(s->qam_user_data, &z, target, constellation_state);
 #endif
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -1183,13 +1223,16 @@ static __inline__ int signal_detect(v17_rx_state_t *s, int16_t amp)
             s->high_sample = 0;
             s->low_samples = 0;
         }
+        /*endif*/
     }
     else
     {
         s->low_samples = 0;
         if (diff > s->high_sample)
             s->high_sample = diff;
+        /*endif*/
     }
+    /*endif*/
 #endif
     if (s->signal_present > 0)
     {
@@ -1208,23 +1251,27 @@ static __inline__ int signal_detect(v17_rx_state_t *s, int16_t amp)
                 report_status_change(s, SIG_STATUS_CARRIER_DOWN);
                 return 0;
             }
+            /*endif*/
 #if defined(IAXMODEM_STUFF)
             /* Carrier has dropped, but the put_bit is pending the signal_present delay. */
             s->carrier_drop_pending = true;
 #endif
         }
+        /*endif*/
     }
     else
     {
         /* Look for power exceeding turn-on threshold to turn the carrier on */
         if (power < s->carrier_on_power)
             return 0;
+        /*endif*/
         s->signal_present = 1;
 #if defined(IAXMODEM_STUFF)
         s->carrier_drop_pending = false;
 #endif
         report_status_change(s, SIG_STATUS_CARRIER_UP);
     }
+    /*endif*/
     return power;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1252,21 +1299,26 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
         s->rrc_filter[s->rrc_filter_step] = amp[i];
         if (++s->rrc_filter_step >= V17_RX_FILTER_STEPS)
             s->rrc_filter_step = 0;
+        /*endif*/
 
         if ((power = signal_detect(s, amp[i])) == 0)
             continue;
+        /*endif*/
         if (s->training_stage == TRAINING_STAGE_PARKED)
             continue;
+        /*endif*/
         /* Only spend effort processing this data if the modem is not
            parked, after training failure. */
         s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
         step = -s->eq_put_step;
         if (step < 0)
             step += RX_PULSESHAPER_COEFF_SETS;
+        /*endif*/
         if (step < 0)
             step = 0;
         else if (step > RX_PULSESHAPER_COEFF_SETS - 1)
             step = RX_PULSESHAPER_COEFF_SETS - 1;
+        /*endif*/
 #if defined(SPANDSP_USE_FIXED_POINTx)
         v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
         sample.re = (v*s->agc_scaling) >> 10;
@@ -1305,12 +1357,14 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
             {
                 if ((root_power = fixed_sqrt32(power)) == 0)
                     root_power = 1;
+                /*endif*/
 #if defined(SPANDSP_USE_FIXED_POINTx)
                 s->agc_scaling = saturate16(((int32_t) (FP_SCALE(2.17f)*1024.0f))/root_power);
 #else
                 s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/root_power;
 #endif
             }
+            /*endif*/
             /* Pulse shape while still at the carrier frequency, using a quadrature
                pair of filters. This results in a properly bandpass filtered complex
                signal, which can be brought directly to baseband by complex mixing.
@@ -1331,12 +1385,14 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
             s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
             process_half_baud(s, &zz);
         }
+        /*endif*/
 #if defined(SPANDSP_USE_FIXED_POINT)
         dds_advance(&s->carrier_phase, s->carrier_phase_rate);
 #else
         dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
 #endif
     }
+    /*endfor*/
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1350,8 +1406,10 @@ SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
     span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
     if (s->signal_present <= 0)
         return 0;
+    /*endif*/
     if (s->training_stage == TRAINING_STAGE_PARKED)
         return 0;
+    /*endif*/
     for (i = 0;  i < len;  i++)
     {
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -1363,8 +1421,10 @@ SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
         s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
         if (s->eq_put_step <= 0)
             s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
+        /*endif*/
         /* TODO: Should we rotate any buffers */
     }
+    /*endfor*/
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1426,6 +1486,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
     default:
         return -1;
     }
+    /*endswitch*/
     s->bit_rate = bit_rate;
 #if defined(SPANDSP_USE_FIXED_POINTx)
     vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
@@ -1447,6 +1508,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
 #endif
     if (short_train != 2)
         s->short_train = short_train;
+    /*endif*/
     vec_zeroi32(s->last_angles, 2);
     vec_zeroi32(s->diff_angles, 16);
 
@@ -1456,6 +1518,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
        initial paths to merge at the zero states. */
     for (i = 0;  i < 8;  i++)
         s->distances[i] = FP_CONSTELLATION_SCALE(99.0f)*FP_CONSTELLATION_SCALE(1.0f);
+    /*endfor*/
     memset(s->full_path_to_past_state_locations, 0, sizeof(s->full_path_to_past_state_locations));
     memset(s->past_state_locations, 0, sizeof(s->past_state_locations));
     s->distances[0] = 0;
@@ -1493,6 +1556,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
         s->carrier_track_p = 40000.0f;
 #endif
     }
+    /*endif*/
     s->last_sample = 0;
     span_log(&s->logging, SPAN_LOG_FLOW, "Gains %f %f\n", (float) s->agc_scaling_save, (float) s->agc_scaling);
     span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
@@ -1504,6 +1568,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
         s->symbol_sync_high[i] = FP_SCALE(0.0f);
         s->symbol_sync_dc_filter[i] = FP_SCALE(0.0f);
     }
+    /*endfor*/
     s->baud_phase = FP_SCALE(0.0f);
     s->baud_half = 0;
 
@@ -1527,11 +1592,14 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
     default:
         return NULL;
     }
+    /*endswitch*/
     if (s == NULL)
     {
         if ((s = (v17_rx_state_t *) span_alloc(sizeof(*s))) == NULL)
             return NULL;
+        /*endif*/
     }
+    /*endif*/
     memset(s, 0, sizeof(*s));
     span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
     span_log_set_protocol(&s->logging, "V.17 RX");
index 0f344157208570d6e0f7453c81ed50ec130e7525..f3d2a6d8f80cd1f05c0f1078028b8c6fc996537f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Written by Steve Underwood <steveu@coppice.org>
  *
- * Copyright (C) 2004-2009 Steve Underwood
+ * Copyright (C) 2004-2015 Steve Underwood
  *
  * All rights reserved.
  *
index 4dbe338f7290a44f38aa52bd76c3dedc16d05966..318ecad564666dacaa37657df87d4215abb7b7bb 100644 (file)
 
 enum
 {
-    V8_WAIT_1S = 0,     /* Start point when sending CI */
-    V8_AWAIT_ANSAM,     /* Start point when sending initial silence */
+    /* Start point when sending CI */
+    V8_WAIT_1S = 0,
+    /* Start point when sending initial silence */
+    V8_AWAIT_ANSAM,
     V8_CI_ON,
     V8_CI_OFF,
     V8_HEARD_ANSAM,
@@ -113,6 +115,8 @@ enum
     V8_V92_SYNC_OCTET = 0x55
 };
 
+#define Te_TIMEOUT      500
+
 SPAN_DECLARE(const char *) v8_call_function_to_str(int call_function)
 {
     switch (call_function)
@@ -134,6 +138,7 @@ SPAN_DECLARE(const char *) v8_call_function_to_str(int call_function)
     case V8_CALL_FUNCTION_EXTENSION:
         return "Call function is in extension octet";
     }
+    /*endswitch*/
     return "Unknown call function";
 }
 /*- End of function --------------------------------------------------------*/
@@ -171,6 +176,7 @@ SPAN_DECLARE(const char *) v8_modulation_to_str(int modulation_scheme)
     case V8_MOD_V92:
         return "V.92 duplex";
     }
+    /*endswitch*/
     return "???";
 }
 /*- End of function --------------------------------------------------------*/
@@ -186,6 +192,7 @@ SPAN_DECLARE(const char *) v8_protocol_to_str(int protocol)
     case V8_PROTOCOL_EXTENSION:
         return "Extension";
     }
+    /*endswitch*/
     return "Undefined";
 }
 /*- End of function --------------------------------------------------------*/
@@ -209,6 +216,7 @@ SPAN_DECLARE(const char *) v8_pstn_access_to_str(int pstn_access)
     case (V8_PSTN_ACCESS_DCE_ON_DIGITAL | V8_PSTN_ACCESS_ANSWER_DCE_CELLULAR | V8_PSTN_ACCESS_CALL_DCE_CELLULAR):
         return "DCE on digital, and answering and calling modems on cellular";
     }
+    /*endswitch*/
     return "PSTN access unknown";
 }
 /*- End of function --------------------------------------------------------*/
@@ -220,6 +228,7 @@ SPAN_DECLARE(const char *) v8_nsf_to_str(int nsf)
     case 0:
         return "???";
     }
+    /*endswitch*/
     return "???";
 }
 /*- End of function --------------------------------------------------------*/
@@ -245,6 +254,7 @@ SPAN_DECLARE(const char *) v8_pcm_modem_availability_to_str(int pcm_modem_availa
     case (V8_PSTN_PCM_MODEM_V91 | V8_PSTN_PCM_MODEM_V90_V92_DIGITAL | V8_PSTN_PCM_MODEM_V90_V92_ANALOGUE):
         return "V.91 and V.90/V.92 digital/analogue available";
     }
+    /*endswitch*/
     return "PCM availability unknown";
 }
 /*- End of function --------------------------------------------------------*/
@@ -271,6 +281,7 @@ SPAN_DECLARE(const char *) v8_t66_to_str(int t66)
     case 7:
         return "Reserved TIA + others";
     }
+    /*endswitch*/
     return "???";
 }
 /*- End of function --------------------------------------------------------*/
@@ -289,7 +300,9 @@ SPAN_DECLARE(void) v8_log_supported_modulations(v8_state_t *s, int modulation_sc
             span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s%s", comma, v8_modulation_to_str(modulation_schemes & (1 << i)));
             comma = ", ";
         }
+        /*endif*/
     }
+    /*endfor*/
     span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " supported\n");
 }
 /*- End of function --------------------------------------------------------*/
@@ -298,6 +311,7 @@ static int report_event(v8_state_t *s)
 {
     if (s->result_handler)
         s->result_handler(s->result_handler_user_data, &s->result);
+    /*endif*/
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
@@ -321,10 +335,13 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
     s->modulation_bytes = 1;
     if (*p & 0x80)
         modulations |= V8_MOD_V34HDX;
+    /*endif*/
     if (*p & 0x40)
         modulations |= V8_MOD_V34;
+    /*endif*/
     if (*p & 0x20)
         modulations |= V8_MOD_V90;
+    /*endif*/
     ++p;
 
     /* Check for an extension octet */
@@ -333,14 +350,19 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
         s->modulation_bytes++;
         if (*p & 0x80)
             modulations |= V8_MOD_V27TER;
+        /*endif*/
         if (*p & 0x40)
             modulations |= V8_MOD_V29;
+        /*endif*/
         if (*p & 0x04)
             modulations |= V8_MOD_V17;
+        /*endif*/
         if (*p & 0x02)
             modulations |= V8_MOD_V22;
+        /*endif*/
         if (*p & 0x01)
             modulations |= V8_MOD_V32;
+        /*endif*/
         ++p;
 
         /* Check for an extension octet */
@@ -349,17 +371,24 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
             s->modulation_bytes++;
             if (*p & 0x80)
                 modulations |= V8_MOD_V21;
+            /*endif*/
             if (*p & 0x40)
                 modulations |= V8_MOD_V23HDX;
+            /*endif*/
             if (*p & 0x04)
                 modulations |= V8_MOD_V23;
+            /*endif*/
             if (*p & 0x02)
                 modulations |= V8_MOD_V26BIS;
+            /*endif*/
             if (*p & 0x01)
                 modulations |= V8_MOD_V26TER;
-             ++p;
+            /*endif*/
+            ++p;
         }
+        /*endif*/
     }
+    /*endif*/
     s->result.modulations = modulations;
     v8_log_supported_modulations(s, modulations);
     return p;
@@ -411,6 +440,7 @@ static void ci_decode(v8_state_t *s)
 {
     if ((s->rx_data[0] & 0x1F) == V8_CALL_FUNCTION_TAG)
         process_call_function(s, &s->rx_data[0]);
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -420,6 +450,7 @@ static void cm_jm_decode(v8_state_t *s)
 
     if (s->got_cm_jm)
         return;
+    /*endif*/
 
     /* We must receive two consecutive identical CM or JM sequences to accept it. */
     if (s->cm_jm_len <= 0
@@ -433,6 +464,7 @@ static void cm_jm_decode(v8_state_t *s)
         memcpy(s->cm_jm_data, s->rx_data, s->rx_data_ptr);
         return;
     }
+    /*endif*/
     /* We have a matching pair of CMs or JMs, so we are happy this is correct. */
     s->got_cm_jm = true;
 
@@ -473,10 +505,13 @@ static void cm_jm_decode(v8_state_t *s)
             p++;
             break;
         }
+        /*endswitch*/
         /* Skip any future extensions we do not understand */
         while ((*p & 0x38) == 0x10)
             p++;
+        /*endwhile*/
     }
+    /*endwhile*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -501,8 +536,10 @@ static void put_bit(void *user_data, int bit)
         default:
             break;
         }
+        /*endswitch*/
         return;
     }
+    /*endif*/
     //span_log(&s->logging, SPAN_LOG_FLOW, "Bit %d\n", bit);
     /* Wait until we sync. */
     s->bit_stream = (s->bit_stream >> 1) | (bit << 19);
@@ -529,6 +566,7 @@ static void put_bit(void *user_data, int bit)
         new_preamble_type = V8_SYNC_UNKNOWN;
         break;
     }
+    /*endswitch*/
     if (new_preamble_type != V8_SYNC_UNKNOWN)
     {
         /* We have seen a fresh sync code */
@@ -552,9 +590,12 @@ static void put_bit(void *user_data, int bit)
                     tag = ">??: ";
                     break;
                 }
+                /*endswitch*/
                 span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, s->rx_data, s->rx_data_ptr);
             }
+            /*endif*/
         }
+        /*endif*/
         /* If we were handling a valid sync code then we should process what has been
            received to date. */
         switch (s->preamble_type)
@@ -566,10 +607,12 @@ static void put_bit(void *user_data, int bit)
             cm_jm_decode(s);
             break;
         }
+        /*endswitch*/
         s->preamble_type = new_preamble_type;
         s->bit_cnt = 0;
         s->rx_data_ptr = 0;
     }
+    /*endif*/
 
     if (s->preamble_type != V8_SYNC_UNKNOWN)
     {
@@ -585,17 +628,22 @@ static void put_bit(void *user_data, int bit)
             {
                 if (++s->zero_byte_count == 3)
                     s->got_cj = true;
+                /*endif*/
             }
             else
             {
                 s->zero_byte_count = 0;
             }
+            /*endif*/
 
             if (s->rx_data_ptr < (int) (sizeof(s->rx_data) - 1))
                 s->rx_data[s->rx_data_ptr++] = data;
+            /*endif*/
             s->bit_cnt = 0;
         }
+        /*endif*/
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -625,6 +673,7 @@ static int get_bit(void *user_data)
     s = user_data;
     if (queue_read(s->tx_queue, &bit, 1) <= 0)
         return SIG_STATUS_END_OF_DATA;
+    /*endif*/
     return bit;
 }
 /*- End of function --------------------------------------------------------*/
@@ -657,9 +706,11 @@ static void v8_put_bytes(v8_state_t *s, uint8_t buf[], int len)
             bits[j] = byte & 1;
             byte >>= 1;
         }
+        /*endfor*/
         bits[9] = 1;
         queue_write(s->tx_queue, bits, 10);
     }
+    /*endfor*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -684,50 +735,68 @@ static void send_cm_jm(v8_state_t *s)
     val = 0x05;
     if (offered_modulations & V8_MOD_V90)
         val |= 0x20;
+    /*endif*/
     if (offered_modulations & V8_MOD_V34)
         val |= 0x40;
+    /*endif*/
     if (offered_modulations & V8_MOD_V34HDX)
         val |= 0x80;
+    /*endif*/
     buf[ptr++] = val;
     if (++bytes < s->modulation_bytes)
     {
         val = 0x10;
         if (offered_modulations & V8_MOD_V32)
             val |= 0x01;
+        /*endif*/
         if (offered_modulations & V8_MOD_V22)
             val |= 0x02;
+        /*endif*/
         if (offered_modulations & V8_MOD_V17)
             val |= 0x04;
+        /*endif*/
         if (offered_modulations & V8_MOD_V29)
             val |= 0x40;
+        /*endif*/
         if (offered_modulations & V8_MOD_V27TER)
             val |= 0x80;
+        /*endif*/
         buf[ptr++] = val;
     }
+    /*endif*/
     if (++bytes < s->modulation_bytes)
     {
         val = 0x10;
         if (offered_modulations & V8_MOD_V26TER)
             val |= 0x01;
+        /*endif*/
         if (offered_modulations & V8_MOD_V26BIS)
             val |= 0x02;
+        /*endif*/
         if (offered_modulations & V8_MOD_V23)
             val |= 0x04;
+        /*endif*/
         if (offered_modulations & V8_MOD_V23HDX)
             val |= 0x40;
+        /*endif*/
         if (offered_modulations & V8_MOD_V21)
             val |= 0x80;
+        /*endif*/
         buf[ptr++] = val;
     }
-
+    /*endif*/
     if (s->parms.protocol)
         buf[ptr++] = (s->parms.protocol << 5) | V8_PROTOCOLS_TAG;
+    /*endif*/
     if (s->parms.pstn_access)
         buf[ptr++] = (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG;
+    /*endif*/
     if (s->parms.pcm_modem_availability)
         buf[ptr++] = (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG;
+    /*endif*/
     if (s->parms.t66 >= 0)
         buf[ptr++] = (s->parms.t66 << 5) | V8_T66_TAG;
+    /*endif*/
     /* No NSF */
     //buf[ptr++] = (0 << 5) | V8_NSF_TAG;
     span_log_buf(&s->logging, SPAN_LOG_FLOW, (s->calling_party)  ?  "<CM: "  :  "<JM: ", &buf[1], ptr - 1);
@@ -743,23 +812,25 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
     len = 0;
     if (s->modem_connect_tone_tx_on)
     {
-        if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 2))
+        if (s->modem_connect_tone_tx_on == (milliseconds_to_samples(75) + 2))
         {
             if (s->fsk_tx_on)
             {
                 /* The initial silence is over */
                 s->modem_connect_tone_tx_on = 0;
             }
+            /*endif*/
         }
-        else if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 1))
+        else if (s->modem_connect_tone_tx_on == (milliseconds_to_samples(75) + 1))
         {
             /* Send the ANSam tone */
             len = modem_connect_tones_tx(&s->ansam_tx, amp, max_len);
             if (len < max_len)
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "ANSam or ANSam/ ended\n");
-                s->modem_connect_tone_tx_on = ms_to_samples(75);
+                s->modem_connect_tone_tx_on = milliseconds_to_samples(75);
             }
+            /*endif*/
         }
         else
         {
@@ -768,10 +839,13 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
                 len = s->modem_connect_tone_tx_on;
             else
                 len = max_len;
+            /*endif*/
             vec_zeroi16(amp, len);
             s->modem_connect_tone_tx_on -= len;
         }
+        /*endif*/
     }
+    /*endif*/
     if (s->fsk_tx_on  &&  len < max_len)
     {
         len += fsk_tx(&s->v21tx, &amp[len], max_len - len);
@@ -781,33 +855,38 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
             s->fsk_tx_on = false;
             //s->state = V8_PARKED;
         }
+        /*endif*/
     }
+    /*endif*/
     if (s->state != V8_PARKED  &&  len < max_len)
     {
         vec_zeroi16(&amp[len], max_len - len);
         len = max_len;
     }
+    /*endif*/
     return len;
 }
 /*- End of function --------------------------------------------------------*/
 
-static void send_v92(v8_state_t *s)
+static void conditionally_send_v92(v8_state_t *s)
 {
     int i;
     uint8_t buf[2];
 
-    if (s->result.v92 >= 0)
+    if (s->parms.v92 >= 0)
     {
         /* Send 2 V.92 packets */
         for (i = 0;  i < 2;  i++)
         {
             v8_put_preamble(s);
             buf[0] = V8_V92_SYNC_OCTET;
-            buf[1] = s->result.v92;
+            buf[1] = s->parms.v92;
             span_log_buf(&s->logging, SPAN_LOG_FLOW, "<V.92: ", &buf[1], 1);
             v8_put_bytes(s, buf, 2);
         }
+        /*endfor*/
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -825,6 +904,7 @@ static void send_ci(v8_state_t *s)
         span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CI: ", &buf[1], 1);
         v8_put_bytes(s, buf, 2);
     }
+    /*endfor*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -839,7 +919,9 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
         /* Set the Te interval. The spec. says 500ms is the minimum,
            but gives reasons why 1 second is a better value (V.8/8.1.1). */
         s->state = V8_HEARD_ANSAM;
-        s->ci_timer = ms_to_samples(1000);
+        s->ci_timer = milliseconds_to_samples(2*Te_TIMEOUT);
+        s->negotiation_timer = milliseconds_to_samples(5000);
+        v8_decode_init(s);
     }
     else
     {
@@ -850,6 +932,7 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
         s->result.status = V8_STATUS_NON_V8_CALL;
         report_event(s);
     }
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -868,6 +951,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
         /* Wait 1 second before sending the first CI packet */
         if ((s->negotiation_timer -= len) > 0)
             break;
+        /*endif*/
         fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
         send_ci(s);
         s->state = V8_CI_ON;
@@ -881,12 +965,15 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             handle_modem_connect_tone(s, tone);
             break;
         }
+        /*endif*/
         if (!s->fsk_tx_on)
         {
             s->state = V8_CI_OFF;
-            s->ci_timer = ms_to_samples(500);
+            s->ci_timer = milliseconds_to_samples(Te_TIMEOUT);
+            s->negotiation_timer = milliseconds_to_samples(5000);
             break;
         }
+        /*endif*/
         break;
     case V8_CI_OFF:
         residual_samples = modem_connect_tones_rx(&s->ansam_rx, amp, len);
@@ -896,6 +983,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             handle_modem_connect_tone(s, tone);
             break;
         }
+        /*endif*/
         if ((s->ci_timer -= len) <= 0)
         {
             if (++s->ci_count >= 10)
@@ -914,28 +1002,30 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
                 s->state = V8_CI_ON;
                 s->fsk_tx_on = true;
             }
+            /*endif*/
         }
+        /*endif*/
         break;
     case V8_AWAIT_ANSAM:
         residual_samples = modem_connect_tones_rx(&s->ansam_rx, amp, len);
         /* Check if an ANSam or ANSam/ tone has been detected */
         if ((tone = modem_connect_tones_rx_get(&s->ansam_rx)) != MODEM_CONNECT_TONES_NONE)
             handle_modem_connect_tone(s, tone);
+        /*endif*/
         break;
     case V8_HEARD_ANSAM:
         /* We have heard the ANSam or ANSam/ signal, but we still need to wait for the
            end of the Te timeout period to comply with the spec. */
         if ((s->ci_timer -= len) <= 0)
         {
-            v8_decode_init(s);
-            s->negotiation_timer = ms_to_samples(5000);
             fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
-            send_v92(s);
+            conditionally_send_v92(s);
             send_cm_jm(s);
-            s->state = V8_CM_ON;
             s->fsk_tx_on = true;
+            s->state = V8_CM_ON;
         }
-        break;
+        /*endif*/
+        /* Fall through */
     case V8_CM_ON:
         residual_samples = fsk_rx(&s->v21rx, amp, len);
         if (s->got_cm_jm)
@@ -951,6 +1041,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             s->fsk_tx_on = true;
             break;
         }
+        /*endif*/
         if ((s->negotiation_timer -= len) <= 0)
         {
             /* Timeout */
@@ -959,20 +1050,23 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             s->result.status = V8_STATUS_FAILED;
             report_event(s);
         }
+        /*endif*/
         if (queue_contents(s->tx_queue) < 10)
         {
             /* Send CM again */
             send_cm_jm(s);
         }
+        /*endif*/
         break;
     case V8_CJ_ON:
         residual_samples = fsk_rx(&s->v21rx, amp, len);
         if (!s->fsk_tx_on)
         {
 #if 0
-            s->negotiation_timer = ms_to_samples(75);
+            s->negotiation_timer = milliseconds_to_samples(75);
             s->state = V8_SIGC;
         }
+        /*endif*/
         break;
     case V8_SIGC:
         if ((s->negotiation_timer -= len) <= 0)
@@ -984,6 +1078,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             s->result.status = V8_STATUS_V8_CALL;
             report_event(s);
         }
+        /*endif*/
         break;
     case V8_CM_WAIT:
         residual_samples = fsk_rx(&s->v21rx, amp, len);
@@ -997,13 +1092,14 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             /* Stop sending ANSam or ANSam/ and send JM instead */
             fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH2], get_bit, s);
             /* Set the timeout for JM */
-            s->negotiation_timer = ms_to_samples(5000);
+            s->negotiation_timer = milliseconds_to_samples(5000);
             s->state = V8_JM_ON;
             send_cm_jm(s);
-            s->modem_connect_tone_tx_on = ms_to_samples(75);
+            s->modem_connect_tone_tx_on = milliseconds_to_samples(75);
             s->fsk_tx_on = true;
             break;
         }
+        /*endif*/
         if ((s->negotiation_timer -= len) <= 0)
         {
             /* Timeout */
@@ -1012,6 +1108,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             s->result.status = V8_STATUS_FAILED;
             report_event(s);
         }
+        /*endif*/
         break;
     case V8_JM_ON:
         residual_samples = fsk_rx(&s->v21rx, amp, len);
@@ -1020,10 +1117,11 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             span_log(&s->logging, SPAN_LOG_FLOW, "CJ recognised\n");
             /* Stop sending JM, flushing anything left in the buffer, and wait 75 ms */
             queue_flush(s->tx_queue);
-            s->negotiation_timer = ms_to_samples(75);
+            s->negotiation_timer = milliseconds_to_samples(75);
             s->state = V8_SIGA;
             break;
         }
+        /*endif*/
         if ((s->negotiation_timer -= len) <= 0)
         {
             /* Timeout */
@@ -1033,11 +1131,13 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             report_event(s);
             break;
         }
+        /*endif*/
         if (queue_contents(s->tx_queue) < 10)
         {
             /* Send JM */
             send_cm_jm(s);
         }
+        /*endif*/
         break;
     case V8_SIGA:
         if (!s->fsk_tx_on)
@@ -1049,11 +1149,13 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
             s->result.status = V8_STATUS_V8_CALL;
             report_event(s);
         }
+        /*endif*/
         break;
     case V8_PARKED:
         residual_samples = len;
         break;
     }
+    /*endswitch*/
     return residual_samples;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1085,30 +1187,34 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, bool calling_party, v8_parms_t *parm
         if (s->result.send_ci)
         {
             s->state = V8_WAIT_1S;
-            s->negotiation_timer = ms_to_samples(1000);
+            s->negotiation_timer = milliseconds_to_samples(1000);
             s->ci_count = 0;
         }
         else
         {
             s->state = V8_AWAIT_ANSAM;
         }
+        /*endif*/
         modem_connect_tones_rx_init(&s->ansam_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
         fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH1], get_bit, s);
-        s->modem_connect_tone_tx_on = ms_to_samples(75) + 2;
+        s->modem_connect_tone_tx_on = milliseconds_to_samples(75) + 2;
     }
     else
     {
         /* Send the ANSam or ANSam/ tone */
         s->state = V8_CM_WAIT;
-        s->negotiation_timer = ms_to_samples(200 + 5000);
+        s->negotiation_timer = milliseconds_to_samples(200 + 5000);
         v8_decode_init(s);
         modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
-        s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
+        s->modem_connect_tone_tx_on = milliseconds_to_samples(75) + 1;
     }
+    /*endif*/
     if (s->tx_queue)
         queue_free(s->tx_queue);
+    /*endif*/
     if ((s->tx_queue = queue_init(NULL, 1024, 0)) == NULL)
         return -1;
+    /*endif*/
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1123,7 +1229,9 @@ SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s,
     {
         if ((s = (v8_state_t *) span_alloc(sizeof(*s))) == NULL)
             return NULL;
+        /*endif*/
     }
+    /*endif*/
     memset(s, 0, sizeof(*s));
     span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
     span_log_set_protocol(&s->logging, "V.8");
index 86bd0850634e1b9e620d63944554b14922667b32..e156f2d3e5428a3bf3f58a6d6bf70e183b2562e2 100644 (file)
@@ -188,6 +188,10 @@ static int modem_tests(int use_gui, int log_audio, int test_sending)
         bert_set_report(bert[i], 100000, reporter, (void *) (intptr_t) i);
         if ((data_modems_state[i] = data_modems_init(NULL,
                                                      calling_party,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
                                                      put_msg,
                                                      get_msg,
                                                      NULL)) == NULL)
index c836f9659ed9a6559fe2acd93fa34f5956fdeb55..e72a3f87160d0e28d4f412723934b87bcee3553b 100644 (file)
@@ -67,6 +67,61 @@ int16_t wave_buffer[4096];
 
 data_modems_state_t *data_modem_state;
 
+int answered = false;
+int done = false;
+
+static int modem_call_control(data_modems_state_t *s, void *user_data, int op, const char *num)
+{
+    printf("\nModem control - %s", at_modem_control_to_str(op));
+    switch (op)
+    {
+    case AT_MODEM_CONTROL_CALL:
+        printf(" %s", num);
+        data_modems_call_event(s, AT_CALL_EVENT_CONNECTED);
+        break;
+    case AT_MODEM_CONTROL_ANSWER:
+        answered = true;
+        data_modems_call_event(s, AT_CALL_EVENT_ANSWERED);
+        break;
+    case AT_MODEM_CONTROL_HANGUP:
+        done = true;
+        break;
+    case AT_MODEM_CONTROL_OFFHOOK:
+        break;
+    case AT_MODEM_CONTROL_DTR:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_RTS:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_CTS:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_CAR:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_RNG:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_DSR:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_SETID:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_RESTART:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    case AT_MODEM_CONTROL_DTE_TIMEOUT:
+        printf(" %d", (int) (intptr_t) num);
+        break;
+    }
+    /*endswitch*/
+    printf("\n");
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 static int get_msg(void *user_data, uint8_t msg[], int len)
 {
     return 0;
@@ -79,17 +134,31 @@ static void put_msg(void *user_data, const uint8_t msg[], int len)
         printf("Status %s\n", signal_status_to_str(len));
     else
         printf("Put %d '%s'\n", len, msg);
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
 static void terminal_callback(void *user_data, const uint8_t msg[], int len)
 {
+    data_modems_state_t *s;
+    int i;
+
+    s = (data_modems_state_t *) user_data;
     printf("terminal callback %d\n", len);
+    for (i = 0;  i < len;  i++)
+    {
+        printf("0x%x ", msg[i]);
+    }
+    printf("\n");
+    at_interpreter(&s->at_state, msg, len);
 }
 /*- End of function --------------------------------------------------------*/
 
 static int termios_callback(void *user_data, struct termios *termios)
 {
+    data_modems_state_t *s;
+
+    s = (data_modems_state_t *) user_data;
     printf("termios callback\n");
     return 0;
 }
@@ -116,7 +185,9 @@ static int rx_callback(void *user_data, const int16_t amp[], int samples)
     {
         for (i = 0;  i < samples;  i++)
             wave_buffer[2*i] = amp[i];
+        /*endfor*/
     }
+    /*endif*/
     return out_samples;
 }
 /*- End of function --------------------------------------------------------*/
@@ -137,10 +208,13 @@ static int tx_callback(void *user_data, int16_t amp[], int samples)
     {
         if (out_samples < samples)
             memset(&amp[out_samples], 0, (samples - out_samples)*2);
+        /*endif*/
         for (i = 0;  i < samples;  i++)
             wave_buffer[2*i + 1] = amp[i];
+        /*endfor*/
         sf_writef_short(wave_handle, wave_buffer, samples);
     }
+    /*endif*/
     return samples;
 }
 /*- End of function --------------------------------------------------------*/
@@ -153,6 +227,10 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
     /* Now set up and run the modems */
     if ((data_modem_state = data_modems_init(NULL,
                                              calling_party,
+                                             terminal_write,
+                                             NULL,
+                                             modem_call_control,
+                                             NULL,
                                              put_msg,
                                              get_msg,
                                              NULL)) == NULL)
@@ -160,6 +238,7 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
         fprintf(stderr, "    Cannot start the data modem\n");
         exit(2);
     }
+    /*endif*/
     logging = data_modems_get_logging_state(data_modem_state);
     span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_DATE);
     span_log_set_tag(logging, "Modem");
@@ -180,6 +259,9 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
         fprintf(stderr, "    Cannot start the socket harness\n");
         exit(2);
     }
+    /*endif*/
+
+    data_modems_set_at_tx_handler(data_modem_state, terminal_write, s);
 
     wave_handle = NULL;
     if (log_audio)
@@ -189,9 +271,11 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
             fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
             exit(2);
         }
+        /*endif*/
     }
+    /*endif*/
 
-    socket_harness_run(s);
+    socket_harness_run(s, calling_party);
 
     if (log_audio)
     {
@@ -200,7 +284,9 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
             fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
             exit(2);
         }
+        /*endif*/
     }
+    /*endif*/
 
     return 0;
 }
@@ -242,10 +328,13 @@ int main(int argc, char *argv[])
             exit(2);
             break;
         }
+        /*endswitch*/
     }
+    /*endwhile*/
 
     if (modem_tests(use_gui, log_audio, calling_party))
         exit(2);
+    /*endif*/
     printf("Tests passed\n");
     return 0;
 }
index f946f4a8a7a2ec58e6db521884028bd788e10503..73b09e230aa04d6c86f17c18a802d4b93a367e25 100644 (file)
@@ -79,7 +79,16 @@ static void log_signal(int signum)
 }
 /*- End of function --------------------------------------------------------*/
 
-int socket_harness_run(socket_harness_state_t *s)
+int terminal_write(void *user_data, const char *buf, int len)
+{
+    socket_harness_state_t *s;
+    
+    s = (socket_harness_state_t *) user_data;
+    return write(s->pty_fd, buf, len);
+}
+/*- End of function --------------------------------------------------------*/
+
+int socket_harness_run(socket_harness_state_t *s, int kick)
 {
     struct timeval tmo;
     fd_set rset;
@@ -91,6 +100,23 @@ int socket_harness_run(socket_harness_state_t *s)
     int tx_samples;
     int ret;
 
+    if (kick)
+    {
+        samples = 160;
+        tx_samples = s->tx_callback(s->user_data, outbuf, samples);
+        if (tx_samples < samples)
+            memset(&outbuf[tx_samples], 0, (samples - tx_samples)*2);
+
+        if ((count = write(s->audio_fd, outbuf, samples*2)) < 0)
+        {
+            if (errno != EAGAIN)
+            {
+                fprintf(stderr, "Error: audio write: %s\n", strerror(errno));
+                return -1;
+            }
+            /* TODO: */
+        }
+    }
     while (keep_running)
     {
         //if (s->modem->event)
@@ -131,7 +157,6 @@ int socket_harness_run(socket_harness_state_t *s)
             fprintf(stderr, "Error: select: %s\n", strerror(errno));
             return ret;
         }
-
         if (ret == 0)
         {
             /* Timeout */
index 9b05d5cfbc56877a2926c2fbad08c1c520e1d145..c30485162f843d93673e05d892b253c31e36803c 100644 (file)
@@ -53,7 +53,9 @@ typedef struct socket_harness_state_s
     modem_t modem;
 } socket_harness_state_t;
 
-int socket_harness_run(socket_harness_state_t *s);
+int socket_harness_run(socket_harness_state_t *s, int kick);
+
+int terminal_write(void *user_data, const char *buf, int len);
 
 socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
                                             const char *socket_name,