Sound is now reliably playing back samples on TLV320AIC20K.
[firmerware] / src / function / develtest / echo.c
1 /* echo.c -- Sound I/O test program
2  *
3  * This file is part of 0cpm Firmerware.
4  *
5  * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
6  *
7  * 0cpm Firmerware is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation, version 3.
10  *
11  * 0cpm Firmerware is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 /* This program will retrieve sound from the codec (sound chip), hold it for a bit,
22  * and send it back out.  When the phone is on-hook, sound communicates over the
23  * speakerphone function (if present).  When the phone is off-hook, sound
24  * communicates over the handset.
25  *
26  * From: Rick van Rein <rick@openfortress.nl>
27  */
28
29
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <stdarg.h>
33 #include <stdbool.h>
34
35 //TODO// test inclusion of bottom and text definitions
36 #define BOTTOM
37 #include <config.h>
38 #include <0cpm/text.h>
39
40 #include <0cpm/kbd.h>
41 #include <0cpm/app.h>
42 #include <0cpm/cons.h>
43 #include <0cpm/show.h>
44 #include <0cpm/snd.h>
45 #include <0cpm/led.h>
46
47
48 volatile uint16_t tobeplayed   = 0;
49 volatile uint16_t toberecorded = 0;
50
51
52 timing_t top_timer_expiration (timing_t timeout) {
53         /* Keep the linker happy */ ;
54         return timeout;
55 }
56
57 void top_hook_update (bool offhook) {
58         if (offhook) {
59                 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_HANDSET);
60         } else {
61                 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_SPEAKER);
62         }
63 }
64
65 bool online;
66
67 void top_network_online (void) {
68         online = true;
69 }
70
71 void top_network_offline (void) {
72         online = false;
73 }
74
75 void top_network_can_send (void) {
76         /* Keep the linker happy */ ;
77 }
78
79 void top_network_can_recv (void) {
80         /* Keep the linker happy */ ;
81 }
82
83 void top_button_press (buttonclass_t bcl, buttoncode_t cde) {
84         if (bcl != BUTCLS_FIXED_FUNCTION) {
85                 return;
86         }
87         switch (cde) {
88 #ifdef HAVE_BUTTON_UP
89         case HAVE_BUTTON_UP:
90                 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY,
91                         bottom_soundchannel_getvolume (PHONE_CHANNEL_TELEPHONY) + 1);
92                 break;
93 #endif
94 #ifdef HAVE_BUTTON_DOWN
95         case HAVE_BUTTON_DOWN:
96                 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY,
97                         bottom_soundchannel_getvolume (PHONE_CHANNEL_TELEPHONY) - 1);
98                 break;
99 #endif
100         default:
101                 break;
102         }
103 }
104
105 void top_button_release (void) {
106         /* Keep the linker happy */
107 }
108
109 uint16_t plyirqs = 0;
110 void top_codec_can_play (uint8_t chan) {
111         plyirqs++;
112 }
113
114 uint16_t recirqs = 0;
115 void top_codec_can_record (uint8_t chan) {
116         recirqs++;
117 }
118
119
120 #define top_main_sine_1khz  top_main
121 // #define top_main_delay_1sec top_main
122
123
124 #ifdef CONFIG_FUNCTION_NETCONSOLE
125 uint8_t netinput [1000];
126 uint16_t netinputlen;
127 void nethandler_llconly (uint8_t *pkt, uint16_t pktlen);
128 #endif
129
130
131 /******** TOP_MAIN FOR A 1 KHZ SINE WAVE OUTPUT ********/
132
133 uint8_t sinewaveL8 [64] = {
134         // 8-bit samples with 0x80 offset
135         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
136         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
137         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
138         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
139         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
140         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
141         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25,
142         0x80, 0xda, 0xff, 0xda, 0x80, 0x25, 0x00, 0x25
143 };
144
145 int8_t sinewaveL16 [128] = {
146         // 16-bit signed values, encoded as byte pairs H,L
147         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
148         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
149         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
150         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
151         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
152         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
153         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191,
154         0,0, 45,65, 63,255, 45,65, 0,0, 210,191, 192,1, 210,191
155 };
156
157 void top_main_sine_1khz (void) {
158         uint16_t oldirqs = 0;
159         bottom_critical_region_end ();
160         if (!bottom_soundchannel_acceptable_samplerate (PHONE_CHANNEL_TELEPHONY, 8000)) {
161                 bottom_printf ("Failed to set sample rate");
162                 bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_CALL_ENDED);
163                 while (true) {
164                         ;
165                 }
166         }
167         bottom_soundchannel_set_samplerate (PHONE_CHANNEL_TELEPHONY, 8000, 64, 1, 1);
168         bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY, 127);
169         bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_RINGING);
170         bottom_printf ("Playing 1 kHz tone to speaker or handset\n");
171         top_hook_update (bottom_phone_is_offhook ());
172         while (true) {
173                 /* First play as many samples as possible */
174                 int16_t *outbuf;
175                 while ((outbuf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY))) {
176                         uint16_t pcmlen, pktlen;
177 #if 0
178                         pcmlen = 64;
179                         pktlen = 64;
180                         // Note: No handle needed for stateless L8
181                         l8_decode (NULL, outbuf, &pcmlen, sinewaveL8, &pktlen);
182 #else
183                         pcmlen = 64;
184                         pktlen = 128;
185                         // Note: No handle needed for stateless L16
186                         l16_decode (NULL, outbuf, &pcmlen, sinewaveL16, &pktlen);
187 #endif
188                         bottom_play_release (PHONE_CHANNEL_TELEPHONY);
189                 }
190                 /* Now let the bottom think that recordings have been processed */
191                 while (bottom_record_claim (PHONE_CHANNEL_TELEPHONY)) {
192                         bottom_record_release (PHONE_CHANNEL_TELEPHONY);
193                 }
194 {extern volatile uint16_t bufofs_play0, bufofs_dma0, bufofs_rec0;
195 bottom_printf ("p/d/r = %d, %d, %d\n", (intptr_t) bufofs_play0, (intptr_t) bufofs_dma0, (intptr_t) bufofs_rec0);
196 }
197
198 #ifdef CONFIG_FUNCTION_NETCONSOLE
199 bottom_led_set (LED_IDX_BACKLIGHT, 1);
200                 if (online) {
201                         netinputlen = sizeof (netinput);
202                         if (bottom_network_recv (netinput, &netinputlen)) {
203                                 nethandler_llconly (netinput, netinputlen);
204                                 { uint32_t ctr = 10000; while (ctr--) ; }
205                         }
206                         trysend ();
207                 }
208 bottom_led_set (LED_IDX_BACKLIGHT, 0);
209 #endif
210
211 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
212                 bottom_keyboard_scan ();
213 #endif
214
215 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK
216                 bottom_hook_scan ();
217 #endif
218
219         }
220 }
221
222
223 /******** TOP_MAIN FOR AN ECHO WITH 1 SECOND DELAY ********/
224
225 uint16_t playpos = 0;
226 uint16_t recpos = 0;
227 uint16_t sampled = 0;
228
229 #define abs(x) (((x)>0)?(x):(-(x)))
230
231 /* 1 second at 8000 samples per second, 2 bytes each, plus 25% extra */
232 int8_t samples [20000];
233
234 void top_main_delay_1sec (void) {
235         uint16_t prepblocks = 0;
236         uint16_t playptr = 4000, recptr = 0;
237         bottom_critical_region_end ();
238         memset (samples, 0x33, sizeof (samples));
239         if (!bottom_soundchannel_acceptable_samplerate (PHONE_CHANNEL_TELEPHONY, 8000)) {
240                 bottom_printf ("Failed to set sample rate");
241                 bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_CALL_ENDED);
242                 while (true) {
243                         ;
244                 }
245         }
246         bottom_soundchannel_set_samplerate (PHONE_CHANNEL_TELEPHONY, 8000, 100, 1, 1);
247         bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY, 127);
248         bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_READY);
249         bottom_printf ("Running the development function \"echo\" (Test sound)\n");
250         top_hook_update (bottom_phone_is_offhook ());
251         while (true) {
252                 int16_t *buf;
253                 uint16_t pcmlen, pktlen;
254
255                 do {
256                         buf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY);
257                 } while (buf == NULL);
258                 pcmlen = 100;
259                 pktlen = 200;
260                 // Note: No handle needed for stateless L16
261 bottom_printf ("Playing %d, %d, %d...\n", 0xffff & (intptr_t) buf [0], 0xffff & (intptr_t) buf [1], 0xffff & (intptr_t) buf [2]);
262                 l16_encode (NULL, buf, &pcmlen, samples + playptr, &pktlen);
263                 bottom_play_release (PHONE_CHANNEL_TELEPHONY);
264
265                 playptr += 200;
266                 if (playptr >= 20000) {
267                         playptr -= 20000;
268                 }
269
270                 do {
271                         buf = bottom_record_claim (PHONE_CHANNEL_TELEPHONY);
272                 } while (buf == NULL);
273                 pcmlen = 100;
274                 pktlen = 200;
275                 // Note: No handle needed for stateless L16
276                 l16_decode (NULL, buf, &pcmlen, samples + recptr, &pktlen);
277 bottom_printf ("Recorded %d, %d, %d...\n", 0xffff & (intptr_t) buf [0], 0xffff & (intptr_t) buf [1], 0xffff & (intptr_t) buf [2]);
278                 bottom_record_release (PHONE_CHANNEL_TELEPHONY);
279
280                 recptr += 200;
281                 if (recptr >= 20000) {
282                         recptr -= 20000;
283                 }
284
285 #ifdef CONFIG_FUNCTION_NETCONSOLE
286                 // { uint32_t ctr = 10000; while (ctr--) ; }
287                 trysend ();
288                 // { uint32_t ctr = 10000; while (ctr--) ; }
289 bottom_led_set (LED_IDX_BACKLIGHT, 1);
290                 netinputlen = sizeof (netinput);
291                 if (bottom_network_recv (netinput, &netinputlen)) {
292                         nethandler_llconly (netinput, netinputlen);
293 bottom_led_set (LED_IDX_BACKLIGHT, 0);
294                         { uint32_t ctr = 10000; while (ctr--) ; }
295                 }
296 bottom_led_set (LED_IDX_BACKLIGHT, 0);
297                 trysend ();
298 #endif
299
300 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
301                 bottom_keyboard_scan ();
302 #endif
303
304 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK
305                 bottom_hook_scan ();
306 #endif
307
308         }
309 }
310