1 /* echo.c -- Sound I/O test program
3 * This file is part of 0cpm Firmerware.
5 * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
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.
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.
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/>.
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.
26 * From: Rick van Rein <rick@openfortress.nl>
35 //TODO// test inclusion of bottom and text definitions
38 #include <0cpm/text.h>
42 #include <0cpm/cons.h>
43 #include <0cpm/show.h>
48 volatile uint16_t tobeplayed = 0;
49 volatile uint16_t toberecorded = 0;
52 timing_t top_timer_expiration (timing_t timeout) {
53 /* Keep the linker happy */ ;
57 void top_hook_update (bool offhook) {
59 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_HANDSET);
61 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_SPEAKER);
67 void top_network_online (void) {
71 void top_network_offline (void) {
75 void top_network_can_send (void) {
76 /* Keep the linker happy */ ;
79 void top_network_can_recv (void) {
80 /* Keep the linker happy */ ;
83 void top_button_press (buttonclass_t bcl, buttoncode_t cde) {
84 if (bcl != BUTCLS_FIXED_FUNCTION) {
90 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY,
91 bottom_soundchannel_getvolume (PHONE_CHANNEL_TELEPHONY) + 1);
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);
105 void top_button_release (void) {
106 /* Keep the linker happy */
109 uint16_t plyirqs = 0;
110 void top_codec_can_play (uint8_t chan) {
114 uint16_t recirqs = 0;
115 void top_codec_can_record (uint8_t chan) {
120 #define top_main_sine_1khz top_main
121 // #define top_main_delay_1sec top_main
124 #ifdef CONFIG_FUNCTION_NETCONSOLE
125 uint8_t netinput [1000];
126 uint16_t netinputlen;
127 void nethandler_llconly (uint8_t *pkt, uint16_t pktlen);
131 /******** TOP_MAIN FOR A 1 KHZ SINE WAVE OUTPUT ********/
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
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
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);
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 ());
173 /* First play as many samples as possible */
175 while ((outbuf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY))) {
176 uint16_t pcmlen, pktlen;
180 // Note: No handle needed for stateless L8
181 l8_decode (NULL, outbuf, &pcmlen, sinewaveL8, &pktlen);
185 // Note: No handle needed for stateless L16
186 l16_decode (NULL, outbuf, &pcmlen, sinewaveL16, &pktlen);
188 bottom_play_release (PHONE_CHANNEL_TELEPHONY);
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);
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);
198 #ifdef CONFIG_FUNCTION_NETCONSOLE
199 bottom_led_set (LED_IDX_BACKLIGHT, 1);
201 netinputlen = sizeof (netinput);
202 if (bottom_network_recv (netinput, &netinputlen)) {
203 nethandler_llconly (netinput, netinputlen);
204 { uint32_t ctr = 10000; while (ctr--) ; }
208 bottom_led_set (LED_IDX_BACKLIGHT, 0);
211 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
212 bottom_keyboard_scan ();
215 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK
223 /******** TOP_MAIN FOR AN ECHO WITH 1 SECOND DELAY ********/
225 uint16_t playpos = 0;
227 uint16_t sampled = 0;
229 #define abs(x) (((x)>0)?(x):(-(x)))
231 /* 1 second at 8000 samples per second, 2 bytes each, plus 25% extra */
232 int8_t samples [20000];
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);
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 ());
253 uint16_t pcmlen, pktlen;
256 buf = bottom_play_claim (PHONE_CHANNEL_TELEPHONY);
257 } while (buf == NULL);
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);
266 if (playptr >= 20000) {
271 buf = bottom_record_claim (PHONE_CHANNEL_TELEPHONY);
272 } while (buf == NULL);
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);
281 if (recptr >= 20000) {
285 #ifdef CONFIG_FUNCTION_NETCONSOLE
286 // { uint32_t ctr = 10000; while (ctr--) ; }
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--) ; }
296 bottom_led_set (LED_IDX_BACKLIGHT, 0);
300 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
301 bottom_keyboard_scan ();
304 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK