Various tweaks to spandsp, including starting to add some genuine ARM

optimisations.
This commit is contained in:
Steve Underwood 2012-12-12 03:23:27 +08:00
parent 8aba7238a8
commit 38bf6342fa
11 changed files with 232 additions and 93 deletions

View File

@ -183,9 +183,7 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
s->put_byte(s->user_data, s->byte_in_progress);
s->bitpos = 0;
}
else
{
if (s->use_v14)
else if (s->use_v14)
{
/* This is actually the start bit for the next character, and
the stop bit has been dropped from the stream. This is the
@ -205,7 +203,6 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
}
}
}
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,

View File

@ -128,6 +128,68 @@ static const char *at_response_codes[] =
"+FRH:3"
};
SPAN_DECLARE(const char *) at_call_state_to_str(int state)
{
switch (state)
{
case AT_CALL_EVENT_ALERTING:
return "Alerting";
case AT_CALL_EVENT_CONNECTED:
return "Connected";
case AT_CALL_EVENT_ANSWERED:
return "Answered";
case AT_CALL_EVENT_BUSY:
return "Busy";
case AT_CALL_EVENT_NO_DIALTONE:
return "No dialtone";
case AT_CALL_EVENT_NO_ANSWER:
return "No answer";
case AT_CALL_EVENT_HANGUP:
return "Hangup";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(const char *) at_modem_control_to_str(int state)
{
switch (state)
{
case AT_MODEM_CONTROL_CALL:
return "Call";
case AT_MODEM_CONTROL_ANSWER:
return "Answer";
case AT_MODEM_CONTROL_HANGUP:
return "Hangup";
case AT_MODEM_CONTROL_OFFHOOK:
return "Off hook";
case AT_MODEM_CONTROL_ONHOOK:
return "On hook";
case AT_MODEM_CONTROL_DTR:
return "DTR";
case AT_MODEM_CONTROL_RTS:
return "RTS";
case AT_MODEM_CONTROL_CTS:
return "CTS";
case AT_MODEM_CONTROL_CAR:
return "CAR";
case AT_MODEM_CONTROL_RNG:
return "RNG";
case AT_MODEM_CONTROL_DSR:
return "DSR";
case AT_MODEM_CONTROL_SETID:
return "Set ID";
case AT_MODEM_CONTROL_RESTART:
return "Restart";
case AT_MODEM_CONTROL_DTE_TIMEOUT:
return "DTE timeout";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) at_set_at_rx_mode(at_state_t *s, int new_mode)
{
/* The use of a DTE timeout is mode dependent. Set the timeout appropriately in
@ -363,8 +425,8 @@ SPAN_DECLARE(void) at_display_call_info(at_state_t *s)
snprintf(buf,
sizeof(buf),
"%s=%s",
call_id->id ? call_id->id : "NULL",
call_id->value ? call_id->value : "<NONE>");
(call_id->id) ? call_id->id : "NULL",
(call_id->value) ? call_id->value : "<NONE>");
at_put_response(s, buf);
call_id = call_id->next;
}

View File

@ -560,8 +560,7 @@ static void quantization_and_coding(int16_t LAR[8])
#undef STEP
#define STEP(A,B,MAC,MIC) \
temp = saturated_mul16(A, *LAR); \
temp = saturated_add16(temp, B); \
temp = saturated_add16(temp, 256); \
temp = saturated_add16(temp, (B + 256)); \
temp >>= 9; \
*LAR = (int16_t) ((temp > MAC) \
? \

View File

@ -201,10 +201,9 @@ static int image_gray8_to_colour16_row(uint16_t colour16[], uint8_t gray8[], int
for (i = pixels - 1; i >= 0; i--)
{
/* TODO: need to balance the colours */
colour16[3*i] = gray8[i] << 8;
colour16[3*i + 1] = gray8[i] << 8;
colour16[3*i + 2] = gray8[i] << 8;
colour16[3*i] = saturateu16((gray8[i]*36532U) >> 7);
colour16[3*i + 1] = saturateu16((gray8[i]*37216U) >> 8);
colour16[3*i + 2] = saturateu16((gray8[i]*47900U) >> 6);
}
return pixels;
}
@ -216,10 +215,9 @@ static int image_gray8_to_colour8_row(uint8_t colour8[], uint8_t gray8[], int pi
for (i = pixels - 1; i >= 0; i--)
{
/* TODO: need to balance the colours */
colour8[3*i] = gray8[i];
colour8[3*i + 1] = gray8[i];
colour8[3*i + 2] = gray8[i];
colour8[3*i] = saturateu8((gray8[i]*36532U) >> 15);
colour8[3*i + 1] = saturateu8((gray8[i]*37216U) >> 16);
colour8[3*i + 2] = saturateu8((gray8[i]*47900U) >> 14);
}
return pixels;
}

