예제 #1
0
SPAN_DECLARE(modem_connect_tones_tx_state_t *) modem_connect_tones_tx_init(modem_connect_tones_tx_state_t *s,
                                                                           int tone_type)
{
    int alloced;

    alloced = FALSE;
    if (s == NULL)
    {
        if ((s = (modem_connect_tones_tx_state_t *) malloc(sizeof(*s))) == NULL)
            return NULL;
        alloced = TRUE;
    }
    s->tone_type = tone_type;
    switch (s->tone_type)
    {
    case MODEM_CONNECT_TONES_FAX_CNG:
        /* 0.5s of 1100Hz+-38Hz + 3.0s of silence repeating. Timing +-15% */
        s->tone_phase_rate = dds_phase_rate(1100.0);
        s->level = dds_scaling_dbm0(-11);
        s->duration_timer = ms_to_samples(500 + 3000);
        s->mod_phase_rate = 0;
        s->tone_phase = 0;
        s->mod_phase = 0;
        s->mod_level = 0;
        break;
    case MODEM_CONNECT_TONES_ANS:
    case MODEM_CONNECT_TONES_ANSAM:
        /* 0.2s of silence, then 2.6s to 4s of 2100Hz+-15Hz tone, then 75ms of silence. */
        s->tone_phase_rate = dds_phase_rate(2100.0);
        s->level = dds_scaling_dbm0(-11);
        s->duration_timer = ms_to_samples(200 + 2600);
        s->mod_phase_rate = dds_phase_rate(15.0);
        s->tone_phase = 0;
        s->mod_phase = 0;
        s->mod_level = (s->tone_type == MODEM_CONNECT_TONES_ANSAM)  ?  s->level/5  :  0;
        break;
    case MODEM_CONNECT_TONES_ANS_PR:
    case MODEM_CONNECT_TONES_ANSAM_PR:
        s->tone_phase_rate = dds_phase_rate(2100.0);
        s->level = dds_scaling_dbm0(-12);
        s->duration_timer = ms_to_samples(200 + 3300);
        s->mod_phase_rate = dds_phase_rate(15.0);
        s->tone_phase = 0;
        s->mod_phase = 0;
        s->hop_timer = ms_to_samples(450);
        s->mod_level = (s->tone_type == MODEM_CONNECT_TONES_ANSAM_PR)  ?  s->level/5  :  0;
        break;
    default:
        if (alloced)
            free(s);
        return NULL;
    }
    return s;
}
예제 #2
0
SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ademco_contactid_sender_state_t *s,
        tone_report_func_t callback,
        void *user_data)
{
    if (s == NULL)
    {
        if ((s = (ademco_contactid_sender_state_t *) span_alloc(sizeof(*s))) == NULL)
            return NULL;
    }
    memset(s, 0, sizeof(*s));
    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
    span_log_set_protocol(&s->logging, "Ademco");

    if (!tone_rx_init)
    {
        make_goertzel_descriptor(&tone_1400_desc, 1400.0f, GOERTZEL_SAMPLES_PER_BLOCK);
        make_goertzel_descriptor(&tone_2300_desc, 2300.0f, GOERTZEL_SAMPLES_PER_BLOCK);
        tone_rx_init = true;
    }
    goertzel_init(&s->tone_1400, &tone_1400_desc);
    goertzel_init(&s->tone_2300, &tone_2300_desc);
    s->current_sample = 0;

    s->callback = callback;
    s->callback_user_data = user_data;

    s->step = 0;
    s->remaining_samples = ms_to_samples(100);
    dtmf_tx_init(&s->dtmf, NULL, NULL);
    /* The specified timing is 50-60ms on, 50-60ms off */
    dtmf_tx_set_timing(&s->dtmf, 55, 55);
    return s;
}
예제 #3
0
SPAN_DECLARE(int) ademco_contactid_sender_tx(ademco_contactid_sender_state_t *s, int16_t amp[], int max_samples)
{
    int sample;
    int samples;

    for (sample = 0;  sample < max_samples;  sample += samples)
    {
        switch (s->step)
        {
        case 0:
            if (!s->clear_to_send)
                return 0;
            s->clear_to_send = false;
            s->step++;
            s->remaining_samples = ms_to_samples(250);
        /* Fall through */
        case 1:
            samples = (s->remaining_samples > (max_samples - sample))  ?  (max_samples - sample)  :  s->remaining_samples;
            vec_zeroi16(&amp[sample], samples);
            s->remaining_samples -= samples;
            if (s->remaining_samples > 0)
                return samples;
            span_log(&s->logging, SPAN_LOG_FLOW, "Pre-send silence finished\n");
            s->step++;
            break;
        case 2:
            samples = dtmf_tx(&s->dtmf, &amp[sample], max_samples - sample);
            if (samples == 0)
            {
                s->clear_to_send = false;
                s->step = 0;
                return sample;
            }
            break;
        default:
            return sample;
        }
    }
    return sample;
}
예제 #4
0
SPAN_DECLARE(ademco_contactid_receiver_state_t *) ademco_contactid_receiver_init(ademco_contactid_receiver_state_t *s,
        ademco_contactid_report_func_t callback,
        void *user_data)
{
    if (s == NULL)
    {
        if ((s = (ademco_contactid_receiver_state_t *) span_alloc(sizeof(*s))) == NULL)
            return NULL;
    }
    memset(s, 0, sizeof(*s));
    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
    span_log_set_protocol(&s->logging, "Ademco");

    dtmf_rx_init(&s->dtmf, dtmf_digit_delivery, (void *) s);
    s->rx_digits_len = 0;

    s->callback = callback;
    s->callback_user_data = user_data;

    s->step = 0;
    s->remaining_samples = ms_to_samples(500);
    return s;
}
예제 #5
0
SPAN_DECLARE(int) ademco_contactid_receiver_tx(ademco_contactid_receiver_state_t *s, int16_t amp[], int max_samples)
{
    int i;
    int samples;

    switch (s->step)
    {
    case 0:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        vec_zeroi16(amp, samples);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "Initial silence finished\n");
        s->step++;
        s->tone_phase_rate = dds_phase_rate(1400.0);
        s->tone_level = dds_scaling_dbm0(-11);
        s->tone_phase = 0;
        s->remaining_samples = ms_to_samples(100);
        return samples;
    case 1:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        for (i = 0;  i < samples;  i++)
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "1400Hz tone finished\n");
        s->step++;
        s->remaining_samples = ms_to_samples(100);
        return samples;
    case 2:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        vec_zeroi16(amp, samples);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "Second silence finished\n");
        s->step++;
        s->tone_phase_rate = dds_phase_rate(2300.0);
        s->tone_level = dds_scaling_dbm0(-11);
        s->tone_phase = 0;
        s->remaining_samples = ms_to_samples(100);
        return samples;
    case 3:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        for (i = 0;  i < samples;  i++)
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "2300Hz tone finished\n");
        s->step++;
        s->remaining_samples = ms_to_samples(100);
        return samples;
    case 4:
        /* Idle here, waiting for a response */
        return 0;
    case 5:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        vec_zeroi16(amp, samples);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "Sending kissoff\n");
        s->step++;
        s->tone_phase_rate = dds_phase_rate(1400.0);
        s->tone_level = dds_scaling_dbm0(-11);
        s->tone_phase = 0;
        s->remaining_samples = ms_to_samples(850);
        return samples;
    case 6:
        samples = (s->remaining_samples > max_samples)  ?  max_samples  :  s->remaining_samples;
        for (i = 0;  i < samples;  i++)
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0);
        s->remaining_samples -= samples;
        if (s->remaining_samples > 0)
            return samples;
        span_log(&s->logging, SPAN_LOG_FLOW, "1400Hz tone finished\n");
        s->step = 4;
        s->remaining_samples = ms_to_samples(100);
        return samples;
    }
    return max_samples;
}
예제 #6
0
파일: sig_tone.c 프로젝트: yallo/plcify
        {     0,        -8578,         -11796},
        15,
