accurate timing requirements. Improved RTT. Added L8/L16 codecs.
# Create a "tags" file for easy Vim navigation
#
tags: src/net/6bed4.c
- ctags $(objs-top-kernel-y:.o=.c) $(objs-top-net-y:.o=.c) $(objs-top-phone-y:.o=.c) $(objs-bottom-y:.o=.c) include/0cpm/*.h include/config.h
+ # [ ! -f src/driver/tic55x/isrmap.c ] && touch src/driver/tic55x/isrmap.c
+ # ctags $(objs-top-kernel-y:.o=.c) $(objs-top-net-y:.o=.c) $(objs-top-phone-y:.o=.c) include/0cpm/*.h include/config.h $(objs-bottom-y:.o=.c)
+ # [ ! -s src/driver/tic55x/isrmap.c ] && rm src/driver/tic55x/isrmap.c
+ rm -f tags
+ for f in $(objs-top-kernel-y:.o=.c) $(objs-top-net-y:.o=.c) $(objs-top-phone-y:.o=.c) include/0cpm/*.h include/config.h $(objs-bottom-y:.o=.c); do if [ -s "$$f" ] ; then ctags --append=yes "$$f" ; fi ; done
#
# Create API documentation with doxygen
* RTT handling:
- consider replacing the call to rtt_recv_keys() with a textapp wakeup
+ - show RTT on the display
* Transcoding: Now supported in spandsp (for G.711) -- this can go.
+* T.38 fax support:
+ - exchange TIFF in fax-usable formats
+ - couple or drop logging
+ - link T.38 to the RTP stack
+ - link T.38 to the TFTP stack
+ - show on the interface what is going on
+ - figure out how much code is added for T.38 -- might be quite a lot
+
+
bottom_console_vprintf (fmt, argh);
va_end (argh);
}
-#endif
-
#endif /* CONFIG_FUNCTION_NETCONSOLE */
+
+#endif /* HEADER_CONSOLE */
#define NEED_KBD_SCANNER_DURING_KEYPRESS 1
-inline bool bottom_soundchannel_acceptable_samplerate (uint8_t chan, uint32_t samplerate) {
+static inline bool bottom_soundchannel_acceptable_samplerate (uint8_t chan, uint32_t samplerate) {
return (samplerate >= 1875) && (samplerate <= 52000);
}
-inline bool bottom_soundchannel_preferred_samplerate (uint8_t chan, uint32_t samplerate) {
+static inline bool bottom_soundchannel_preferred_samplerate (uint8_t chan, uint32_t samplerate) {
return bottom_acceptable_samplerate (chan, samplerate)
&& ( ( ( 30720000 / 16 ) % ( 1 * 2 * samplerate)) == 0);
}
#pragma CODE_SECTION(netinput, ".text_fast");
+/* Optimising included codecs: Speex, SpanDSP */
+#define CONFIG_TI_C55X 1
+
+
/* Following definitions are only available if BOTTOM is defined */
#ifdef BOTTOM
*/
+#ifndef HEADER_BOOL
+#define HEADER_BOOL
+
typedef enum {
false = 0,
true = 1
} bool;
+
+#endif
void l8_decode (struct codec *hdl, int16_t *pcm, uint16_t *pcmlen, uint8_t *pkt, uint16_t *pktlen) {
while ((*pktlen >= 1) && (*pcmlen >= 1)) {
- // Note: The 0xff masks away bits from 16-bit DSPs like tic55x
- *pcm++ = (((*pkt++) & 0xff) ^ 0x80) << 8;
- *pcmlen--;
- *pktlen--;
+ // Note: The 0x00ff masks away extra bits from 16-bit DSPs like tic55x
+ *pcm++ = ((((uint16_t) *pkt++) & 0x00ff) ^ 0x0080) << 8;
+ (*pcmlen) --;
+ (*pktlen) --;
}
}
void l8_encode (struct codec *hdl, int16_t *pcm, uint16_t *pcmlen, uint8_t *pkt, uint16_t *pktlen) {
while ((*pktlen >= 1) && (*pcmlen >= 1)) {
- // Note: The 0xff masks away bits from 16-bit DSPs like tic55x
+ // Note: The 0xff masks away extra bits from 16-bit DSPs like tic55x
*pkt++ = (((*pcm++) >> 8) ^ 0x80) & 0xff;
- *pcmlen--;
- *pktlen--;
+ (*pcmlen) --;
+ (*pktlen) --;
}
}
void l16_decode (struct codec *hdl, int16_t *pcm, uint16_t *pcmlen, uint8_t *pkt, uint16_t *pktlen) {
while ((*pktlen >= 2) && (*pcmlen >= 1)) {
- // Note: The 0xff masks away bits from 16-bit DSPs like tic55x
- *pcm++ = (int16_t) (((*pkt++) << 8) | ((*pkt++) & 0xff));
- *pcmlen--;
- *pktlen -= 2;
+ // Note: The 0xff masks away extra bits from 16-bit DSPs like tic55x
+ *pcm++ = (int16_t) ((((uint16_t) *pkt++) << 8) | ((*pkt++) & 0xff));
+ (*pcmlen) --;
+ (*pktlen) -= 2;
}
}
void l16_encode (struct codec *hdl, int16_t *pcm, uint16_t *pcmlen, uint8_t *pkt, uint16_t *pktlen) {
while ((*pktlen >= 2) && (*pcmlen >= 1)) {
- // Note: The 0xff masks away bits from 16-bit DSPs like tic55x
+ // Note: The 0xff masks away extra bits from 16-bit DSPs like tic55x
*pkt++ = ((*pcm) >> 8) & 0xff;
*pkt++ = (*pcm++) & 0xff;
- *pcmlen--;
- *pktlen -= 2;
+ (*pcmlen) --;
+ (*pktlen) -= 2;
}
}
TARGET=rtt_desktop_test
OBJS=recvkeys.o sendkeys.o desktop.o
-# CFLAGS=-m32 -L.
-CFLAGS=-m64
+# CFLAGS=-m32 -L. -DTODO_WAKEUP_TEXTSHOW_PROCESS
+CFLAGS=-m64 -DTODO_WAKEUP_TEXTSHOW_PROCESS
-# CFLAGS+=-ggdb3
+CFLAGS+=-ggdb3
all: tags $(TARGET)
tags:
ctags *.c
+
+rtp-setup-pipe:
+ mknod rtp-setup-pipe p
http://devel.0cpm.org/6bed4/
+Test with SIP using SIPP
+------------------------
+
+Some tests warrant a simple SIP client, for example compliance testing. This
+can be achieved using SIPP, a tool that can send and receive scripted SIP
+messages. Upon reception, it can also run commands.
+
+Use the uac.sipp or the uas-passive.sipp script. These will send the RTP
+coordinates to a named pipe (./rtp-setip-pipe) that is created automatically
+and then listened to by the ./user-display.sh script. As soon as an RTP
+setup is constructed by SIPP, it will send it to the pipe, and the script
+will start the RTT desktop test tool with the RTP parameters.
+
+The commands to run such tests are::
+
+ sipp -i [2001:db8:130::deaf] -sf uas-passive.sipp
+ sipp [2001:db8:130::deaf]:5060 -i [2001:db8:987::d00f] -sf uac.sipp -m 1
+
+It is even possible to run both client and server on the same host; there
+would also be two instances of ./user-display.sh running that each start
+one of the sides of the RTP session.
+
+This setup is really simple. It does not register or authenticate, it won't
+handle exceptions, it will not tear down the connection, it will not even
+stop the RTT user session when SIP signals BYE. Much more may be causing
+trouble. This is not an end user application, but just a demo to help with
+RTT codec compliancy tests.
+
+
Have fun!
Rick van Rein
bzero (&remot, sizeof (remot));
local.sin6_family = AF_INET6;
remot.sin6_family = AF_INET6;
+ if ((*argv [1] == '[') && argv [1] [strlen (argv [1])-1] == ']') {
+ argv [1] [strlen (argv [1])-1] = 0;
+ argv [1]++;
+ }
if (inet_pton (AF_INET6, argv [1], &local.sin6_addr) != 1) {
fprintf (stderr, "Failed to parse local IPv6 address\n");
exit (1);
}
+ if ((*argv [3] == '[') && argv [3] [strlen (argv [3])-1] == ']') {
+ argv [3] [strlen (argv [3])-1] = 0;
+ argv [3]++;
+ }
if (inet_pton (AF_INET6, argv [3], &remot.sin6_addr) != 1) {
fprintf (stderr, "Failed to parse remote IPv6 address\n");
exit (1);
void rtp_paytype_text_t140 (uint8_t *msg, uint16_t len) {
uint16_t newseq;
- //TODO:WAKEUP-TEXTSHOW-PROCESS// void rtt_recv_keys (uint8_t *text, uint16_t len);
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ void rtt_recv_keys (uint8_t *text, uint16_t len);
+#endif
rtt_skipheader (&msg, &len, &newseq, NULL);
switch ((int16_t) (newseq - rtt_seqnr)) {
case -2:
return;
default:
/* Packets out of sync, report missing text */
- //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+#endif
// ...continue into handling the one extension...
case 1:
/* Packets properly ordered */
- //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (msg, len);
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ rtt_recv_keys (msg, len);
+#endif
rtt_seqnr = newseq;
}
}
void rtp_paytype_text_red (uint8_t *msg, uint16_t len) {
uint16_t newseq;
uint16_t gencount, skipcount, skipbytes;
- //TODO:WAKEUP-TEXTSHOW-PROCESS// void rtt_recv_keys (uint8_t *text, uint16_t len);
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ void rtt_recv_keys (uint8_t *text, uint16_t len);
+#endif
rtt_skipheader (&msg, &len, &newseq, &gencount);
//
// Skip the redundant parts that were processed before
if (gencount < (newseq - rtt_seqnr)) {
/* Packets are missing -- report and use what is supplied */
- //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ rtt_recv_keys (rtt_missing_text, sizeof (rtt_missing_text));
+#endif
skipcount = 0;
} else {
/* No missing packets -- skip 0 or more redundant generations */
//
// Copy the redundant parts that are new
if (((int16_t) len) > 0) {
- //TODO:WAKEUP-TEXTSHOW-PROCESS// rtt_recv_keys (msg, len);
+#ifdef TODO_WAKEUP_TEXTSHOW_PROCESS
+ rtt_recv_keys (msg, len);
+#endif
}
}
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ uac.sipp
+
+ This is a scenario file for SIPP version 2.3. Invocation:
+
+ sipp [::1]:5060 -i [::1] -sf uac.sipp -m 1
+
+ Replace [::1]:5060 with the remote peer's SIP address/port.
+ Replace [::1] with any IPv6 address to use for SIP and RTP.
+
+ It sits and waits for incoming Realtime Text SIP calls,
+ and starts the test utility from the local directory
+ when one comes in. The call ends when the remote end
+ takes the initiative to do so.
+
+ This is hardly a functional phone, it is just an RTP
+ wrapper for test purposes.
+
+ This file is part of 0cpm Firmerware.
+
+ 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
+
+ 0cpm Firmerware is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, version 3.
+
+ 0cpm Firmerware is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<scenario name="Passive RTT UAS">
+
+<send>
+<![CDATA[
+
+ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+ Via: SIP/2.0/UDP [local_ip]:[local_port]
+ From: <sip:rtt@[local_ip]:[local_port]>;tag=[call_number]
+ To: <sip:[service]@[remote_ip]:[remote_port]>
+ Call-ID: [call_id]
+ CSeq: 1 INVITE
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Server: SIPP testing RTT
+ Max-Forwards: 70
+ Content-Type: application/sdp
+ Content-Length: [len]
+
+ v=0
+ o=user1 53655765 2353687637 IN IP6 [local_ip]
+ s=-
+ c=IN IP6 [local_ip]
+ t=0 0
+ m=text 12000 RTP/AVP 98 100
+ a=rtpmap:98 t140/1000
+ a=rtpmap:100 red/1000
+ a=fmtp:100 98/98/98
+
+]]>
+</send>
+
+<recv response="100" optional="true"/>
+
+<recv response="183" optional="true"/>
+
+<recv response="200">
+ <action>
+ <ereg regexp="c=IN IP6 ([^\r\n]+)" search_in="body" check_it="true" assign_to="whole,remote_media_ip"/>
+ <ereg regexp="m=text ([0-9]+)" search_in="body" check_it="true" assign_to="whole,remote_media_port"/>
+ <log message="RTT remote_media=[$remote_media_ip]:[$remote_media_port]"/>
+ <exec command="echo > ./rtp-setup-pipe [local_ip] 12000 [$remote_media_ip] [$remote_media_port]"/>
+ </action>
+</recv>
+
+<send>
+<![CDATA[
+
+ ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: <sip:rtt@[local_ip]:[local_port]>;tag=[call_number]
+ To: <sip:[service]@[remote_ip]:[remote_port]>;[peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 1 INVITE
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Server: SIPP testing RTT
+ Max-Forwards: 70
+
+]]>
+</send>
+
+<recv request="BYE"/>
+
+<send>
+<![CDATA[
+
+ SIP/2.0 200 OK
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: <sip:rtt@[local_ip]:[local_port]>;tag=[call_number]
+ To: <sip:[service]@[remote_ip]:[remote_port]>;[peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: [cseq] INVITE
+ Contact: <sip:[service]@[remote_ip]:[remote_port]>
+ Server: SIPP testing RTT
+ Max-Forwards: 70
+
+]]>
+</send>
+
+</scenario>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+ uas-passive.sipp
+
+ This is a scenario file for SIPP version 2.3. Invocation:
+
+ sipp -i [::1] -sf uas-passive.sipp
+
+ Replace ::1 with any IPv6 address to use for SIP and RTP.
+
+ It sits and waits for incoming Realtime Text SIP calls,
+ and starts the test utility from the local directory
+ when one comes in. The call ends when the remote end
+ takes the initiative to do so.
+
+ This is hardly a functional phone, it is just an RTP
+ wrapper for test purposes.
+
+ This file is part of 0cpm Firmerware.
+
+ 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
+
+ 0cpm Firmerware is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, version 3.
+
+ 0cpm Firmerware is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<scenario name="Passive RTT UAS">
+
+<recv request="INVITE">
+ <action>
+ <ereg regexp="c=IN IP6 ([^\r\n]+)" search_in="body" check_it="true" assign_to="whole,remote_media_ip"/>
+ <ereg regexp="m=text ([0-9]+)" search_in="body" check_it="true" assign_to="whole,remote_media_port"/>
+ <log message="RTT remote_media=[$remote_media_ip]:[$remote_media_port]"/>
+ <exec command="echo > ./rtp-setup-pipe [local_ip] 13000 [$remote_media_ip] [$remote_media_port]"/>
+ </action>
+</recv>
+
+<send>
+<![CDATA[
+
+ SIP/2.0 200 OK
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: <sip:[service]@[remote_ip]:[remote_port]>;[peer_tag_param]
+ To: <sip:rtt@[local_ip]:[local_port]>;tag=[call_number]
+ Call-ID: [call_id]
+ CSeq: [cseq] INVITE
+ Contact: <sip:TODO@[remote_ip]:[remote_port]>
+ Server: SIPP testing RTT
+ Max-Forwards: 70
+ Content-Type: application/sdp
+ Content-Length: [len]
+
+ v=0
+ o=user1 53655765 2353687637 IN IP6 [local_ip]
+ s=-
+ c=IN IP6 [local_ip]
+ t=0 0
+ m=text 13000 RTP/AVP 98 100
+ a=rtpmap:98 t140/1000
+ a=rtpmap:100 red/1000
+ a=fmtp:100 98/98/98
+
+]]>
+</send>
+
+<recv request="ACK"/>
+
+<recv request="BYE"/>
+
+<send>
+<![CDATA[
+
+ SIP/2.0 200 OK
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: <sip:[service]@[remote_ip]:[remote_port]>;[peer_tag_param]
+ To: <sip:rtt@[local_ip]:[local_port]>;tag=[call_number]
+ Call-ID: [call_id]
+ CSeq: [cseq] INVITE
+ Contact: <sip:TODO@[remote_ip]:[remote_port]>
+ Server: SIPP testing RTT
+ Max-Forwards: 70
+
+]]>
+</send>
+
+</scenario>
--- /dev/null
+#!/bin/sh
+#
+# user-display.sh
+#
+# This is the chatty portion of the Realtime Text test environment.
+# It creates a pipe named "rtp-setuppipe" and waits until RTP hints
+# are received. It the opens an RTT session for that data.
+#
+# This file is part of 0cpm Firmerware.
+#
+# 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
+#
+# 0cpm Firmerware is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, version 3.
+#
+# 0cpm Firmerware is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
+
+
+if [ ! -p ./rtp-setup-pipe ]
+then
+ echo >&2 'Creating ./rtp-setup-pipe'
+ rm -f ./rtp-setup-pipe
+ mknod ./rtp-setup-pipe p
+fi
+
+echo >&2 Waiting for RTP suggestion from SIPP scripts
+
+X=''
+while [ -z "$X" ]
+do
+ read < ./rtp-setup-pipe X
+done
+
+# X=`echo $X | sed 's/\[\([^ ]*\)\]/\1/g'`
+echo >&2 RTP local/remote coordinates: $X
+./rtt_desktop_test $X
+
void speex_transform_encode (struct codec *hdl,
uint16_t *pcm, uint16_t *pcmlen,
uint8_t *pkt, uint16_t *pktlen) {
- speex_encode (&hdl->state.state_speex_encode, NULL /*TODO*/);
+ speex_encode (&hdl->state.state_speex_encode, NULL /*TODO*/, NULL /*TODO*/);
}
void speex_init_decode (struct codec *hdl, uint32_t samplerate) {
speex_decoder_init (&hdl->state.state_speex_decode);
speex_decoder_destroy (&hdl->state.state_speex_decode);
}
void speex_transform_decode (struct codec *hdl, uint16_t *pktlen) {
- speex_decode (&hdl->state.state_speex_decode, NULL /*TODO*/);
+ speex_decode (&hdl->state.state_speex_decode, NULL /*TODO*/, NULL /*TODO*/);
}
#endif
/********** CODEC2 DEFINITIONS **********/
+#ifdef CONFIG_CODEC_CODEC2
static void codec2_init (struct codec *hdl, uint32_t samplerate) {
//TODO// Static allocation
codec2_create (&hdl->state.codec2_state);
*pktlen = (CODEC2_BITS_PER_FRAME + 7) >> 3;
}
-
-#ifdef CONFIG_CODEC_CODEC2
struct codec_fun encoder_codec2_1500 = {
"audio", "x-codec2", NULL,
"CODEC2",
// bottom_led_set (LED_IDX_SPEAKERPHONE, 1);
while (!(I2CSTR & REGVAL_I2CSTR_XRDY)) {
if (I2CSTR & REGVAL_I2CSTR_NACK) {
- bottom_printf ("I2C received NACK\n");
+ // bottom_printf ("I2C received NACK\n");
I2CSTR = REGVAL_I2CSTR_NACK;
I2CMDR = REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
return;
* recordable rec0 dma0
*
* DMA is possible if the dmaready area is non-empty, so if
- * dma0 != play0. When DMA has finished transferring a block,
+ * dma0 != play0. After DMA has transferred a block,
* the dma0 pointer is incremented, and this is checked.
*
* bottom_record_claim() succeeds if rec0 != dma0, and when
* it returns the rec0 offset of the playbuf, instead of the
* rec0 offset in the recbuf as is returned by record_claim.
*
- * bottom_play_claim() succeeds if play0 != rec0 *or* if there
- * is no actual recordable area, that is, rec0 == dma0. This
+ * bottom_play_claim() succeeds if play0 != rec0 *or* if the
+ * buffer is empty, which is noticed if DMA is not active. This
* means that playback is the first thing to start when a new
* set of index pointers is setup with zero values. When the
* bottom_play_release() is called, play0 increments, and the
* DMA conditions are evaluated.
*/
-static volatile uint16_t bufofs_play0 = 0;
-static volatile uint16_t bufofs_dma0 = 0;
-static volatile uint16_t bufofs_rec0 = 0;
+volatile bool dma_active = false;
+/*TODO:static*/ volatile uint16_t bufofs_play0 = 0;
+/*TODO:static*/ volatile uint16_t bufofs_dma0 = 0;
+/*TODO:static*/ volatile uint16_t bufofs_rec0 = 0;
inline void bottom_bufferdma_progress (uint8_t chan) {
bufofs_dma0 = (bufofs_dma0 + samplebuf_blocksize) % samplebuf_wrapindex;
if (bufofs_dma0 == bufofs_play0) {
SPCR2_1 &= ~REGVAL_SPCR2_FRST_NOTRESET; // Stop DMA
+ dma_active = false;
}
if (recordinghint) {
top_codec_can_record (chan);
}
int16_t *bottom_play_claim (uint8_t chan) {
- if ((bufofs_play0 != bufofs_rec0) || (bufofs_rec0 == bufofs_dma0)) {
+ if ((!dma_active) || (bufofs_play0 != bufofs_rec0)) {
return (int16_t *) &samplebuf_play [bufofs_play0];
} else {
return NULL;
DXR1_1 = DXR1_1; // Flag down XEMPTY
DMACCR_1 |= REGVAL_DMACCR_EN;
SPCR2_1 |= REGVAL_SPCR2_FRST_NOTRESET; // Start DMA
+ dma_active = true;
}
}
}
int16_t *bottom_echo_claim (uint8_t chan) {
- bool playbackhint = (bufofs_rec0 == bufofs_play0);
if (bufofs_rec0 != bufofs_dma0) {
return (int16_t *) &samplebuf_play [bufofs_rec0];
} else {
return NULL;
}
- if (playbackhint) {
- top_codec_can_play (chan);
- }
}
void bottom_record_release (uint8_t chan) {
+ bool playbackhint = (bufofs_rec0 == bufofs_play0);
bufofs_rec0 = (bufofs_rec0 + samplebuf_blocksize) % samplebuf_wrapindex;
+ if (playbackhint) {
+ top_codec_can_play (chan);
+ }
}
static int TODO_setratectr = 0;
//TODO// Not all this code is properly split between generic TLV and specific BT200
void tlv320aic2x_set_samplerate (uint8_t chan, uint32_t samplerate) {
uint16_t m, n, p;
-#if 0
SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
{ uint32_t ctr = 100; while (ctr-- > 0) ; }
SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
{ uint32_t ctr = 10000; while (ctr-- > 0) ; }
-#endif
DXR1_1 = DXR1_1; // Flag down XEMPTY
tlv320aic2x_setreg (chan, 3, 0x31); // Channel offline
{ uint32_t ctr = 1000; while (ctr-- > 0) ; }
n = 1;
p = 2;
m = ( 30720000 / 16 ) / ( n * p * samplerate );
- if (m & 0x03 == 0x00) {
+ if ((m & 0x03) == 0x00) {
// Save PLL energy without compromising accuracy
p = 8; // Factor 2 -> 8 so multiplied by 4
m >>= 2; // Divide by 4
n <<= 1;
}
{ uint8_t ip4 [4]; ip4 [0] = m; ip4 [1] = n; ip4 [2] = p; ip4 [3] = ++TODO_setratectr; bottom_show_ip4 (APP_LEVEL_CONNECTING, ip4); }
+#ifdef CONFIG_FUNCTION_NETCONSOLE
bottom_printf ("TLV320AIC20K setting: M=%d, N=%d, P=%d\n", (intptr_t) m, (intptr_t) n, (intptr_t) p);
+#endif
m &= 0x7f;
n &= 0x0f; // Ignore range problems?
p &= 0x07;
tlv320aic2x_set_samplerate (chan, samplerate);
//
// Setup buffer index pointers at the start; effectively clearing all
+ dma_active = false;
bufofs_play0 = 0;
bufofs_dma0 = 0;
bufofs_rec0 = 0;
if ((available_play >= 64) && ! (DMACCR_1 & REGVAL_DMACCR_EN)) {
DXR1_1 = DXR1_1; // Flag down XEMPTY
DMACCR_1 |= REGVAL_DMACCR_EN;
+#ifdef CONFIG_FUNCTION_NETCONSOLE
bottom_printf ("dmahint_play() started playing DMA\n");
+#endif
// #ifdef TODO_FS_ONLY_DURING_SOUND_IO
// SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET | REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
// #endif
tic55x_setup_timers ();
tic55x_setup_interrupts ();
ht162x_setup_lcd ();
- // tlv320aic2x_set_samplerate (0, 8000);
+ tlv320aic2x_set_samplerate (0, 8000);
tlv320aic2x_setup_sound ();
ksz8842_setup_network ();
// Enable INT0..INT3
// .text > ROM
.text > RAM
.text_quick > DARAM
- .switch > ROM
- .const > ROM
+ // .switch > ROM
+ .switch > CONSTRAM
+ // .const > ROM
+ .const > CONSTRAM
// .const > CONSTRAM
.const_codec2_codebook > CONSTRAM
- .cinit > ROM
+ // .cinit > ROM
+ .cinit > CONSTRAM
.interrupts > VECTOR
.isrmap > ISRMAP
.data > RAM
# Function for the target image
-menu "5. Firmerware functions"
+menu "4. Firmerware functions"
choice
prompt "Primary firmware function"
config FUNCTION_RADIO
bool "Internet radio (multicast reception)"
- depends on UNIMPLEMENTED
+ depends on UNIMPLEMENTED && !MAINFUNCTION_DEVEL_GPIO && !MAINFUNCTION_DEVEL_TIMER && !MAINFUNCTION_DEVEL_KEYBOARD && !MAINFUNCTION_DEVEL_NETWORK && !MAINFUNCTION_DEVEL_SOUND
default y
help
Enable Internet Radio functions. This makes the phone pickup
TODO: a polling TFTP client may in fact be better?
-source "src/codec/Kconfig"
-
endmenu
}
}
+bool online;
+
void top_network_online (void) {
- /* Keep the linker happy */ ;
+ online = true;
}
void top_network_offline (void) {
- /* Keep the linker happy */ ;
+ online = false;
}
void top_network_can_send (void) {
void top_main_sine_1khz (void) {
uint16_t oldirqs = 0;
-extern volatile uint16_t available_play;
-extern volatile uint16_t available_record;
-uint8_t l16ctr = 1;
bottom_critical_region_end ();
if (!bottom_soundchannel_acceptable_samplerate (PHONE_CHANNEL_TELEPHONY, 8000)) {
bottom_printf ("Failed to set sample rate");
bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_CALL_ENDED);
- exit (1);
+ while (1) {
+ ;
+ }
}
bottom_soundchannel_set_samplerate (PHONE_CHANNEL_TELEPHONY, 8000, 64, 1, 1);
bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY, 127);
bottom_printf ("Playing 1 kHz tone to speaker or handset\n");
top_hook_update (bottom_phone_is_offhook ());
while (true) {
-#if 0
-if (SPCR2_1 & REGVAL_SPCR2_XRDY) { DXR1_1 = sinewaveL16 [l16ctr++]; if (l16ctr == 8) { l16ctr = 0; } }
-{ uint16_t _ = DRR1_1; }
-#else
- do {
- int16_t *outbuf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY);
+ /* First play as many samples as possible */
+ int16_t *outbuf;
+ while ((outbuf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY))) {
uint16_t pcmlen, pktlen;
- if (!outbuf) {
- break;
- }
#if 1
pcmlen = 64;
pktlen = 64;
l16_decode (NULL, outbuf, &pcmlen, sinewaveL16, &pktlen);
#endif
bottom_play_release (PHONE_CHANNEL_TELEPHONY);
- } while (true);
-#endif
+ }
+ /* Now let the bottom think that recordings have been processed */
+ while (bottom_record_claim (PHONE_CHANNEL_TELEPHONY)) {
+ bottom_record_release (PHONE_CHANNEL_TELEPHONY);
+ }
+{extern volatile uint16_t bufofs_play0, bufofs_dma0, bufofs_rec0;
+bottom_printf ("p/d/r = %d, %d, %d\n", (intptr_t) bufofs_play0, (intptr_t) bufofs_dma0, (intptr_t) bufofs_rec0);
+}
#ifdef CONFIG_FUNCTION_NETCONSOLE
- // { uint32_t ctr = 10000; while (ctr--) ; }
- trysend ();
- // { uint32_t ctr = 10000; while (ctr--) ; }
bottom_led_set (LED_IDX_BACKLIGHT, 1);
- netinputlen = sizeof (netinput);
- if (bottom_network_recv (netinput, &netinputlen)) {
- nethandler_llconly (netinput, netinputlen);
-bottom_led_set (LED_IDX_BACKLIGHT, 0);
- { uint32_t ctr = 10000; while (ctr--) ; }
+ if (online) {
+ netinputlen = sizeof (netinput);
+ if (bottom_network_recv (netinput, &netinputlen)) {
+ nethandler_llconly (netinput, netinputlen);
+ { uint32_t ctr = 10000; while (ctr--) ; }
+ }
+ trysend ();
}
bottom_led_set (LED_IDX_BACKLIGHT, 0);
- trysend ();
#endif
#if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
pktlen = 100;
// Note: No handle needed for stateless L8
l8_decode (NULL, buf, &pcmlen, samples + recptr, &pktlen);
+ bottom_record_release (PHONE_CHANNEL_TELEPHONY);
recptr += 100;
if (recptr >= 10000) {
# 4. Intended functionality
source "src/function/Kconfig"
+# 5. Codec support
+source "src/codec/Kconfig"
+
source "src/net/Kconfig"
source "src/phone/Kconfig"
this software. And of course we will gladly integrate your
changes, so you don't have to keep your own code forked.
+ For the latest news on the support for these phones, visit
+ http://reverse.0cpm.org/grandstream/gxp.html
+
config TARGET_GRANDSTREAM_GXV
bool "Grandstream GXV series (video phones)"
select PLATFORM_TIC55X
* camera
* touch screen (on some models)
- Support for these models is not planned at this time.
+ For the latest news on the support for these phones, visit
+ http://reverse.0cpm.org/grandstream/gxv.html
endchoice