View File

@ -433,7 +433,7 @@ void lpc10_voicing(lpc10_encode_state_t *s,
s->voibuf[1][1] = 1;
break;
case 11:
if (s->voice[1][9] < -s->voice[0][1])
if (s->voice[1][0] < -s->voice[0][1])
s->voibuf[2][0] = 0;
else
s->voibuf[1][1] = 1;

View File

@ -486,7 +486,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
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));
report_tone_state(s, MODEM_CONNECT_TONES_FAX_CNG, lfastrintf(((s->channel_level == 0) ? (-96.329f + DBM0_MAX_POWER) : log10f(s->channel_level/32768.0f)*20.0f) + DBM0_MAX_POWER + 0.8f));
}
}
else
@ -565,7 +565,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
{
report_tone_state(s,
(s->am_level*15/256 > s->channel_level) ? MODEM_CONNECT_TONES_ANSAM_PR : MODEM_CONNECT_TONES_ANS_PR,
lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
lfastrintf(((s->channel_level == 0) ? (-96.329f + DBM0_MAX_POWER) : log10f(s->channel_level/32768.0f)*20.0f) + DBM0_MAX_POWER + 0.8f));
}
}
else
@ -583,7 +583,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
{
report_tone_state(s,
(s->am_level*15/256 > s->channel_level) ? MODEM_CONNECT_TONES_ANSAM : MODEM_CONNECT_TONES_ANS,
lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
lfastrintf(((s->channel_level == 0) ? (-96.329f + DBM0_MAX_POWER) : log10f(s->channel_level/32768.0f)*20.0f) + DBM0_MAX_POWER + 0.8f));
}
s->good_cycles = 0;
s->tone_cycle_duration = ms_to_samples(450 + 100);
@ -637,7 +637,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
if (s->tone_present != MODEM_CONNECT_TONES_BELL_ANS)
{
if (++s->tone_cycle_duration >= ms_to_samples(415))
report_tone_state(s, MODEM_CONNECT_TONES_BELL_ANS, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
report_tone_state(s, MODEM_CONNECT_TONES_BELL_ANS, lfastrintf(((s->channel_level == 0) ? (-96.329f + DBM0_MAX_POWER) : log10f(s->channel_level/32768.0f)*20.0f) + DBM0_MAX_POWER + 0.8f));
}
}
else
@ -675,7 +675,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
if (s->tone_present != MODEM_CONNECT_TONES_CALLING_TONE)
{
if (++s->tone_cycle_duration >= ms_to_samples(415))
report_tone_state(s, MODEM_CONNECT_TONES_CALLING_TONE, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
report_tone_state(s, MODEM_CONNECT_TONES_CALLING_TONE, lfastrintf(((s->channel_level == 0) ? (-96.329f + DBM0_MAX_POWER) : log10f(s->channel_level/32768.0f)*20.0f) + DBM0_MAX_POWER + 0.8f));
}
}
else

View File