#else
        {0.393676f,    -0.5f,          -0.5f}, 
        {0.0f,         -0.261778f,     -0.359985f},
#endif
    }
};

static const sig_tone_descriptor_t sig_tones[3] =
{
    {
        /* 2280Hz (e.g. AC15, and many other European protocols) */
        {2280,  0},
        {{-10, -20}, {0, 0}},       /* -10+-1 dBm0 and -20+-1 dBm0 */
        ms_to_samples(400),         /* High to low timout - 300ms to 550ms */
        ms_to_samples(225),         /* Sharp to flat timeout */
        ms_to_samples(225),         /* Notch insertion timeout */
    
        ms_to_samples(3),           /* Tone on persistence check */
        ms_to_samples(8),           /* Tone off persistence check */

        1,
        {
            &notch_coeffs[NOTCH_COEFF_SET_2280HZ],
            NULL,
        },
        &flat_coeffs[NOTCH_COEFF_SET_2280HZ],

        13.0f,
        -30.0f,
예제 #7
0
static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
{
    fax_state_t *s;
    fax_modems_state_t *t;
    int tone;

    s = (fax_state_t *) user_data;
    t = &s->modems;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (t->current_tx_type == type)
        return;

    switch (type)
    {
    case T30_MODEM_PAUSE:
        silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL);
        t->transmit = true;
        break;
    case T30_MODEM_CED:
    case T30_MODEM_CNG:
        tone = (type == T30_MODEM_CED)  ?  FAX_MODEM_CED_TONE_TX  :  FAX_MODEM_CNG_TONE_TX;
        fax_modems_start_slow_modem(t, tone);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL);
        t->transmit = true;
        break;
    case T30_MODEM_V21:
        fax_modems_start_slow_modem(t, FAX_MODEM_V21_TX);
        /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
        fax_modems_hdlc_tx_flags(t, 32);
        /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
           might not see the carrier fall between the high speed and low speed sections. In practice,
           a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
           a call, and ensures the receiving end is ready. */
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &fsk_tx, &t->v21_tx);
        t->transmit = true;
        break;
    case T30_MODEM_V17:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        fax_modems_hdlc_tx_flags(t, bit_rate/(8*5));
        fax_modems_start_fast_modem(t, FAX_MODEM_V17_TX, bit_rate, short_train, use_hdlc);
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v17_tx, &t->fast_modems.v17_tx);
        t->transmit = true;
        break;
    case T30_MODEM_V27TER:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        fax_modems_hdlc_tx_flags(t, bit_rate/(8*5));
        fax_modems_start_fast_modem(t, FAX_MODEM_V27TER_TX, bit_rate, short_train, use_hdlc);
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v27ter_tx, &t->fast_modems.v27ter_tx);
        t->transmit = true;
        break;
    case T30_MODEM_V29:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        fax_modems_hdlc_tx_flags(t, bit_rate/(8*5));
        fax_modems_start_fast_modem(t, FAX_MODEM_V29_TX, bit_rate, short_train, use_hdlc);
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v29_tx, &t->fast_modems.v29_tx);
        t->transmit = true;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        /* Fall through */
    default:
        silence_gen_alter(&t->silence_gen, 0);
        fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen);
        fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL);
        t->transmit = false;
        break;
    }
    t->tx_bit_rate = bit_rate;
    t->current_tx_type = type;
}
예제 #8
0
static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_train, int use_hdlc)
{
    fax_state_t *s;
    get_bit_func_t get_bit_func;
    void *get_bit_user_data;
    fax_modems_state_t *t;
    int tone;

    s = (fax_state_t *) user_data;
    t = &s->modems;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (t->current_tx_type == type)
        return;
    if (use_hdlc)
    {
        get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
        get_bit_user_data = (void *) &t->hdlc_tx;
    }
    else
    {
        get_bit_func = t30_non_ecm_get_bit;
        get_bit_user_data = (void *) &s->t30;
    }
    switch (type)
    {
    case T30_MODEM_PAUSE:
        silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = TRUE;
        break;
    case T30_MODEM_CED:
    case T30_MODEM_CNG:
        if (type == T30_MODEM_CED)
            tone = MODEM_CONNECT_TONES_FAX_CED;
        else
            tone = MODEM_CONNECT_TONES_FAX_CNG;
        modem_connect_tones_tx_init(&t->connect_tx, tone);
        set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V21:
        fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data);
        /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
        hdlc_tx_flags(&t->hdlc_tx, 32);
        /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
           might not see the carrier fall between the high speed and low speed sections. In practice,
           a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
           a call, and ensures the receiving end is ready. */
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V27TER:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
        v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V29:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
        v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_V17:
        silence_gen_alter(&t->silence_gen, ms_to_samples(75));
        /* For any fast modem, set 200ms of preamble flags */
        hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
        v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
        v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
        t->transmit = TRUE;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        /* Fall through */
    default:
        silence_gen_alter(&t->silence_gen, 0);
        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
        t->transmit = FALSE;
        break;
    }
    t->tx_bit_rate = bit_rate;
    t->current_tx_type = type;
}
예제 #9
0
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len)
{
    t38_terminal_state_t *s;
    uint8_t buf2[len];
    
    s = (t38_terminal_state_t *) user_data;
#if 0
    /* In termination mode we don't care very much what the data type is. */
    switch (data_type)
    {
    case T38_DATA_V21:
    case T38_DATA_V27TER_2400:
    case T38_DATA_V27TER_4800:
    case T38_DATA_V29_7200:
    case T38_DATA_V29_9600:
    case T38_DATA_V17_7200:
    case T38_DATA_V17_9600:
    case T38_DATA_V17_12000:
    case T38_DATA_V17_14400:
    case T38_DATA_V8:
    case T38_DATA_V34_PRI_RATE:
    case T38_DATA_V34_CC_1200:
    case T38_DATA_V34_PRI_CH:
    case T38_DATA_V33_12000:
    case T38_DATA_V33_14400:
    default:
        break;
    }
#endif

    switch (field_type)
    {
    case T38_FIELD_HDLC_DATA:
        if (s->rx_len + len <= T38_MAX_HDLC_LEN)
        {
            bit_reverse(s->rx_buf + s->rx_len, buf, len);
            s->rx_len += len;
        }
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_OK:
        if (len > 0)
        {
            span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
            /* The sender has incorrectly included data in this message. It is unclear what we should do
               with it, to maximise tolerance of buggy implementations. */
        }
        /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK
           packets, when they have sent no data for the body of the frame. */
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (s->rx_len >= 3)  ?  t30_frametype(s->rx_buf[2])  :  "???", (s->missing_data)  ?  "missing octets"  :  "clean");
            t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len);
        }
        s->rx_len = 0;
        s->missing_data = FALSE;
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_BAD:
        if (len > 0)
        {
            span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
            /* The sender has incorrectly included data in this message. We can safely ignore it, as the
               bad FCS means we will throw away the whole message, anyway. */
        }
        /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD
           packets, when they have sent no data for the body of the frame. */
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (s->rx_len >= 3)  ?  t30_frametype(s->rx_buf[2])  :  "???", (s->missing_data)  ?  "missing octets"  :  "clean");
            t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len);
        }
        s->rx_len = 0;
        s->missing_data = FALSE;
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_HDLC_FCS_OK_SIG_END:
        if (len > 0)
        {
            span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
            /* The sender has incorrectly included data in this message. It is unclear what we should do
               with it, to maximise tolerance of buggy implementations. */
        }
        /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END
           packets, when they have sent no data for the body of the frame. */
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (s->rx_len >= 3)  ?  t30_frametype(s->rx_buf[2])  :  "???", (s->missing_data)  ?  "missing octets"  :  "clean");
            t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len);
            t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN);
        }
        s->rx_len = 0;
        s->missing_data = FALSE;
        s->timeout_rx_samples = 0;
        break;
    case T38_FIELD_HDLC_FCS_BAD_SIG_END:
        if (len > 0)
        {
            span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
            /* The sender has incorrectly included data in this message. We can safely ignore it, as the
               bad FCS means we will throw away the whole message, anyway. */
        }
        /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END
           packets, when they have sent no data for the body of the frame. */
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (s->rx_len >= 3)  ?  t30_frametype(s->rx_buf[2])  :  "???", (s->missing_data)  ?  "missing octets"  :  "clean");
            t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len);
            t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN);
        }
        s->rx_len = 0;
        s->missing_data = FALSE;
        s->timeout_rx_samples = 0;
        break;
    case T38_FIELD_HDLC_SIG_END:
        if (len > 0)
        {
            span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n");
            /* The sender has incorrectly included data in this message, but there seems nothing meaningful
               it could be. There could not be an FCS good/bad report beyond this. */
        }
        /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - 
           i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops.
           The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the
                           end of non-ECM data. We need to tolerate this. We use the generic receive complete
                           indication, rather than the specific HDLC carrier down. */
            s->rx_len = 0;
            s->missing_data = FALSE;
            s->timeout_rx_samples = 0;
            t30_receive_complete(&(s->t30_state));
        }
        break;
    case T38_FIELD_T4_NON_ECM_DATA:
        if (!s->rx_signal_present)
        {
            t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED);
            s->rx_signal_present = TRUE;
        }
        bit_reverse(buf2, buf, len);
        t30_non_ecm_put_chunk(&(s->t30_state), buf2, len);
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_FIELD_T4_NON_ECM_SIG_END:
        if (t->current_rx_data_type != data_type
            ||
            t->current_rx_field_type != field_type)
        {
            if (len > 0)
            {
                if (!s->rx_signal_present)
                {
                    t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED);
                    s->rx_signal_present = TRUE;
                }
                bit_reverse(buf2, buf, len);
                t30_non_ecm_put_chunk(&(s->t30_state), buf2, len);
            }
            /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where
                           they should send non-ECM signal end. It is possible they also do the opposite.
                           We need to tolerate this, so we use the generic receive complete
                           indication, rather than the specific non-ECM carrier down. */
            t30_receive_complete(&(s->t30_state));
        }
        s->rx_signal_present = FALSE;
        s->timeout_rx_samples = 0;
        break;
    case T38_FIELD_CM_MESSAGE:
    case T38_FIELD_JM_MESSAGE:
    case T38_FIELD_CI_MESSAGE:
    case T38_FIELD_V34RATE:
    default:
        break;
    }
    return 0;
}
예제 #10
0
SPAN_DECLARE(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *s, const int16_t amp[], int len)
{
    int i;
    int16_t notched;
    float v1;
    float famp;
    
    switch (s->tone_type)
    {
    case MODEM_CONNECT_TONES_FAX_CNG:
        for (i = 0;  i < len;  i++)
        {
            /* A Cauer notch at 1100Hz, spread just wide enough to meet our detection bandwidth
               criteria. */
            famp = amp[i];
            v1 = 0.792928f*famp + 1.0018744927985f*s->z1 - 0.54196833412465f*s->z2;
            famp = v1 - 1.2994747954630f*s->z1 + s->z2;
            s->z2 = s->z1;
            s->z1 = v1;
            notched = (int16_t) lfastrintf(famp);

            /* Estimate the overall energy in the channel, and the energy in
               the notch (i.e. overall channel energy - tone energy => noise).
               Use abs instead of multiply for speed (is it really faster?). */
            s->channel_level += ((abs(amp[i]) - s->channel_level) >> 5);
            s->notch_level += ((abs(notched) - s->notch_level) >> 5);
            if (s->channel_level > 70  &&  s->notch_level*6 < s->channel_level)
            {
                /* There is adequate energy in the channel, and it is mostly at 1100Hz. */
                if (s->tone_present != MODEM_CONNECT_TONES_FAX_CNG)
                {
                    if (++s->tone_cycle_duration >= ms_to_samples(415))
                        report_tone_state(s, MODEM_CONNECT_TONES_FAX_CNG, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
                }
            }
            else
            {
                /* If the signal looks wrong, even for a moment, we consider this the
                   end of the tone. */
                if (s->tone_present == MODEM_CONNECT_TONES_FAX_CNG)
                    report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
                s->tone_cycle_duration = 0;
            }
        }
        break;
    case MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE:
        /* Also look for V.21 preamble. A lot of machines don't send the 2100Hz burst. It
           might also not be seen all the way through the channel, due to switching delays. */
        fsk_rx(&(s->v21rx), amp, len);
        /* Now fall through and look for a 2100Hz tone */
    case MODEM_CONNECT_TONES_ANS:
        for (i = 0;  i < len;  i++)
        {
            /* A Cauer notch at 2100Hz, spread just wide enough to meet our detection bandwidth
               criteria. */
            /* This is actually centred at 2095Hz, but gets the balance we want, due
               to the asymmetric walls of the notch */
            famp = amp[i];
            v1 = 0.76000f*famp - 0.1183852f*s->z1 - 0.5104039f*s->z2;
            famp = v1 + 0.1567596f*s->z1 + s->z2;
            s->z2 = s->z1;
            s->z1 = v1;
            notched = (int16_t) lfastrintf(famp);
            /* Estimate the overall energy in the channel, and the energy in
               the notch (i.e. overall channel energy - tone energy => noise).
               Use abs instead of multiply for speed (is it really faster?).
               Damp the overall energy a little more for a stable result.
               Damp the notch energy a little less, so we don't damp out the
               blip every time the phase reverses */
            s->channel_level += ((abs(amp[i]) - s->channel_level) >> 5);
            s->notch_level += ((abs(notched) - s->notch_level) >> 4);
            /* This should cut off at about -43dBm0 */
            if (s->channel_level <= 70)
            {
                /* If the energy level is low, even for a moment, we consider this the
                   end of the tone. */
                if (s->tone_present != MODEM_CONNECT_TONES_NONE)
                    report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
                s->tone_cycle_duration = 0;
                s->good_cycles = 0;
                s->tone_on = FALSE;
                continue;
            }
            /* There is adequate energy in the channel. Is it mostly at 2100Hz? */
            s->tone_cycle_duration++;
            if (s->notch_level*6 < s->channel_level)
            {
                /* The notch test says yes, so we have the tone. */
                /* We should get a kick from the notch filter every 450+-25ms, as the phase reverses, for an
                   EC disable tone. For a simple answer tone, the tone should persist unbroken for longer. */
                if (!s->tone_on)
                {
                    if (s->tone_cycle_duration >= ms_to_samples(450 - 25))
                    {
                        if (++s->good_cycles == 3)
                            report_tone_state(s, MODEM_CONNECT_TONES_ANS_PR, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
                    }
                    else
                    {
                        s->good_cycles = 0;
                    }
                    /* Cycles are timed from rising edge to rising edge */
                    s->tone_cycle_duration = 0;
                }
                else
                {
                    if (s->tone_cycle_duration >= ms_to_samples(550))
                    {
                        if (s->tone_present == MODEM_CONNECT_TONES_NONE)
                            report_tone_state(s, MODEM_CONNECT_TONES_ANS, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
                        s->good_cycles = 0;
                        s->tone_cycle_duration = ms_to_samples(550);
                    }
                }
                s->tone_on = TRUE;
            }
            else
            {
                if (s->tone_present == MODEM_CONNECT_TONES_ANS)
                {
                    report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
                    s->good_cycles = 0;
                }
                else
                {
                    if (s->tone_cycle_duration >= ms_to_samples(450 + 25))
                    {
                        /* The change came too late for a cycle of ANS_PR tone */
                        if (s->tone_present == MODEM_CONNECT_TONES_ANS_PR  ||  s->tone_present == MODEM_CONNECT_TONES_ANSAM_PR)
                            report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
                        s->good_cycles = 0;
                    }
                }
                s->tone_on = FALSE;
            }
        }
        break;
    }
    return 0;
}
예제 #11
0
static void fax_set_tx_type(void *user_data, int type, int short_train, int use_hdlc)
{
    fax_state_t *s;
    tone_gen_descriptor_t tone_desc;
    get_bit_func_t get_bit_func;
    void *get_bit_user_data;

    s = (fax_state_t *) user_data;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (s->current_tx_type == type)
        return;
    s->first_tx_hdlc_frame = TRUE;
    if (use_hdlc)
    {
        get_bit_func = (get_bit_func_t) hdlc_tx_get_bit;
        get_bit_user_data = (void *) &(s->hdlctx);
    }
    else
    {
        get_bit_func = t30_non_ecm_get_bit;
        get_bit_user_data = (void *) &(s->t30_state);
    }
    switch (type)
    {
    case T30_MODEM_PAUSE:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(short_train));
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = NULL;
        s->transmit = TRUE;
        break;
    case T30_MODEM_CNG:
        /* 0.5s of 1100Hz+-38Hz + 3.0s of silence repeating. Timing +-15% */
        make_tone_gen_descriptor(&tone_desc,
                                 1100,
                                 -11,
                                 0,
                                 0,
                                 500,
                                 3000,
                                 0,
                                 0,
                                 TRUE);
        tone_gen_init(&(s->tone_gen), &tone_desc);
        s->tx_handler = (span_tx_handler_t *) &tone_gen;
        s->tx_user_data = &(s->tone_gen);
        s->next_tx_handler = NULL;
        s->transmit = TRUE;
        break;
    case T30_MODEM_CED:
        /* 0.2s of silence, then 2.6s to 4s of 2100Hz+-15Hz tone, then 75ms of silence. The 75ms of silence
           will be inserted by the pre V.21 pause we use for any switch to V.21. */
        silence_gen_alter(&(s->silence_gen), ms_to_samples(200));
        make_tone_gen_descriptor(&tone_desc,
                                 2100,
                                 -11,
                                 0,
                                 0,
                                 2600,
                                 0,
                                 0,
                                 0,
                                 FALSE);
        tone_gen_init(&(s->tone_gen), &tone_desc);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &tone_gen;
        s->next_tx_user_data = &(s->tone_gen);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V21:
        fsk_tx_init(&(s->v21tx), &preset_fsk_specs[FSK_V21CH2], get_bit_func, get_bit_user_data);
        /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
        hdlc_tx_flags(&(s->hdlctx), 32);
        /* Pause before switching from phase C, as per T.30 5.3.2.2. If we omit this, the receiver
           might not see the carrier fall between the high speed and low speed sections. In practice,
           a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
           a call, and ensures the receiving end is ready. */
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &fsk_tx;
        s->next_tx_user_data = &(s->v21tx);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V27TER_2400:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v27ter_tx_restart(&(s->v27ter_tx), 2400, s->use_tep);
        v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
        s->next_tx_user_data = &(s->v27ter_tx);
        hdlc_tx_flags(&(s->hdlctx), 60);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V27TER_4800:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v27ter_tx_restart(&(s->v27ter_tx), 4800, s->use_tep);
        v27ter_tx_set_get_bit(&(s->v27ter_tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
        s->next_tx_user_data = &(s->v27ter_tx);
        hdlc_tx_flags(&(s->hdlctx), 120);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V29_7200:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v29_tx_restart(&(s->v29tx), 7200, s->use_tep);
        v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v29_tx;
        s->next_tx_user_data = &(s->v29tx);
        hdlc_tx_flags(&(s->hdlctx), 180);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V29_9600:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v29_tx_restart(&(s->v29tx), 9600, s->use_tep);
        v29_tx_set_get_bit(&(s->v29tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v29_tx;
        s->next_tx_user_data = &(s->v29tx);
        hdlc_tx_flags(&(s->hdlctx), 240);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_7200:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 7200, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 180);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_9600:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 9600, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 240);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_12000:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 12000, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 300);
        s->transmit = TRUE;
        break;
    case T30_MODEM_V17_14400:
        silence_gen_alter(&(s->silence_gen), ms_to_samples(75));
        v17_tx_restart(&(s->v17tx), 14400, s->use_tep, short_train);
        v17_tx_set_get_bit(&(s->v17tx), get_bit_func, get_bit_user_data);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = (span_tx_handler_t *) &v17_tx;
        s->next_tx_user_data = &(s->v17tx);
        hdlc_tx_flags(&(s->hdlctx), 360);
        s->transmit = TRUE;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        /* Fall through */
    default:
        silence_gen_alter(&(s->silence_gen), 0);
        s->tx_handler = (span_tx_handler_t *) &silence_gen;
        s->tx_user_data = &(s->silence_gen);
        s->next_tx_handler = NULL;
        s->transmit = FALSE;
        break;
    }
    s->current_tx_type = type;
}
예제 #12
0
static int tx_handler(void *user_data, int what)
{
    //printf("What - %d\n", what);
    if ((what & SIG_TONE_UPDATE_REQUEST))
    {
        printf("Tx: update request\n");
        /* The signaling processor wants to know what to do next */
        if (sampleno < ms_to_samples(100))
        {
            /* 100ms off-hook */
            printf("100ms off-hook - %d samples\n", 800 - sampleno);
            return 0x02 | ((ms_to_samples(100) - sampleno) << 16);
        }
        else if (sampleno < ms_to_samples(600))
        {
            /* 500ms idle */
            printf("500ms idle - %d samples\n", ms_to_samples(600) - sampleno);
            return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(600) - sampleno) << 16);
        }
        else if (sampleno < ms_to_samples(700))
        {
            /* 100ms seize */
            printf("100ms seize - %d samples\n", ms_to_samples(700) - sampleno);
            return 0x02 | ((ms_to_samples(700) - sampleno) << 16);
        }
        else if (sampleno < ms_to_samples(1700))
        {
            if (ping)
            {
                printf("33ms break - %d samples\n", ms_to_samples(33));
                ping = !ping;
                return 0x02 | (ms_to_samples(33) << 16);
            }
            else
            {
                printf("67ms make - %d samples\n", ms_to_samples(67));
                ping = !ping;
                return 0x02 | SIG_TONE_1_PRESENT | (ms_to_samples(67) << 16);
            }
            /*endif*/
        }
        else
        {
            return 0x02 | SIG_TONE_1_PRESENT | ((ms_to_samples(700) - sampleno) << 16) | SIG_TONE_TX_PASSTHROUGH;
        }
        /*endif*/
    }
    /*endif*/
    return 0;
}
예제 #13
0
static void tx_handler(void *user_data, int what, int level, int duration)
{
    sig_tone_tx_state_t *s;
    int tone;
    int time;
    static const int pattern_1_tone[][2] =
    {
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {600, SIG_TONE_1_PRESENT},
        {0, 0}
    };
    static const int pattern_2_tones[][2] =
    {
#if 0
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
        {33, SIG_TONE_1_PRESENT},
        {67, 0},
#endif
        {100, SIG_TONE_1_PRESENT},
        {100, SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT},
        {100, SIG_TONE_2_PRESENT},
#if 0
        {100, 0},
        {100, SIG_TONE_2_PRESENT},
        {100, SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT},
        {100, SIG_TONE_1_PRESENT},
#endif
        {0, 0}
    };
    
    s = (sig_tone_tx_state_t *) user_data;
    tx_handler_callbacks++;
    //printf("What - %d, duration - %d\n", what, duration);
    if ((what & SIG_TONE_TX_UPDATE_REQUEST))
    {
        /* The sig tone transmit side wants to know what to do next */
        printf("Tx: update request\n");

        if (number_of_tones == 1)
        {
            time = pattern_1_tone[tx_section][0];
            tone = pattern_1_tone[tx_section][1];
        }
        else
        {
            time = pattern_2_tones[tx_section][0];
            tone = pattern_2_tones[tx_section][1];
        }
        if (time)
        {
            printf("Tx: [%04x] %s %s for %d samples (%dms)\n",
                   tone,
                   (tone & SIG_TONE_1_PRESENT)  ?  "on "  :  "off",
                   (tone & SIG_TONE_2_PRESENT)  ?  "on "  :  "off",
                   ms_to_samples(time),
                   time);
            sig_tone_tx_set_mode(s, tone, ms_to_samples(time));
            tx_section++;
        }
        else
        {
            printf("End of sequence\n");
        }
    }
    /*endif*/
}
예제 #14
0
static void set_tx_type(void *user_data, int type, int short_train, int use_hdlc)
{
    t38_terminal_state_t *s;

    s = (t38_terminal_state_t *) user_data;
    span_log(&s->logging, SPAN_LOG_FLOW, "Set tx type %d\n", type);
    if (s->current_tx_type == type)
        return;

    switch (type)
    {
    case T30_MODEM_NONE:
        s->timed_step = T38_TIMED_STEP_NONE;
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T30_MODEM_PAUSE:
        s->next_tx_samples = s->samples + ms_to_samples(short_train);
        s->timed_step = T38_TIMED_STEP_PAUSE;
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T30_MODEM_CED:
        /* A 200ms initial delay is specified. Delay this amount before the CED indicator is sent. */
        s->next_tx_samples = s->samples;
        s->timed_step = T38_TIMED_STEP_CED;
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T30_MODEM_CNG:
        /* Allow a short initial delay, so the chances of the other end actually being ready to receive
           the CNG indicator are improved. */
        s->next_tx_samples = s->samples;
        s->timed_step = T38_TIMED_STEP_CNG;
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T30_MODEM_V21:
        if (s->current_tx_type > T30_MODEM_V21)
        {
            /* Pause before switching from phase C, as per T.30. If we omit this, the receiver
               might not see the carrier fall between the high speed and low speed sections. */
            s->next_tx_samples = s->samples + ms_to_samples(75);
        }
        else
        {
            s->next_tx_samples = s->samples;
        }
        set_octets_per_data_packet(s, 300);
        s->next_tx_indicator = T38_IND_V21_PREAMBLE;
        s->current_tx_data_type = T38_DATA_V21;
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V27TER_2400:
        set_octets_per_data_packet(s, 2400);
        s->next_tx_indicator = T38_IND_V27TER_2400_TRAINING;
        s->current_tx_data_type = T38_DATA_V27TER_2400;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V27TER_4800:
        set_octets_per_data_packet(s, 4800);
        s->next_tx_indicator = T38_IND_V27TER_4800_TRAINING;
        s->current_tx_data_type = T38_DATA_V27TER_4800;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V29_7200:
        set_octets_per_data_packet(s, 7200);
        s->next_tx_indicator = T38_IND_V29_7200_TRAINING;
        s->current_tx_data_type = T38_DATA_V29_7200;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V29_9600:
        set_octets_per_data_packet(s, 9600);
        s->next_tx_indicator = T38_IND_V29_9600_TRAINING;
        s->current_tx_data_type = T38_DATA_V29_9600;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V17_7200:
        set_octets_per_data_packet(s, 7200);
        s->next_tx_indicator = (short_train)  ?  T38_IND_V17_7200_SHORT_TRAINING  :  T38_IND_V17_7200_LONG_TRAINING;
        s->current_tx_data_type = T38_DATA_V17_7200;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V17_9600:
        set_octets_per_data_packet(s, 9600);
        s->next_tx_indicator = (short_train)  ?  T38_IND_V17_9600_SHORT_TRAINING  :  T38_IND_V17_9600_LONG_TRAINING;
        s->current_tx_data_type = T38_DATA_V17_9600;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V17_12000:
        set_octets_per_data_packet(s, 12000);
        s->next_tx_indicator = (short_train)  ?  T38_IND_V17_12000_SHORT_TRAINING  :  T38_IND_V17_12000_LONG_TRAINING;
        s->current_tx_data_type = T38_DATA_V17_12000;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_V17_14400:
        set_octets_per_data_packet(s, 14400);
        s->next_tx_indicator = (short_train)  ?  T38_IND_V17_14400_SHORT_TRAINING  :  T38_IND_V17_14400_LONG_TRAINING;
        s->current_tx_data_type = T38_DATA_V17_14400;
        s->next_tx_samples = s->samples + ms_to_samples(s->ms_per_tx_chunk);
        s->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
        break;
    case T30_MODEM_DONE:
        span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
        s->timed_step = T38_TIMED_STEP_NONE;
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    }
    s->current_tx_type = type;
}
예제 #15
0
int t38_terminal_send_timeout(t38_terminal_state_t *s, int samples)
{
    int len;
    int i;
    int previous;
    uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50];
    /* Training times for all the modem options, with and without TEP */
    static const int training_time[] =
    {
           0,      0,   /* T38_IND_NO_SIGNAL */
           0,      0,   /* T38_IND_CNG */
           0,      0,   /* T38_IND_CED */
        1000,   1000,   /* T38_IND_V21_PREAMBLE */ /* TODO: 850 should be OK for this, but it causes trouble with some ATAs. Why? */
         943,   1158,   /* T38_IND_V27TER_2400_TRAINING */
         708,    923,   /* T38_IND_V27TER_4800_TRAINING */
         234,    454,   /* T38_IND_V29_7200_TRAINING */
         234,    454,   /* T38_IND_V29_9600_TRAINING */
         142,    367,   /* T38_IND_V17_7200_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_7200_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_9600_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_9600_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_12000_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_12000_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_14400_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_14400_LONG_TRAINING */
           0,      0,   /* T38_IND_V8_ANSAM */
           0,      0,   /* T38_IND_V8_SIGNAL */
           0,      0,   /* T38_IND_V34_CNTL_CHANNEL_1200 */
           0,      0,   /* T38_IND_V34_PRI_CHANNEL */
           0,      0,   /* T38_IND_V34_CC_RETRAIN */
           0,      0,   /* T38_IND_V33_12000_TRAINING */
           0,      0    /* T38_IND_V33_14400_TRAINING */
    };

    if (s->current_rx_type == T30_MODEM_DONE  ||  s->current_tx_type == T30_MODEM_DONE)
        return TRUE;

    s->samples += samples;
    t30_timer_update(&s->t30_state, samples);
    if (s->timeout_rx_samples  &&  s->samples > s->timeout_rx_samples)
    {
        span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n");
        s->timeout_rx_samples = 0;
        t30_receive_complete(&(s->t30_state));
    }
    if (s->timed_step == T38_TIMED_STEP_NONE)
        return FALSE;
    if (s->samples < s->next_tx_samples)
        return FALSE;
    /* Its time to send something */
    switch (s->timed_step)
    {
    case T38_TIMED_STEP_NON_ECM_MODEM:
        /* Create a 75ms silence */
        if (s->t38.current_tx_indicator != T38_IND_NO_SIGNAL)
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2;
        s->next_tx_samples += ms_to_samples(75);
        break;
    case T38_TIMED_STEP_NON_ECM_MODEM_2:
        /* Switch on a fast modem, and give the training time to complete */
        t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count);
        s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
        s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]);
        break;
    case T38_TIMED_STEP_NON_ECM_MODEM_3:
        /* Send a chunk of non-ECM image data */
        /* T.38 says it is OK to send the last of the non-ECM data in the signal end message.
           However, I think the early versions of T.38 said the signal end message should not
           contain data. Hopefully, following the current spec will not cause compatibility
           issues. */
        len = t30_non_ecm_get_chunk(&s->t30_state, buf, s->octets_per_data_packet);
        bit_reverse(buf, buf, len);
        if (len >= s->octets_per_data_packet)
        {
            s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
            t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, DATA_TX_COUNT);
        }
        else
        {
            t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, s->data_end_tx_count);
            /* This should not be needed, since the message above indicates the end of the signal, but it
               seems like it can improve compatibility with quirky implementations. */
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
            s->timed_step = T38_TIMED_STEP_NONE;
            t30_send_complete(&(s->t30_state));
        }
        break;
    case T38_TIMED_STEP_HDLC_MODEM:
        /* Send HDLC preambling */
        t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count);
        s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]);
        s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
        break;
    case T38_TIMED_STEP_HDLC_MODEM_2:
        /* Send a chunk of HDLC data */
        i = s->octets_per_data_packet;
        if (i >= (s->tx_len - s->tx_ptr))
        {
            i = s->tx_len - s->tx_ptr;
            s->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
        }
        t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, &s->tx_buf[s->tx_ptr], i, DATA_TX_COUNT);
        s->tx_ptr += i;
        s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
        break;
    case T38_TIMED_STEP_HDLC_MODEM_3:
        /* End of HDLC frame */
        previous = s->current_tx_data_type;
        s->tx_ptr = 0;
        s->tx_len = 0;
        t30_send_complete(&s->t30_state);
        if (s->tx_len < 0)
        {
            t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, s->data_end_tx_count);
            /* We have already sent T38_FIELD_HDLC_FCS_OK_SIG_END. It seems some boxes may not like
               us sending a T38_FIELD_HDLC_SIG_END at this point. Just say there is no signal. */
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
            s->tx_len = 0;
            t30_send_complete(&s->t30_state);
            if (s->tx_len)
                s->timed_step = T38_TIMED_STEP_HDLC_MODEM;
        }
        else
        {
            t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, DATA_TX_COUNT);
            if (s->tx_len)
                s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
        }
        s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
        break;
    case T38_TIMED_STEP_CED:
        /* It seems common practice to start with a no signal indicator, though
           this is not a specified requirement. Since we should be sending 200ms
           of silence, starting the delay with a no signal indication makes sense.
           We do need a 200ms delay, as that is a specification requirement. */
        s->timed_step = T38_TIMED_STEP_CED_2;
        s->next_tx_samples = s->samples + ms_to_samples(200);
        t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CED_2:
        /* Initial 200ms delay over. Send the CED indicator */
        s->next_tx_samples = s->samples + ms_to_samples(3000);
        s->timed_step = T38_TIMED_STEP_PAUSE;
        t38_core_send_indicator(&s->t38, T38_IND_CED, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CNG:
        /* It seems common practice to start with a no signal indicator, though
           this is not a specified requirement. Since we should be sending 200ms
           of silence, starting the delay with a no signal indication makes sense.
           We do need a 200ms delay, as that is a specification requirement. */
        s->timed_step = T38_TIMED_STEP_CNG_2;
        s->next_tx_samples = s->samples + ms_to_samples(200);
        t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CNG_2:
        /* Initial short delay over. Send the CNG indicator */
        s->timed_step = T38_TIMED_STEP_NONE;
        t38_core_send_indicator(&s->t38, T38_IND_CNG, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_PAUSE:
        /* End of timed pause */
        s->timed_step = T38_TIMED_STEP_NONE;
        t30_send_complete(&s->t30_state);
        break;
    }
    return FALSE;
}
예제 #16
0
SPAN_DECLARE(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s,
                                         int16_t amp[],
                                         int len)
{
    int16_t mod;
    int i;
    int xlen;

    i = 0;
    switch (s->tone_type)
    {
    case MODEM_CONNECT_TONES_FAX_CNG:
        for (  ;  i < len;  i++)
        {
            if (s->duration_timer > ms_to_samples(3000))
            {
                if ((xlen = i + s->duration_timer - ms_to_samples(3000)) > len)
                    xlen = len;
                s->duration_timer -= (xlen - i);
                for (  ;  i < xlen;  i++)
                    amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0);
            }
            if (s->duration_timer > 0)
            {
                if ((xlen = i + s->duration_timer) > len)
                    xlen = len;
                s->duration_timer -= (xlen - i);
                memset(amp + i, 0, sizeof(int16_t)*(xlen - i));
                i = xlen;
            }
            if (s->duration_timer == 0)
                s->duration_timer = ms_to_samples(500 + 3000);
        }
        break;
    case MODEM_CONNECT_TONES_ANS:
        if (s->duration_timer < len)
            len = s->duration_timer;
        if (s->duration_timer > ms_to_samples(2600))
        {
            /* There is some initial silence to be generated. */
            if ((i = s->duration_timer - ms_to_samples(2600)) > len)
                i = len;
            memset(amp, 0, sizeof(int16_t)*i);
        }
        for (  ;  i < len;  i++)
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0);
        s->duration_timer -= len;
        break;
    case MODEM_CONNECT_TONES_ANS_PR:
        if (s->duration_timer < len)
            len = s->duration_timer;
        if (s->duration_timer > ms_to_samples(3300))
        {
            if ((i = s->duration_timer - ms_to_samples(3300)) > len)
                i = len;
            memset(amp, 0, sizeof(int16_t)*i);
        }
        for (  ;  i < len;  i++)
        {
            if (--s->hop_timer <= 0)
            {
                s->hop_timer = ms_to_samples(450);
                s->tone_phase += 0x80000000;
            }
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0);
        }
        s->duration_timer -= len;
        break;
    case MODEM_CONNECT_TONES_ANSAM:
        if (s->duration_timer < len)
            len = s->duration_timer;
        if (s->duration_timer > ms_to_samples(3300))
        {
            if ((i = s->duration_timer - ms_to_samples(3300)) > len)
                i = len;
            memset(amp, 0, sizeof(int16_t)*i);
        }
        for (  ;  i < len;  i++)
        {
            mod = (int16_t) (s->level + dds_mod(&s->mod_phase, s->mod_phase_rate, s->mod_level, 0));
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, mod, 0);
        }
        s->duration_timer -= len;
        break;
    case MODEM_CONNECT_TONES_ANSAM_PR:
        if (s->duration_timer < len)
            len = s->duration_timer;
        if (s->duration_timer > ms_to_samples(3300))
        {
            if ((i = s->duration_timer - ms_to_samples(3300)) > len)
                i = len;
            memset(amp, 0, sizeof(int16_t)*i);
        }
        for (  ;  i < len;  i++)
        {
            if (--s->hop_timer <= 0)
            {
                s->hop_timer = ms_to_samples(450);
                s->tone_phase += 0x80000000;
            }
            mod = (int16_t) (s->level + dds_mod(&s->mod_phase, s->mod_phase_rate, s->mod_level, 0));
            amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, mod, 0);
        }
        s->duration_timer -= len;
        break;
    }
    return len;
}
예제 #17
0
SPAN_DECLARE(int) ademco_contactid_sender_rx(ademco_contactid_sender_state_t *s, const int16_t amp[], int samples)
{
#if defined(SPANDSP_USE_FIXED_POINT)
    int32_t energy_1400;
    int32_t energy_2300;
    int16_t xamp;
#else
    float energy_1400;
    float energy_2300;
    float xamp;
#endif
    int sample;
    int limit;
    int hit;
    int j;

    for (sample = 0;  sample < samples;  sample = limit)
    {
        if ((samples - sample) >= (GOERTZEL_SAMPLES_PER_BLOCK - s->current_sample))
            limit = sample + (GOERTZEL_SAMPLES_PER_BLOCK - s->current_sample);
        else
            limit = samples;
        for (j = sample;  j < limit;  j++)
        {
            xamp = amp[j];
            xamp = goertzel_preadjust_amp(xamp);
#if defined(SPANDSP_USE_FIXED_POINT)
            s->energy += ((int32_t) xamp*xamp);
#else
            s->energy += xamp*xamp;
#endif
            goertzel_samplex(&s->tone_1400, xamp);
            goertzel_samplex(&s->tone_2300, xamp);
        }
        s->current_sample += (limit - sample);
        if (s->current_sample < GOERTZEL_SAMPLES_PER_BLOCK)
            continue;

        energy_1400 = goertzel_result(&s->tone_1400);
        energy_2300 = goertzel_result(&s->tone_2300);
        hit = 0;
        if (energy_1400 > DETECTION_THRESHOLD  ||  energy_2300 > DETECTION_THRESHOLD)
        {
            if (energy_1400 > energy_2300)
            {
                if (energy_1400 > TONE_TO_TOTAL_ENERGY*s->energy)
                    hit = 1;
            }
            else
            {
                if (energy_2300 > TONE_TO_TOTAL_ENERGY*s->energy)
                    hit = 2;
            }
        }
        if (hit != s->in_tone  &&  hit == s->last_hit)
        {
            /* We have two successive indications that something has changed to a
               specific new state. */
            switch (s->tone_state)
            {
            case 0:
                if (hit == 1)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Receiving initial 1400Hz\n");
                    s->in_tone = hit;
                    s->tone_state = 1;
                    s->duration = 0;
                }
                break;
            case 1:
                /* We are looking for a burst of 1400Hz which is 100ms +- 5% long */
                if (hit == 0)
                {
                    if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad initial 1400Hz tone duration\n");
                        s->tone_state = 0;
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received 1400Hz tone\n");
                        s->tone_state = 2;
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 2:
                /* We are looking for 100ms +-5% of silence after the 1400Hz tone */
                if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Bad silence length\n");
                    s->tone_state = 0;
                    s->in_tone = hit;
                }
                else if (hit == 2)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Received silence\n");
                    s->tone_state = 3;
                    s->in_tone = hit;
                }
                else
                {
                    s->tone_state = 0;
                    s->in_tone = 0;
                }
                s->duration = 0;
                break;
            case 3:
                /* We are looking for a burst of 2300Hz which is 100ms +- 5% long */
                if (hit == 0)
                {
                    if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad initial 2300Hz tone duration\n");
                        s->tone_state = 0;
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received 2300Hz\n");
                        if (s->callback)
                            s->callback(s->callback_user_data, -1, 0, 0);
                        s->tone_state = 4;
                        /* Release the transmit side, and it will time the 250ms post tone delay */
                        s->clear_to_send = true;
                        s->tries = 0;
                        if (s->tx_digits_len)
                            s->timer = ms_to_samples(3000);
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 4:
                if (hit == 1)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Receiving kissoff\n");
                    s->tone_state = 5;
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 5:
                if (hit == 0)
                {
                    s->busy = false;
                    if (s->duration < ms_to_samples(400)  ||  s->duration > ms_to_samples(1500))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad kissoff duration %d\n", s->duration);
                        if (++s->tries < 4)
                        {
                            dtmf_tx_put(&s->dtmf, s->tx_digits, s->tx_digits_len);
                            s->timer = ms_to_samples(3000);
                            s->tone_state = 4;
                        }
                        else
                        {
                            s->timer = 0;
                            if (s->callback)
                                s->callback(s->callback_user_data, false, 0, 0);
                        }
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received good kissoff\n");
                        s->clear_to_send = true;
                        s->tx_digits_len = 0;
                        if (s->callback)
                            s->callback(s->callback_user_data, true, 0, 0);
                        s->tone_state = 4;
                        s->clear_to_send = true;
                        s->tries = 0;
                        if (s->tx_digits_len)
                            s->timer = ms_to_samples(3000);
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            }
        }
        s->last_hit = hit;
        s->duration += GOERTZEL_SAMPLES_PER_BLOCK;
        if (s->timer > 0)
        {
            s->timer -= GOERTZEL_SAMPLES_PER_BLOCK;
            if (s->timer <= 0)
            {
                span_log(&s->logging, SPAN_LOG_FLOW, "Timer expired\n");
                if (s->tone_state == 4  &&  s->tx_digits_len)
                {
                    if (++s->tries < 4)
                    {
                        dtmf_tx_put(&s->dtmf, s->tx_digits, s->tx_digits_len);
                        s->timer = ms_to_samples(3000);
                    }
                    else
                    {
                        s->timer = 0;
                        if (s->callback)
                            s->callback(s->callback_user_data, false, 0, 0);
                    }
                }
            }
        }
        s->energy = 0;
        s->current_sample = 0;
    }
    return 0;
}
예제 #18
0
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator)
{
    t38_terminal_state_t *s;
    
    s = (t38_terminal_state_t *) user_data;
    if (t->current_rx_indicator == indicator)
    {
        /* This is probably due to the far end repeating itself. Ignore it. Its harmless */
        return 0;
    }
    /* In termination mode we don't care very much about indicators telling us training
       is starting. We only care about the actual data. */
    switch (indicator)
    {
    case T38_IND_NO_SIGNAL:
        if (t->current_rx_indicator == T38_IND_V21_PREAMBLE
            &&
            (s->current_rx_type == T30_MODEM_V21  ||  s->current_rx_type == T30_MODEM_CNG))
        {
            t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN);
        }
        s->timeout_rx_samples = 0;
        break;
    case T38_IND_CNG:
        break;
    case T38_IND_CED:
        break;
    case T38_IND_V21_PREAMBLE:
        /* Some people pop these preamble indicators between HDLC frames, so we need to be tolerant of that. */
        if (s->current_rx_type == T30_MODEM_V21)
        {
            t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_UP);
            t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_FRAMING_OK);
        }
        break;
    case T38_IND_V27TER_2400_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V27TER_4800_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V29_7200_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V29_9600_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_7200_SHORT_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_7200_LONG_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_9600_SHORT_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_9600_LONG_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_12000_SHORT_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_12000_LONG_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_14400_SHORT_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V17_14400_LONG_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V8_ANSAM:
        break;
    case T38_IND_V8_SIGNAL:
        break;
    case T38_IND_V34_CNTL_CHANNEL_1200:
        break;
    case T38_IND_V34_PRI_CHANNEL:
        break;
    case T38_IND_V34_CC_RETRAIN:
        break;
    case T38_IND_V33_12000_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    case T38_IND_V33_14400_TRAINING:
        s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT);
        break;
    default:
        break;
    }
    s->rx_len = 0;
    s->missing_data = FALSE;
    return 0;
}