diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/recorder/radio.c | 296 | ||||
-rw-r--r-- | apps/recorder/radio.h | 7 |
2 files changed, 300 insertions, 3 deletions
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c index 839fafe303..6fcc982946 100644 --- a/apps/recorder/radio.c +++ b/apps/recorder/radio.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "config.h" | 20 | #include "config.h" |
21 | #include <stdio.h> | 21 | #include <stdio.h> |
22 | #include <stdbool.h> | 22 | #include <stdbool.h> |
23 | #include "sprintf.h" | ||
23 | #include "lcd.h" | 24 | #include "lcd.h" |
24 | #include "mas.h" | 25 | #include "mas.h" |
25 | #include "settings.h" | 26 | #include "settings.h" |
@@ -28,6 +29,17 @@ | |||
28 | #include "status.h" | 29 | #include "status.h" |
29 | #include "kernel.h" | 30 | #include "kernel.h" |
30 | #include "mpeg.h" | 31 | #include "mpeg.h" |
32 | #include "ctype.h" | ||
33 | #include "file.h" | ||
34 | #include "errno.h" | ||
35 | #include "atoi.h" | ||
36 | #include "string.h" | ||
37 | #include "system.h" | ||
38 | #include "radio.h" | ||
39 | #include "menu.h" | ||
40 | #include "misc.h" | ||
41 | #include "keyboard.h" | ||
42 | #include "screens.h" | ||
31 | 43 | ||
32 | #ifdef HAVE_FMRADIO | 44 | #ifdef HAVE_FMRADIO |
33 | 45 | ||
@@ -36,9 +48,18 @@ | |||
36 | #define PLL_FREQ_STEP 10000 | 48 | #define PLL_FREQ_STEP 10000 |
37 | #define FREQ_STEP 100000 | 49 | #define FREQ_STEP 100000 |
38 | 50 | ||
51 | static int curr_preset = -1; | ||
39 | static int curr_freq = 99400000; | 52 | static int curr_freq = 99400000; |
40 | static int pll_cnt; | 53 | static int pll_cnt; |
41 | 54 | ||
55 | #define MAX_PRESETS 32 | ||
56 | static bool presets_loaded = false; | ||
57 | static struct fmstation presets[MAX_PRESETS]; | ||
58 | |||
59 | void fm_load_presets(void); | ||
60 | bool fm_preset_select(void); | ||
61 | bool fm_f3_menu(void); | ||
62 | |||
42 | void fm_set_frequency(int freq) | 63 | void fm_set_frequency(int freq) |
43 | { | 64 | { |
44 | /* We add the standard Intermediate Frequency 10.7MHz before calculating | 65 | /* We add the standard Intermediate Frequency 10.7MHz before calculating |
@@ -55,6 +76,21 @@ void fm_set_frequency(int freq) | |||
55 | fmradio_set(1, 0x100002 | pll_cnt << 3); | 76 | fmradio_set(1, 0x100002 | pll_cnt << 3); |
56 | } | 77 | } |
57 | 78 | ||
79 | static int find_preset(int freq) | ||
80 | { | ||
81 | int i; | ||
82 | if(presets_loaded) | ||
83 | { | ||
84 | for(i = 0;i < MAX_PRESETS;i++) | ||
85 | { | ||
86 | if(freq == presets[i].frequency) | ||
87 | return i; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | return -1; | ||
92 | } | ||
93 | |||
58 | bool radio_screen(void) | 94 | bool radio_screen(void) |
59 | { | 95 | { |
60 | char buf[128]; | 96 | char buf[128]; |
@@ -71,6 +107,8 @@ bool radio_screen(void) | |||
71 | lcd_setmargins(0, 8); | 107 | lcd_setmargins(0, 8); |
72 | status_draw(false); | 108 | status_draw(false); |
73 | fmradio_set_status(FMRADIO_PLAYING); | 109 | fmradio_set_status(FMRADIO_PLAYING); |
110 | |||
111 | fm_load_presets(); | ||
74 | 112 | ||
75 | /* Enable the Left and right A/D Converter */ | 113 | /* Enable the Left and right A/D Converter */ |
76 | mas_codec_writereg(0x0, 0xccc7); | 114 | mas_codec_writereg(0x0, 0xccc7); |
@@ -79,6 +117,7 @@ bool radio_screen(void) | |||
79 | 117 | ||
80 | fmradio_set(2, 0x140884); /* 5kHz, 7.2MHz crystal */ | 118 | fmradio_set(2, 0x140884); /* 5kHz, 7.2MHz crystal */ |
81 | fm_set_frequency(curr_freq); | 119 | fm_set_frequency(curr_freq); |
120 | curr_preset = find_preset(curr_freq); | ||
82 | 121 | ||
83 | while(!done) | 122 | while(!done) |
84 | { | 123 | { |
@@ -108,18 +147,26 @@ bool radio_screen(void) | |||
108 | 147 | ||
109 | /* Stop searching if the IF frequency is close to 10.7MHz */ | 148 | /* Stop searching if the IF frequency is close to 10.7MHz */ |
110 | if(i_freq > 1065 && i_freq < 1075) | 149 | if(i_freq > 1065 && i_freq < 1075) |
150 | { | ||
111 | search_dir = 0; | 151 | search_dir = 0; |
152 | curr_preset = find_preset(curr_freq); | ||
153 | } | ||
112 | } | 154 | } |
113 | 155 | ||
114 | freq = curr_freq / 100000; | 156 | freq = curr_freq / 100000; |
115 | snprintf(buf, 128, "Freq: %d.%dMHz", freq / 10, freq % 10); | 157 | snprintf(buf, 128, "Freq: %d.%dMHz", freq / 10, freq % 10); |
116 | lcd_puts(0, 1, buf); | 158 | lcd_puts(0, 2, buf); |
117 | 159 | ||
118 | val = fmradio_read(3); | 160 | val = fmradio_read(3); |
119 | stereo = (val & 0x100000)?true:false; | 161 | stereo = (val & 0x100000)?true:false; |
120 | lock = (val & 0x80000)?true:false; | 162 | lock = (val & 0x80000)?true:false; |
121 | snprintf(buf, 128, "Mode: %s", stereo?"Stereo":"Mono"); | 163 | snprintf(buf, 128, "Mode: %s", stereo?"Stereo":"Mono"); |
122 | lcd_puts(0, 2, buf); | 164 | lcd_puts(0, 3, buf); |
165 | |||
166 | if(curr_preset >= 0) | ||
167 | { | ||
168 | lcd_puts_scroll(0, 1, presets[curr_preset].name); | ||
169 | } | ||
123 | 170 | ||
124 | lcd_update(); | 171 | lcd_update(); |
125 | 172 | ||
@@ -129,7 +176,7 @@ bool radio_screen(void) | |||
129 | button = button_get_w_tmo(HZ/2); | 176 | button = button_get_w_tmo(HZ/2); |
130 | switch(button) | 177 | switch(button) |
131 | { | 178 | { |
132 | case BUTTON_OFF | BUTTON_REL: | 179 | case BUTTON_OFF: |
133 | done = true; | 180 | done = true; |
134 | break; | 181 | break; |
135 | 182 | ||
@@ -139,6 +186,7 @@ bool radio_screen(void) | |||
139 | curr_freq = MIN_FREQ; | 186 | curr_freq = MIN_FREQ; |
140 | 187 | ||
141 | fm_set_frequency(curr_freq); | 188 | fm_set_frequency(curr_freq); |
189 | curr_preset = find_preset(curr_freq); | ||
142 | search_dir = 0; | 190 | search_dir = 0; |
143 | break; | 191 | break; |
144 | 192 | ||
@@ -148,6 +196,7 @@ bool radio_screen(void) | |||
148 | curr_freq = MAX_FREQ; | 196 | curr_freq = MAX_FREQ; |
149 | 197 | ||
150 | fm_set_frequency(curr_freq); | 198 | fm_set_frequency(curr_freq); |
199 | curr_preset = find_preset(curr_freq); | ||
151 | search_dir = 0; | 200 | search_dir = 0; |
152 | break; | 201 | break; |
153 | 202 | ||
@@ -179,13 +228,254 @@ bool radio_screen(void) | |||
179 | settings_save(); | 228 | settings_save(); |
180 | break; | 229 | break; |
181 | 230 | ||
231 | case BUTTON_F2: | ||
232 | fm_preset_select(); | ||
233 | curr_preset = find_preset(curr_freq); | ||
234 | lcd_clear_display(); | ||
235 | lcd_setmargins(0, 8); | ||
236 | status_draw(false); | ||
237 | break; | ||
238 | |||
239 | case BUTTON_F3: | ||
240 | fm_f3_menu(); | ||
241 | curr_preset = find_preset(curr_freq); | ||
242 | lcd_clear_display(); | ||
243 | lcd_setmargins(0, 8); | ||
244 | status_draw(false); | ||
245 | break; | ||
246 | |||
182 | case BUTTON_NONE: | 247 | case BUTTON_NONE: |
183 | status_draw(true); | 248 | status_draw(true); |
184 | break; | 249 | break; |
250 | |||
251 | case SYS_USB_CONNECTED: | ||
252 | usb_screen(); | ||
253 | fmradio_set_status(0); | ||
254 | return true; | ||
185 | } | 255 | } |
186 | } | 256 | } |
187 | 257 | ||
188 | fmradio_set_status(0); | 258 | fmradio_set_status(0); |
189 | return false; | 259 | return false; |
190 | } | 260 | } |
261 | |||
262 | static bool parseline(char* line, char** freq, char** name) | ||
263 | { | ||
264 | char* ptr; | ||
265 | |||
266 | while ( isspace(*line) ) | ||
267 | line++; | ||
268 | |||
269 | if ( *line == '#' ) | ||
270 | return false; | ||
271 | |||
272 | ptr = strchr(line, ':'); | ||
273 | if ( !ptr ) | ||
274 | return false; | ||
275 | |||
276 | *freq = line; | ||
277 | *ptr = 0; | ||
278 | ptr++; | ||
279 | while (isspace(*ptr)) | ||
280 | ptr++; | ||
281 | *name = ptr; | ||
282 | return true; | ||
283 | } | ||
284 | |||
285 | void fm_save_presets(void) | ||
286 | { | ||
287 | int fd; | ||
288 | int i; | ||
289 | |||
290 | fd = open("/.rockbox/fm_presets.txt", O_WRONLY); | ||
291 | if(fd >= 0) | ||
292 | { | ||
293 | for(i = 0;i < MAX_PRESETS;i++) | ||
294 | { | ||
295 | fprintf(fd, "%d:%s\n", presets[i].frequency, presets[i].name); | ||
296 | } | ||
297 | close(fd); | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | splash(HZ*2, 0, true, "Preset save failed"); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | void fm_load_presets(void) | ||
306 | { | ||
307 | int fd; | ||
308 | int rc; | ||
309 | char buf[128]; | ||
310 | char *freq; | ||
311 | char *name; | ||
312 | int num_presets = 0; | ||
313 | bool done = false; | ||
314 | int i; | ||
315 | |||
316 | if(!presets_loaded) | ||
317 | { | ||
318 | memset(presets, 0, sizeof(presets)); | ||
319 | |||
320 | fd = open("/.rockbox/fm_presets.txt", O_RDONLY); | ||
321 | if(fd >= 0) | ||
322 | { | ||
323 | i = 0; | ||
324 | while(!done) | ||
325 | { | ||
326 | rc = read_line(fd, buf, 128); | ||
327 | if(rc > 0) | ||
328 | { | ||
329 | if(parseline(buf, &freq, &name)) | ||
330 | { | ||
331 | presets[i].frequency = atoi(freq); | ||
332 | strncpy(presets[i].name, name, 27); | ||
333 | presets[i].name[27] = 0; | ||
334 | i++; | ||
335 | presets_loaded = true; | ||
336 | if(num_presets == MAX_PRESETS) | ||
337 | done = true; | ||
338 | } | ||
339 | } | ||
340 | else | ||
341 | done = true; | ||
342 | } | ||
343 | close(fd); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | bool fm_preset_select(void) | ||
349 | { | ||
350 | struct menu_items menu[MAX_PRESETS]; | ||
351 | int m, result; | ||
352 | int i; | ||
353 | bool reload_dir = false; | ||
354 | int num_presets; | ||
355 | |||
356 | if(presets_loaded) | ||
357 | { | ||
358 | num_presets = 0; | ||
359 | |||
360 | for(i = 0;i < MAX_PRESETS;i++) | ||
361 | { | ||
362 | if(presets[i].frequency) | ||
363 | { | ||
364 | menu[num_presets].desc = presets[i].name; | ||
365 | /* We use the function pointer entry for the preset | ||
366 | entry index */ | ||
367 | menu[num_presets++].function = (void *)i; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | if(num_presets) | ||
372 | { | ||
373 | /* DIY menu handling, since we want to exit after selection */ | ||
374 | m = menu_init( menu, num_presets ); | ||
375 | result = menu_show(m); | ||
376 | menu_exit(m); | ||
377 | if (result == MENU_SELECTED_EXIT) | ||
378 | return false; | ||
379 | else if (result == MENU_ATTACHED_USB) | ||
380 | reload_dir = true; | ||
381 | |||
382 | if (result >= 0) | ||
383 | { | ||
384 | i = (int)menu[result].function; | ||
385 | curr_freq = presets[i].frequency; | ||
386 | fm_set_frequency(curr_freq); | ||
387 | } | ||
388 | } | ||
389 | else | ||
390 | { | ||
391 | splash(HZ*2, 0, true, "No presets"); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | return reload_dir; | ||
396 | } | ||
397 | |||
398 | static bool fm_add_preset(void) | ||
399 | { | ||
400 | char buf[27]; | ||
401 | int i = find_preset(0); | ||
402 | |||
403 | if(i >= 0) | ||
404 | { | ||
405 | memset(buf, 0, 27); | ||
406 | |||
407 | if (!kbd_input(buf, 27)) | ||
408 | { | ||
409 | buf[27] = 0; | ||
410 | strcpy(presets[i].name, buf); | ||
411 | presets[i].frequency = curr_freq; | ||
412 | fm_save_presets(); | ||
413 | } | ||
414 | } | ||
415 | else | ||
416 | { | ||
417 | splash(HZ*2, 0, true, "No free preset entries"); | ||
418 | } | ||
419 | return true; | ||
420 | } | ||
421 | |||
422 | bool fm_delete_preset(void) | ||
423 | { | ||
424 | struct menu_items menu[MAX_PRESETS]; | ||
425 | int m, result; | ||
426 | int i; | ||
427 | bool reload_dir = false; | ||
428 | int num_presets; | ||
429 | |||
430 | if(presets_loaded) | ||
431 | { | ||
432 | num_presets = 0; | ||
433 | |||
434 | for(i = 0;i < MAX_PRESETS;i++) | ||
435 | { | ||
436 | if(presets[i].frequency) | ||
437 | { | ||
438 | menu[num_presets].desc = presets[i].name; | ||
439 | /* We use the function pointer entry for the preset | ||
440 | entry index */ | ||
441 | menu[num_presets++].function = (void *)i; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | /* DIY menu handling, since we want to exit after selection */ | ||
446 | m = menu_init( menu, num_presets ); | ||
447 | result = menu_show(m); | ||
448 | menu_exit(m); | ||
449 | if (result == MENU_SELECTED_EXIT) | ||
450 | return false; | ||
451 | else if (result == MENU_ATTACHED_USB) | ||
452 | reload_dir = true; | ||
453 | |||
454 | if (result >= 0) | ||
455 | { | ||
456 | i = (int)menu[result].function; | ||
457 | presets[i].frequency = 0; | ||
458 | fm_save_presets(); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | return reload_dir; | ||
463 | } | ||
464 | |||
465 | static struct menu_items f3_items[] = { | ||
466 | { "Add preset...", fm_add_preset }, | ||
467 | { "Delete preset...", fm_delete_preset } | ||
468 | }; | ||
469 | |||
470 | bool fm_f3_menu(void) | ||
471 | { | ||
472 | int m; | ||
473 | bool result; | ||
474 | |||
475 | m = menu_init( f3_items, sizeof f3_items / sizeof(struct menu_items) ); | ||
476 | result = menu_run(m); | ||
477 | menu_exit(m); | ||
478 | return result; | ||
479 | } | ||
480 | |||
191 | #endif | 481 | #endif |
diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h index dafa46d90d..f6d7686ea9 100644 --- a/apps/recorder/radio.h +++ b/apps/recorder/radio.h | |||
@@ -21,6 +21,13 @@ | |||
21 | 21 | ||
22 | #ifdef HAVE_FMRADIO | 22 | #ifdef HAVE_FMRADIO |
23 | bool radio_screen(void); | 23 | bool radio_screen(void); |
24 | |||
25 | struct fmstation | ||
26 | { | ||
27 | int frequency; /* In Hz */ | ||
28 | char name[28]; | ||
29 | }; | ||
30 | |||
24 | #endif | 31 | #endif |
25 | 32 | ||
26 | #endif | 33 | #endif |