@ -136,6 +136,10 @@ extern "C"
{
#endif
SPAN_DECLARE(const char *) at_call_state_to_str(int state);
SPAN_DECLARE(const char *) at_modem_control_to_str(int state);
SPAN_DECLARE(void) at_set_at_rx_mode(at_state_t *s, int new_mode);
SPAN_DECLARE(void) at_put_response(at_state_t *s, const char *t);

View File

@ -45,68 +45,123 @@ extern "C"
/* This is the same as saturate16(), but is here for historic reasons */
static __inline__ int16_t saturate(int32_t amp)
{
int16_t amp16;
#if defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int16_t z;
__asm__ __volatile__(
" ssat %[z],#16,%[amp];\n"
: [z] "=r" (z)
: [amp] "r" (amp)
);
return z;
#else
int16_t z;
/* Hopefully this is optimised for the common case - not clipping */
amp16 = (int16_t) amp;
if (amp == amp16)
return amp16;
z = (int16_t) amp;
if (amp == z)
return z;
if (amp > INT16_MAX)
return INT16_MAX;
return INT16_MIN;
#endif
}
/*- End of function --------------------------------------------------------*/
static __inline__ int16_t saturate16(int32_t amp)
{
int16_t amp16;
#if defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int16_t z;
__asm__ __volatile__(
" ssat %[z],#16,%[amp];\n"
: [z] "=r" (z)
: [amp] "r" (amp)
);
return z;
#else
int16_t z;
/* Hopefully this is optimised for the common case - not clipping */
amp16 = (int16_t) amp;
if (amp == amp16)
return amp16;
z = (int16_t) amp;
if (amp == z)
return z;
if (amp > INT16_MAX)
return INT16_MAX;
return INT16_MIN;
#endif
}
/*- End of function --------------------------------------------------------*/
/*! Saturate to 15 bits, rather than the usual 16 bits. This is often a useful function. */
static __inline__ int16_t saturate15(int32_t amp)
{
#if defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int16_t z;
__asm__ __volatile__(
" ssat %[z],#15,%[amp];\n"
: [z] "=r" (z)
: [amp] "r" (amp)
);
return z;
#else
if (amp > 16383)
return 16383;
if (amp < -16384)
return -16384;
return (int16_t) amp;
#endif
}
/*- End of function --------------------------------------------------------*/
static __inline__ uint16_t saturateu16(int32_t amp)
{
uint16_t amp16;
#if defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
uint16_t z;
__asm__ __volatile__(
" usat %[z],#16,%[amp];\n"
: [z] "=r" (z)
: [amp] "r" (amp)
);
return z;
#else
uint16_t z;
/* Hopefully this is optimised for the common case - not clipping */
amp16 = (uint16_t) amp;
if (amp == amp16)
return amp16;
z = (uint16_t) amp;
if (amp == z)
return z;
if (amp > UINT16_MAX)
return UINT16_MAX;
return 0;
#endif
}
/*- End of function --------------------------------------------------------*/
static __inline__ uint8_t saturateu8(int32_t amp)
{
uint8_t amp8;
#if defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
uint8_t z;
__asm__ __volatile__(
" usat %[z],#8,%[amp];\n"
: [z] "=r" (z)
: [amp] "r" (amp)
);
return z;
#else
uint8_t z;
/* Hopefully this is optimised for the common case - not clipping */
amp8 = (uint8_t) amp;
if (amp == amp8)
return amp8;
z = (uint8_t) amp;
if (amp == z)
return z;
if (amp > UINT8_MAX)
return UINT8_MAX;
return 0;
#endif
}
/*- End of function --------------------------------------------------------*/
@ -188,15 +243,15 @@ static __inline__ int16_t saturated_add16(int16_t a, int16_t b)
: "cc"
);
return a;
#elif defined(__GNUC__) && defined(__arm5__)
int16_t result;
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int16_t z;
__asm__ __volatile__(
" sadd16 %0,%1,%2;\n"
: "=r" (result)
: "0" (a), "ir" (b)
" qsub16 %[z],%[a],%[b];\n"
: [z] "=r" (z)
: [a] "r" (a), [b] "r" (b)
);
return result;
return z;
#else
return saturate((int32_t) a + (int32_t) b);
#endif
@ -217,25 +272,25 @@ static __inline__ int32_t saturated_add32(int32_t a, int32_t b)
: "cc"
);
return a;
#elif defined(__GNUC__) && defined(__arm5__)
int32_t result;
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int32_t z;
__asm__ __volatile__(
" qadd %0,%1,%2;\n"
: "=r" (result)
: "0" (a), "ir" (b)
" qadd %[z],%[a],%[b];\n"
: [z] "=r" (z)
: [a] "r" (a), [b] "r" (b)
);
return result;
return z;
#else
int32_t sum;
int32_t z;
sum = a + b;
z = a + b;
if ((a ^ b) >= 0)
{
if ((sum ^ a) < 0)
sum = (a < 0) ? INT32_MIN : INT32_MAX;
if ((z ^ a) < 0)
z = (a < 0) ? INT32_MIN : INT32_MAX;
}
return sum;
return z;
#endif
}
/*- End of function --------------------------------------------------------*/
@ -254,15 +309,15 @@ static __inline__ int16_t saturated_sub16(int16_t a, int16_t b)
: "cc"
);
return a;
#elif defined(__GNUC__) && defined(__arm5__)
int16_t result;
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int16_t z;
__asm__ __volatile__(
" ssub16 %0,%1,%2;\n"
: "=r" (result)
: "0" (a), "ir" (b)
" qsub16 %[z],%[a],%[b];\n"
: [z] "=r" (z)
: [a] "r" (a), [b] "r" (b)
);
return result;
return z;
#else
return saturate((int32_t) a - (int32_t) b);
#endif
@ -283,25 +338,25 @@ static __inline__ int32_t saturated_sub32(int32_t a, int32_t b)
: "cc"
);
return a;
#elif defined(__GNUC__) && defined(__arm5__)
int32_t result;
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int32_t z;
__asm__ __volatile__(
" qsub %0,%1,%2;\n"
: "=r" (result)
: "0" (a), "ir" (b)
" qsub %[z],%[a],%[b];\n"
: [z] "=r" (z)
: [a] "r" (a), [b] "r" (b)
);
return result;
return z;
#else
int32_t diff;
int32_t z;
diff = a - b;
z = a - b;
if ((a ^ b) < 0)
{
if ((diff ^ a) & INT32_MIN)
diff = (a < 0L) ? INT32_MIN : INT32_MAX;
if ((z ^ a) & INT32_MIN)
z = (a < 0L) ? INT32_MIN : INT32_MAX;
}
return diff;
return z;
#endif
}
/*- End of function --------------------------------------------------------*/

