OSDN Git Service

[SCHEMATIC] Modify SW/MW/LW Preamp, insert galbanic-isolator replace of common-mode...
[openi2cradio/OpenI2CRadio.git] / akc6955.c
1 /*
2  * OpenI2CRADIO
3  * RADIO CHIP AKC6955 Handler
4  * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
5  * License: GPL2+LE
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2,
10  *  or (at your option) any later version.
11  *  This library / program 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.
14  *  See the GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this library; see the file COPYING. If not, write to the
18  *  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19  *  MA 02110-1301, USA.
20  *
21  *  As a special exception, if you link this(includeed from sdcc) library
22  *  with other files, some of which are compiled with SDCC,
23  *  to produce an executable, this library does not by itself cause
24  *  the resulting executable to be covered by the GNU General Public License.
25  *  This exception does not however invalidate any other reasons why
26  *  the executable file might be covered by the GNU General Public License.
27  */
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #ifdef __SDCC
32 #include <delay.h>
33 #else
34 #include <xc.h>
35 #endif
36 #include <string.h>
37 #include "akc6955.h"
38 #include "i2c_io.h"
39 #include "idle.h"
40 #include "power.h"
41 #include "commondef.h"
42 #include "menu.h"
43 #include "ui.h"
44
45 unsigned char akc6955_readcmd(unsigned char reg)
46 {
47    return i2c_read_byte(AKC6955_ADDRESS, reg);
48 }
49
50 void akc6955_writecmd(unsigned char reg,unsigned char data)
51 {
52     i2c_send_byte(AKC6955_ADDRESS, reg, data);
53 }
54
55 unsigned char akc6955_get_band(void)
56 {
57     return akc6955_readcmd(AKC6955_BAND);
58 }
59
60 unsigned char akc6955_get_amband(void)
61 {
62    return akc6955_get_band() >> 3; 
63 }
64
65 unsigned char akc6955_get_fmband(void)
66 {
67    return akc6955_get_band() & 0x07; 
68 }
69
70
71 void akc6955_chg_fm(unsigned char f, unsigned int freq)
72 {
73     __bitops_t b;
74     b.byte = akc6955_readcmd(AKC6955_POWER);
75     b.b6 = 0;
76     if(f != 0){
77         b.b6 = 1;
78         akc6955_set_fmband(setup.fmband);
79         akc6955_writecmd(AKC6955_POWER, b.byte);
80         akc6955_set_freq(freq);
81         return;
82     }
83     akc6955_writecmd(AKC6955_POWER, b.byte);
84     akc6955_set_amband(setup.amband);
85     akc6955_set_freq(freq);
86
87 }
88
89 unsigned char akc6955_get_fm(void)
90 {
91     __bitops_t b;
92     b.byte = akc6955_readcmd(AKC6955_POWER);
93     if(b.b6){
94         return 0xff;
95     }
96     return 0;
97 }
98
99
100 void akc6955_set_amband(unsigned char band)
101 {
102     unsigned char b;
103     unsigned char c;
104
105     c = RFAMP_SW;
106     if((band < AKC6955_BAND_SW1) || (band == AKC6955_BAND_MW4)) {
107         c = RFAMP_MWLW;
108     }
109     rfamp_power(c);
110     b = akc6955_readcmd(AKC6955_BAND);
111     b &= 0x07; // extract FM
112     b = b | ((band & 0x1f) << 3);
113     akc6955_writecmd(AKC6955_BAND, b);
114     akc6955_do_tune();
115 }
116
117 void akc6955_set_fmband(unsigned char band)
118 {
119     unsigned char b;
120     rfamp_power(RFAMP_FM);
121     b = akc6955_readcmd(AKC6955_BAND);
122     b &= 0xf8; // extract AM
123     b = b | (band & 0x07);
124     akc6955_writecmd(AKC6955_BAND, b);
125     akc6955_do_tune();
126 }
127
128 void akc6955_set_power(unsigned char on)
129 {
130     __bitops_t b;
131     b.byte = akc6955_readcmd(AKC6955_POWER);
132     b.b7 = 0;
133     if(on != 0){
134         b.b7 = 1;
135     }
136     akc6955_writecmd(AKC6955_POWER, b.byte);
137 }
138
139 void akc6955_do_tune(void)
140 {
141     __bitops_t b;
142     b.byte = akc6955_readcmd(AKC6955_POWER) & 0b11001111;
143 //    b.b5 = 0; // Tun = '0'
144 //    b.b4 = 0; // Force abort scan.
145     akc6955_writecmd(AKC6955_POWER, b.byte);
146     idle_time_ms(1);
147     // Need sleep?-> Need! this sequence re                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 fer from reference code.
148     b.b5= 1; // Tun = '1'
149     akc6955_writecmd(AKC6955_POWER, b.byte);
150     idle_time_ms(1);
151     b.b5 = 0;
152     akc6955_writecmd(AKC6955_POWER, b.byte);
153     idle_time_ms(8);
154 }
155
156 unsigned char akc6955_tune(void)
157 {
158     __bitops_t b;
159     b.byte = akc6955_readcmd(AKC6955_RCH_HI);
160     if(b.b5) {
161         return 0xff;
162     }
163     return 0;
164 }
165
166
167 void akc6955_mode3k(unsigned char flag)
168 {
169     __bitops_t b;
170     b.byte = akc6955_readcmd(AKC6955_CH_LO);
171     akc6955_writecmd(AKC6955_CH_LO, b.byte);
172
173     b.byte = akc6955_readcmd(AKC6955_CH_HI);
174     b.b5 = 0;
175     if(flag != 0){
176         b.b5 = 1;
177     }
178     akc6955_writecmd(AKC6955_CH_HI, b.byte);
179     akc6955_do_tune();
180 }
181
182 unsigned char akc6955_get_mode3k(void)
183 {
184     __bitops_t c;
185     c.byte = akc6955_readcmd(AKC6955_CNR_AM);
186     if(c.b7) {
187         return 0xff;
188     }
189     return 0;
190 }
191
192 void akc6955_set_tune(unsigned char mode_3k, unsigned int ch)
193 {
194     unsigned char band;
195     unsigned char f;
196     __bitops_t b;
197     unsigned int i = ch;
198     unsigned int start, stop;
199     unsigned char q;
200
201     while(akc6955_chk_donescan() == 0) { // Wait for before completed
202         idle_time_35ms();
203     }
204     f = akc6955_get_fm();
205     band = 0;
206     if(f == 0){
207         band = akc6955_get_amband();
208         if(band == AKC6955_BAND_AMUSER){
209             start = userband.am_usrbands[setup.am_userbandnum].start * 32;
210             stop = userband.am_usrbands[setup.am_userbandnum].stop * 32;
211         } else {
212             if(mode_3k != 0) {
213                 q = 3;
214             } else {
215                 q = 5;
216             }
217             start = ambands[band].start / q;
218             stop  = ambands[band].end / q;
219         }
220     } else {
221         band = akc6955_get_fmband();
222         if(band == AKC6955_BAND_FMUSER){
223             start = userband.fm_usrbands[setup.fm_userbandnum].start * 32;
224             stop = userband.fm_usrbands[setup.fm_userbandnum].stop * 32;
225         } else {
226             start = ((fmbands[band].start - 3000) * 2) / 5;
227             stop = ((fmbands[band].end - 3000) * 2) / 5;;
228         }
229     }
230     if(i > stop) i = stop; // ADD
231     if(i < start) i = start;
232
233     b.byte = i & 0xff;
234     akc6955_writecmd(AKC6955_CH_LO, b.byte);
235
236     b.byte = i >> 8;
237     b.b6 = 1;
238     if(mode_3k != 0){
239         b.b5 = 1; // Mode 3K ON
240     }
241     akc6955_writecmd(AKC6955_CH_HI, b.byte);
242
243     akc6955_do_tune();
244 }
245
246 void akc6955_do_scan(unsigned char up)
247 {
248     __bitops_t b;
249     unsigned char c;
250
251     //20130823 Need wait for scan/tune completed w/o SDCC 3.3.x.
252 #ifndef __SDCC
253     while(akc6955_chk_donescan() == 0)
254     {
255         if(pollkey_single_timeout(1, 0) == charcode_a) return;  // 23ms, if 'A' Abort.
256     }
257 #endif
258     b.byte = akc6955_readcmd(AKC6955_POWER) & 0b11000111;
259
260 //    b.b3 = 0;
261  //   b.b4 = 0;
262 // 20130823 : Is this collect?
263 #ifdef __SDCC
264 //     b.b5 = 0;
265     akc6955_writecmd(AKC6955_POWER, b.byte);
266     idle_time_35ms();
267 #endif
268
269     b.b5 = 1; // Tune 0->1.
270     akc6955_writecmd(AKC6955_POWER, b.byte);
271     idle_time_35ms();
272
273     b.b4 = 1;
274     if(up != 0) {
275         b.b3= 1;
276     }
277     akc6955_writecmd(AKC6955_POWER, b.byte); // Raise seek bit to '1'.
278     idle_time_35ms();
279 }
280
281 void akc6955_abort_scan(void)
282 {
283     __bitops_t b;
284     b.byte = akc6955_readcmd(AKC6955_POWER);
285     b.b4 = 0;
286     akc6955_writecmd(AKC6955_POWER, b.byte); // Falldown seek bit to '0'.
287 }
288
289 void akc6955_set_scanrate_fm(unsigned char rate)
290 {
291     unsigned char c;
292     c = akc6955_readcmd(AKC6955_SPACE);
293     c = (c & 0xcf) | ((rate & 0x03) << 4);
294     akc6955_writecmd(AKC6955_SPACE, c);
295 }
296
297 unsigned char akc6955_get_scanrate_fm(void)
298 {
299 //    unsigned char c;
300 //    c = akc6955_readcmd(AKC6955_SPACE);
301 //    c = (c & 0x30) >> 4;
302    return (akc6955_readcmd(AKC6955_SPACE) & 0x30) >> 4;
303 }
304
305 unsigned char akc6955_chk_donescan(void)
306 {
307     __bitops_t b;
308     b.byte = akc6955_readcmd(AKC6955_RCH_HI);
309     if(b.b6){
310         return 0xff;
311     }
312     return 0;
313 }
314
315 unsigned int akc6955_get_channel(void)
316 {
317     unsigned char h, l;
318     unsigned int u;
319     l = akc6955_readcmd(AKC6955_RCH_LO) ;
320     h = akc6955_readcmd(AKC6955_RCH_HI) & 0x1f;
321     return  (h << 8) | l;
322 //    return u;
323 }
324
325 /*
326  * Get AM/FM Frequency: ret = KHz at AM, 10KHz @FM.
327  */
328 unsigned int akc6955_get_freq(void)
329 {
330     __bitops_t b;
331     unsigned int i;
332     unsigned int freq;
333     unsigned char band;
334     unsigned char q;
335     unsigned char f;
336
337     f = akc6955_get_fm();
338     i = akc6955_get_channel();
339     if(f != 0){ // 25KHz
340         freq = i * 2 + i / 2 + 3000; // freq' = 25*i[KHz] = (25 / 10) *i [10KHz]
341     } else { // 5K
342        b.byte = akc6955_readcmd(AKC6955_CH_HI);
343        band = akc6955_get_amband();
344        if((band == AKC6955_BAND_MW2) || (band == AKC6955_BAND_LW) || (b.b5)){
345            q = 3;
346        } else {
347            q = 5;
348        }
349        freq = i * q;
350     }
351     return freq;
352 }
353
354 void akc6955_set_freq(unsigned int freq)
355 {
356     unsigned int ch;
357     __bitops_t mode3k;
358     unsigned char band;
359     unsigned char q;
360     unsigned char f;
361
362     f = akc6955_get_fm();
363     if(f != 0) { // FM
364        band = akc6955_get_fmband();
365        //        band &= 7;
366        ch = ((freq - 3000) * 2) / 5;
367     } else {
368         band = akc6955_get_amband();
369         mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
370         if((band == AKC6955_BAND_MW2) || (band == AKC6955_BAND_LW) || (mode3k.b7)){
371             q = 3;
372             mode3k.b7 = 1;
373         } else {
374             q = 5;
375             mode3k.b7 = 0;
376         }
377         ch = freq / q;
378     }
379     akc6955_set_tune(mode3k.b7, ch);
380 }
381
382 void akc6955_set_userband(unsigned char start, unsigned char stop, unsigned int ch, unsigned char mode3k)
383 {
384     unsigned char f;
385
386     f = akc6955_get_fm();
387     akc6955_writecmd(AKC6955_UCH_ST, start);
388     akc6955_writecmd(AKC6955_UCH_EN, stop);
389     if(f != 0){
390         akc6955_set_fmband(AKC6955_BAND_FMUSER);
391     } else {
392         akc6955_set_amband(AKC6955_BAND_AMUSER);
393     }
394     akc6955_set_tune(mode3k, ch);
395 }
396
397
398 unsigned char akc6955_get_cnr(void)
399 {
400     unsigned char f;
401     __bitops_t b;
402     f = akc6955_get_fm();
403     if(f != 0) { // FM
404         b.byte = akc6955_readcmd(AKC6955_CNR_FM);
405     } else { // AM
406         b.byte = akc6955_readcmd(AKC6955_CNR_AM);
407     }
408     b.b7 = 0;
409     return b.byte;
410 }
411
412 int akc6955_read_level(void)
413 {
414     unsigned char f;
415     unsigned char rflevel, iflevel;
416     unsigned char b;
417     int rssi;
418     unsigned char band;
419     int totallevel;
420     int level;
421
422     f = akc6955_get_fm();
423     b =  akc6955_readcmd(AKC6955_PGALEVEL);
424     rflevel = (b & 0xe0) >> 5;
425     iflevel = (b & 0x1c) >> 2;
426     totallevel = rflevel + iflevel;
427
428     rssi = (int)(akc6955_readcmd(AKC6955_RSSI) & 0x7f);
429     level = (int)(totallevel * 6 + rssi);
430     if(f != 0){
431         level = 103 - level; // totallevel * 6
432     } else {
433         band = akc6955_get_amband();
434         if((band >= AKC6955_BAND_SW1) && (band <= AKC6955_BAND_AMUSER)) { // SW
435             level = 103 - level;
436         } else { //  MW,LW
437             level = 123 - level;
438         }
439     }
440     return level;
441 }
442
443
444 // Get diff. unit = 100Hz.
445 int akc6955_get_diff(void)
446 {
447     __bitops_t diff;
448     unsigned char f;
449     int n;
450
451     diff.byte = akc6955_readcmd(AKC6955_FDNUM);
452     if(diff.b7) {
453         diff.b7 = 0;
454         n = -((int) diff.byte);
455     } else {
456         diff.b7 = 0;
457         n = (int)diff.byte;
458     }
459
460     f = akc6955_get_fm();
461     if(f != 0) { // FM
462         return n * 10;
463     }
464     return n; // 10n
465 }
466
467 void akc6955_up_freq(unsigned int step)
468 {
469     unsigned int freq;
470 //    __bitops_t mode3k;
471     unsigned char mode3k;
472
473     freq = akc6955_get_channel();
474     freq += step;
475 //    mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
476 //    akc6955_set_tune(mode3k.b7, freq);
477     mode3k = akc6955_get_mode3k();
478     akc6955_set_tune(mode3k, freq);
479 }
480
481
482 void akc6955_down_freq(unsigned int step)
483 {
484     unsigned int freq;
485     unsigned char mode3k;
486
487     freq = akc6955_get_channel();
488     if(freq <= step) return;
489     freq -= step;
490 //    mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
491     mode3k = akc6955_get_mode3k();
492     akc6955_set_tune(mode3k, freq);
493 }
494
495 void akc6955_setvolumemode(unsigned char flag)
496 {
497     __bitops_t c;
498     c.byte = akc6955_readcmd(AKC6955_ENABLE);
499     c.b3 = 0;
500     if(flag != 0x00){
501         c.b3 = 1;
502     }
503     akc6955_writecmd(AKC6955_ENABLE, c.byte);
504 }
505
506 unsigned char akc6955_getvolumemode(void)
507 {
508     __bitops_t c;
509     c.byte = akc6955_readcmd(AKC6955_ENABLE);
510     if(c.b3){
511         return 0xff;
512     }
513     return 0;
514 }
515
516 void akc6955_setvolume(unsigned char level)
517 {
518 //    unsigned char c;
519 //    c = akc6955_readcmd(AKC6955_VOLUME) & 0x03;
520     if(level > 63) level = 63;
521     akc6955_writecmd(AKC6955_VOLUME, ((akc6955_readcmd(AKC6955_VOLUME) & 0x03) | (level << 2)));
522 }
523
524 unsigned char akc6955_getvolume(void)
525 {
526     unsigned char c;
527     c = akc6955_readcmd(AKC6955_VOLUME) >> 2;
528     return c;
529 }
530
531 void akc6955_set_prevolume(unsigned char level)
532 {
533     unsigned char c;
534     c = akc6955_readcmd(AKC6955_PRE) & 0xf3;
535     c |= ((level & 0x03) << 2);
536     akc6955_writecmd(AKC6955_PRE, c);
537 }
538
539 unsigned char akc6955_get_prevolume(void)
540 {
541     unsigned char c;
542 //    c = akc6955_readcmd(AKC6955_PRE) & 0x0c;
543  //   c >>= 2;
544     return (akc6955_readcmd(AKC6955_PRE) & 0x0c) >> 2;
545 }
546
547
548 void akc6955_setphase(unsigned char flag)
549 {
550     __bitops_t c;
551     c.byte = akc6955_readcmd(AKC6955_VOLUME);
552
553     c.b0 = 1;
554     if(flag == 0) {
555         c.b0 = 0; //
556     }
557     akc6955_writecmd(AKC6955_VOLUME, c.byte);
558 }
559
560 void akc6955_setline(unsigned char flag)
561 {
562     __bitops_t c;
563     c.byte = akc6955_readcmd(AKC6955_VOLUME);
564     c.b1 = 1;
565     if(flag == 0) {
566         c.b1 = 0;
567     }
568     akc6955_writecmd(AKC6955_VOLUME, c.byte);
569 }
570
571 void akc6955_set_lowboost(unsigned char flag)
572 {
573     __bitops_t c;
574     c.byte = akc6955_readcmd(AKC6955_STEREO);
575     c.b3 = 1;
576     if(flag == 0) {
577         c.b3 = 0;
578     }
579     akc6955_writecmd(AKC6955_STEREO, c.byte);
580 }
581
582 void akc6955_set_stereomode(unsigned char mode)
583 {
584     unsigned char c;
585     c = akc6955_readcmd(AKC6955_STEREO);
586     mode = (mode & 0x03) << 2;
587     c = (c & 0xf3) | mode;
588     akc6955_writecmd(AKC6955_STEREO, c);
589 }
590
591 unsigned char akc6955_get_stereo(void)
592 {
593  //   unsigned char c;
594 //    c = akc6955_readcmd(AKC6955_RCH_HI) & 0x80;
595     return akc6955_readcmd(AKC6955_RCH_HI) & 0x80;
596 }
597
598 /*
599  * Get battery level.
600  * Unit = 0.01V
601  */
602
603 unsigned int akc6955_get_battery(void)
604 {
605     unsigned int batt;
606     unsigned char c;
607     c = akc6955_readcmd(AKC6955_VBAT) & 0x3f;
608     batt = 180 + c * 5;
609     return batt;
610 }
611
612 /*
613  * Misc
614  */
615 void akc6955_set_fmbandwidth(unsigned char bw)
616 {
617    unsigned char c = akc6955_readcmd(AKC6955_STEREO);
618    c = (c & 0xfc) | (bw & 0x03);
619    akc6955_writecmd(AKC6955_STEREO, c);
620 }
621
622 unsigned char akc6955_get_fmbandwidth(void)
623 {
624     return (akc6955_readcmd(AKC6955_STEREO) & 0x03);
625 }
626
627
628
629 void akc6955_set_thresh_fmstereo(unsigned char a)
630 {
631     unsigned char b;
632     a = a & 0x03;
633     setup.threshold_fmstereo = a;
634     b = akc6955_readcmd(AKC6955_THRESH) & 0xfc;
635     akc6955_writecmd(AKC6955_THRESH, a | b);
636 }
637
638 void akc6955_set_thresh_width(unsigned char a)
639 {
640     unsigned char b;
641     a = a & 0x03;
642     setup.threshold_width = a;
643     a = a << 2; // << 2
644     b = akc6955_readcmd(AKC6955_THRESH) & 0xf3;;
645     akc6955_writecmd(AKC6955_THRESH, a | b);
646 }
647
648 void akc6955_set_thresh_amcnr(unsigned char a)
649 {
650     unsigned char b;
651     a = a & 0x03;
652     setup.threshold_amcnr = a;
653     a = a << 4; // << 4
654     b = akc6955_readcmd(AKC6955_THRESH) & 0xcf;
655     akc6955_writecmd(AKC6955_THRESH, a | b);
656 }
657
658 void akc6955_set_thresh_fmcnr(unsigned char a)
659 {
660     unsigned char b;
661     a = a & 0x03;
662     setup.threshold_fmcnr = a;
663     a = a << 6; // << 4
664     b = akc6955_readcmd(AKC6955_THRESH) & 0x3f;
665     akc6955_writecmd(AKC6955_THRESH, a | b);
666 }