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 definitions
41 #include <0cpm/cons.h>
42 #include <0cpm/show.h>
47 volatile uint16_t tobeplayed = 0;
48 volatile uint16_t toberecorded = 0;
51 timing_t top_timer_expiration (timing_t timeout) {
52 /* Keep the linker happy */ ;
56 void top_hook_update (bool offhook) {
58 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_HANDSET);
60 bottom_soundchannel_device (PHONE_CHANNEL_TELEPHONY, PHONE_SOUNDDEV_SPEAKER);
64 void top_network_online (void) {
65 /* Keep the linker happy */ ;
68 void top_network_offline (void) {
69 /* Keep the linker happy */ ;
72 void top_network_can_send (void) {
73 /* Keep the linker happy */ ;
76 void top_network_can_recv (void) {
77 /* Keep the linker happy */ ;
80 void top_button_press (buttonclass_t bcl, buttoncode_t cde) {
81 if (bcl != BUTCLS_FIXED_FUNCTION) {
87 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY,
88 bottom_soundchannel_getvolume (PHONE_CHANNEL_TELEPHONY) + 1);
91 #ifdef HAVE_BUTTON_DOWN
92 case HAVE_BUTTON_DOWN:
93 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY,
94 bottom_soundchannel_getvolume (PHONE_CHANNEL_TELEPHONY) - 1);
102 void top_button_release (void) {
103 /* Keep the linker happy */
106 uint16_t plyirqs = 0;
107 void top_can_play (uint16_t samples) {
108 tobeplayed = samples;
112 uint16_t recirqs = 0;
113 void top_can_record (uint16_t samples) {
114 toberecorded = samples;
119 #define top_main_delay_1sec top_main
120 // #define top_main_sine_1khz top_main
123 #ifdef CONFIG_FUNCTION_NETCONSOLE
124 uint8_t netinput [1000];
125 uint16_t netinputlen;
126 void nethandler_llconly (uint8_t *pkt, uint16_t pktlen);
130 /******** TOP_MAIN FOR A 1 KHZ SINE WAVE OUTPUT ********/
132 uint8_t sinewave [8] = {
133 0x00, 0x5a, 0x7f, 0x5a, 0x00, 0xa5, 0x80, 0xa5
136 void top_main_sine_1khz (void) {
137 uint16_t oldirqs = 0;
138 extern volatile uint16_t available_play;
139 top_hook_update (bottom_phone_is_offhook ());
140 bottom_codec_play_samplerate (0, 8000);
141 bottom_codec_record_samplerate (0, 8000); // Both MUST be called for now
142 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY, 127);
143 bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_RINGING); // TODO: Not really necessary
144 bottom_printf ("Playing 1 kHz tone to speaker or handset\n");
147 uint16_t newplayed = tobeplayed;
148 uint16_t oldplayed = newplayed;
149 if (oldirqs != plyirqs) {
150 bottom_printf ("New playing IRQs detected\n");
153 while (newplayed >= 8) {
154 bottom_codec_play (0, CODEC_L8, sinewave, 8, 8);
156 bottom_critical_region_end ();
159 if (oldplayed != newplayed) {
160 bottom_printf ("available_play := %d\n", (intptr_t) available_play);
161 bottom_printf ("Playbuffer reduced from %d to %d\n", (intptr_t) oldplayed, (intptr_t) newplayed);
165 #ifdef CONFIG_FUNCTION_NETCONSOLE
167 bottom_led_set (LED_IDX_BACKLIGHT, 1);
168 netinputlen = sizeof (netinput);
169 if (bottom_network_recv (netinput, &netinputlen)) {
170 nethandler_llconly (netinput, netinputlen);
171 { uint32_t ctr = 10000; while (ctr--) ; }
172 bottom_led_set (LED_IDX_BACKLIGHT, 0);
177 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
178 bottom_keyboard_scan ();
181 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK
189 /******** TOP_MAIN FOR AN ECHO WITH 1 SECOND DELAY ********/
191 uint16_t playpos = 0;
193 uint16_t sampled = 0;
195 #define abs(x) (((x)>0)?(x):(-(x)))
197 /* 1 second at 8000 samples per second, plus 25% extra */
198 uint8_t samples [10000];
200 void top_main_delay_1sec (void) {
201 uint16_t prevsampled = 0;
202 uint16_t prevrecirqs = 0;
203 uint16_t prevplyirqs = 0;
204 uint16_t oldspcr1 = 0xffff;
206 bottom_critical_region_end ();
207 top_hook_update (bottom_phone_is_offhook ());
208 bottom_codec_play_samplerate (PHONE_CHANNEL_TELEPHONY, 8000);
209 bottom_codec_record_samplerate (PHONE_CHANNEL_TELEPHONY, 8000);
210 bottom_soundchannel_setvolume (PHONE_CHANNEL_TELEPHONY, 127);
211 bottom_show_fixed_msg (APP_LEVEL_ZERO, FIXMSG_READY); // TODO: Not really necessary
212 bottom_printf ("Running the development function \"echo\" (Test sound)\n");
217 uint8_t chan = PHONE_CHANNEL_TELEPHONY;
218 for (reg = 1; reg <= 6; reg++) {
219 uint8_t val0, val1, val2, val3;
220 for (subreg = 0; subreg <=3 ; subreg++) {
221 val0 = tlv320aic2x_getreg (chan, reg);
222 val1 = tlv320aic2x_getreg (chan, reg);
223 val2 = tlv320aic2x_getreg (chan, reg);
224 val3 = tlv320aic2x_getreg (chan, reg);
226 bottom_printf ("TLV_%d = %02x, %02x, %02x, %02x\n", (intptr_t) reg, (intptr_t) val0, (intptr_t) val1, (intptr_t) val2, (intptr_t) val3);
231 if (recirqs != prevrecirqs) {
232 bottom_printf ("Record IRQs #%d, ", (intptr_t) recirqs);
233 bottom_printf ("available %d\n", (intptr_t) toberecorded);
234 prevrecirqs = recirqs;
236 if (plyirqs != prevplyirqs) {
237 bottom_printf ("Playbk IRQs #%d, ", (intptr_t) plyirqs);
238 bottom_printf ("available %d\n", (intptr_t) tobeplayed);
239 prevplyirqs = plyirqs;
242 {uint16_t xor = oldspcr1 ^ SPCR1_1; if (xor) { oldspcr1 ^= xor; bottom_printf ("SPCR1_1 := 0x%04x\n", oldspcr1); } }
243 if (sampled != prevsampled) {
244 bottom_printf ("Buffered %d samples\n", (intptr_t) sampled);
245 prevsampled = sampled;
247 if (toberecorded > 0) {
248 int16_t rec = toberecorded;
249 bottom_led_set (LED_IDX_HANDSET, 1);
250 if (sampled + rec > 10000) {
251 rec = 10000 - sampled;
253 if (recpos + rec > 10000) {
254 rec = 10000 - recpos;
257 bottom_printf ("Recording %d extends buffer from %d to %d\n", (intptr_t) rec, (intptr_t) sampled, (intptr_t) (rec+sampled));
258 // Codec implies that #samples and #bytes are the same
259 rec -= abs (bottom_codec_record (0, CODEC_G711A, samples + recpos, rec, rec));
262 if (recpos >= 10000) {
265 bottom_critical_region_begin ();
266 //TODO:SPYING-ON-NEXT-LINE// toberecorded -= rec;
267 { extern uint16_t available_record; toberecorded = available_record; }
268 bottom_critical_region_end ();
270 bottom_led_set (LED_IDX_SPEAKERPHONE, 0);
272 if (sampled > 8000) {
273 uint16_t ply = sampled - 8000;
274 bottom_led_set (LED_IDX_SPEAKERPHONE, 1);
275 if (playpos + ply > 10000) {
276 ply = 10000 - playpos;
279 bottom_printf ("Playback of %d samples reduces buffer from %d to %d\n", (intptr_t) ply, (intptr_t) sampled, (intptr_t) (sampled - ply));
280 ply -= abs (bottom_codec_play (0, CODEC_G711A, samples + playpos, ply, ply));
283 if (playpos >= 10000) {
286 bottom_led_set (LED_IDX_HANDSET, 0);
289 #ifdef CONFIG_FUNCTION_NETCONSOLE
290 // { uint32_t ctr = 10000; while (ctr--) ; }
292 // { uint32_t ctr = 10000; while (ctr--) ; }
293 bottom_led_set (LED_IDX_BACKLIGHT, 1);
294 netinputlen = sizeof (netinput);
295 if (bottom_network_recv (netinput, &netinputlen)) {
296 nethandler_llconly (netinput, netinputlen);
297 { uint32_t ctr = 10000; while (ctr--) ; }
298 bottom_led_set (LED_IDX_BACKLIGHT, 0);
302 #if defined NEED_KBD_SCANNER_BETWEEN_KEYS || defined NEED_KBD_SCANNER_DURING_KEYPRESS
303 bottom_keyboard_scan ();
305 #if defined NEED_HOOK_SCANNER_WHEN_ONHOOK || defined NEED_HOOK_SCANNER_WHEN_OFFHOOK