View File

@ -240,6 +240,7 @@ SPAN_DECLARE(const char *) t30_completion_code_to_str(int result)
case T30_ERR_CSA_UNACCEPTABLE:
return "Called subscriber internet address not accepted";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
@ -411,6 +412,7 @@ SPAN_DECLARE(const char *) t30_frametype(uint8_t x)
case T4_RCP:
return "RCP";
}
/*endswitch*/
return "???";
}
/*- End of function --------------------------------------------------------*/
@ -436,6 +438,7 @@ static void octet_reserved_bit(logging_state_t *log,
s[7 - bit_no + ((bit_no < 4) ? 1 : 0)] = (uint8_t) (bit + '0');
span_log(log, SPAN_LOG_FLOW, " %s= Unexpected state for reserved bit: %d\n", s, bit);
}
/*endif*/
}
/*- End of function --------------------------------------------------------*/

View File

@ -155,7 +155,9 @@ enum
{
T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001,
T38_CHUNKING_WHOLE_FRAMES = 0x0002,
T38_CHUNKING_ALLOW_TEP_TIME = 0x0004
T38_CHUNKING_ALLOW_TEP_TIME = 0x0004,
T38_CHUNKING_SEND_REGULAR_INDICATORS = 0x0008,
T38_CHUNKING_SEND_2S_REGULAR_INDICATORS = 0x0010
};
enum
@ -181,7 +183,8 @@ enum
T38_TIMED_STEP_CED_3 = 0x42,
T38_TIMED_STEP_CNG = 0x50,
T38_TIMED_STEP_CNG_2 = 0x51,
T38_TIMED_STEP_PAUSE = 0x60
T38_TIMED_STEP_PAUSE = 0x60,
T38_TIMED_STEP_NO_SIGNAL = 0x70
};
static int restart_modem(t31_state_t *s, int new_modem);

View File

@ -230,6 +230,7 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
/* Protect against T.38 stuff arriving after we've actually finished. */
if (fe->current_rx_type == T30_MODEM_DONE)
return 0;
/*endif*/
if (t->current_rx_indicator == indicator)
{
@ -333,6 +334,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
/* Protect against T.38 stuff arriving after we've actually finished. */
if (fe->current_rx_type == T30_MODEM_DONE)
return 0;
/*endif*/
/* In termination mode we don't care very much what the data type is apart from a couple of
special cases. */
@ -608,6 +610,7 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
{
if (s->t38_fe.us_per_tx_chunk)
s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len);
/*endif*/
bit_reverse(s->t38_fe.hdlc_tx.buf, msg, len);
s->t38_fe.hdlc_tx.len = len;
s->t38_fe.hdlc_tx.ptr = 0;
@ -774,6 +777,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
break;
}
/*endif*/
@ -805,6 +809,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
/*endif*/
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
break;
}
/*endif*/
@ -825,6 +830,10 @@ static int stream_non_ecm(t38_terminal_state_t *s)
fe->timed_step = fe->queued_timed_step;
fe->queued_timed_step = T38_TIMED_STEP_NONE;
}
else
{
fe->timed_step = T38_TIMED_STEP_NONE;
}
/*endif*/
return delay;
}
@ -910,6 +919,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
fe->hdlc_tx.len = 0;
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
/* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
if (fe->hdlc_tx.len >= 0)
{
@ -941,6 +951,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
/*endif*/
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
}
/*endif*/
break;
@ -971,6 +982,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
fe->hdlc_tx.len = 0;
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
/* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
if (fe->hdlc_tx.len >= 0)
{
@ -1006,6 +1018,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
/*endif*/
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
}
/*endif*/
break;
@ -1018,6 +1031,10 @@ static int stream_hdlc(t38_terminal_state_t *s)
fe->timed_step = fe->queued_timed_step;
fe->queued_timed_step = T38_TIMED_STEP_NONE;
}
else
{
fe->timed_step = T38_TIMED_STEP_NONE;
}
/*endif*/
return delay;
}
@ -1063,6 +1080,7 @@ static int stream_ced(t38_terminal_state_t *s)
fe->timed_step = fe->queued_timed_step;
if (front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE) < 0)
return -1;
/*endif*/
return 0;
}
/*endswitch*/