OSDN Git Service

[Backlight] Split I/O routine related backlight to backlight.[c|h].
[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
44
45 void akc6955_chg_fm(unsigned char f, unsigned int freq)
46 {
47     __bitops_t b;
48     b.byte = akc6955_readcmd(AKC6955_POWER);
49     b.b6 = 0;
50     if(f != 0){
51         b.b6 = 1;
52         akc6955_set_fmband(setup.fmband);
53         akc6955_writecmd(AKC6955_POWER, b.byte);
54         akc6955_set_freq(freq);
55         return;
56     }
57     akc6955_writecmd(AKC6955_POWER, b.byte);
58     akc6955_set_amband(setup.amband);
59     akc6955_set_freq(freq);
60
61 }
62
63 unsigned char akc6955_get_fm(void)
64 {
65     __bitops_t b;
66     b.byte = akc6955_readcmd(AKC6955_POWER);
67     if(b.b6){
68         return 0xff;
69     }
70     return 0;
71 }
72
73
74 void akc6955_set_amband(unsigned char band)
75 {
76     unsigned char b;
77     unsigned char c;
78
79     c = RFAMP_SW;
80     if((band < AKC6955_BAND_SW1) || (band == AKC6955_BAND_MW4)) {
81         c = RFAMP_MWLW;
82     }
83     rfamp_power(c);
84     b = akc6955_readcmd(AKC6955_BAND);
85     b &= 0x07; // extract FM
86     b = b | ((band & 0x1f) << 3);
87     akc6955_writecmd(AKC6955_BAND, b);
88     akc6955_do_tune();
89 }
90
91 void akc6955_set_fmband(unsigned char band)
92 {
93     unsigned char b;
94     rfamp_power(RFAMP_FM);
95     b = akc6955_readcmd(AKC6955_BAND);
96     b &= 0xf8; // extract AM
97     b = b | (band & 0x07);
98     akc6955_writecmd(AKC6955_BAND, b);
99     akc6955_do_tune();
100 }
101
102 unsigned char akc6955_get_band(void)
103 {
104     return akc6955_readcmd(AKC6955_BAND);
105 }
106
107
108 void akc6955_set_power(unsigned char on)
109 {
110     __bitops_t b;
111     b.byte = akc6955_readcmd(AKC6955_POWER);
112     b.b7 = 0;
113     if(on != 0){
114         b.b7 = 1;
115     }
116     akc6955_writecmd(AKC6955_POWER, b.byte);
117 }
118
119 void akc6955_do_tune(void)
120 {
121     __bitops_t b;
122     b.byte = akc6955_readcmd(AKC6955_POWER);
123     b.b5 = 0; // Tun = '0'
124     b.b4 = 0; // Force abort scan.
125     akc6955_writecmd(AKC6955_POWER, b.byte);
126     idle_time_ms(1);
127     // Need sleep?-> Need! this sequence re                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 fer from reference code.
128     b.b5= 1; // Tun = '1'
129     akc6955_writecmd(AKC6955_POWER, b.byte);
130     idle_time_ms(1);
131     b.b5 = 0;
132     akc6955_writecmd(AKC6955_POWER, b.byte);
133     idle_time_ms(8);
134 }
135
136 unsigned char akc6955_tune(void)
137 {
138     __bitops_t b;
139     b.byte = akc6955_readcmd(AKC6955_RCH_HI);
140     if(b.b5) {
141         return 0xff;
142     }
143     return 0;
144 }
145
146
147 void akc6955_mode3k(unsigned char flag)
148 {
149     __bitops_t b;
150     b.byte = akc6955_readcmd(AKC6955_CH_HI);
151     b.b5 = 0;
152     if(flag != 0){
153         b.b5 = 1;
154     }
155     akc6955_writecmd(AKC6955_CH_HI, b.byte);
156     akc6955_do_tune();
157     _AKC6955_WAIT_62_5MS();
158 }
159
160 void akc6955_set_tune(unsigned char mode_3k, unsigned int ch)
161 {
162     unsigned char band;
163     __bitops_t f;
164     __bitops_t b;
165     unsigned int i = ch;
166     unsigned char comp;
167
168     do { // Wait for before completed
169         comp = akc6955_chk_donescan();
170         idle_time_35ms();
171     } while(comp == 0x00);
172     f.byte = akc6955_readcmd(AKC6955_POWER);
173     band = 0;
174     if(!f.b6){
175         akc6955_get_amband(band);
176     }
177
178     if(band == AKC6955_BAND_MW2){
179         // BAND=AM && MW2
180         i = ch / 3; // On MW2, Channnel must be multiple of 3.
181         i = i * 3; // i = (i/3) * 3
182     }
183     if(i > 0x1fff) i = 0x1fff;
184     //i = ch & 0x1fff;
185
186     b.byte = i & 0xff;
187     akc6955_writecmd(AKC6955_CH_LO, b.byte);
188
189     b.byte = i >> 8;
190     b.b6 = 1;
191     if(mode_3k != 0){
192         b.b5 = 1; // Mode 3K ON
193     }
194     akc6955_writecmd(AKC6955_CH_HI, b.byte);
195
196     akc6955_do_tune();
197 }
198
199 void akc6955_do_scan(unsigned char up)
200 {
201     __bitops_t b;
202
203     //20130823 Need wait for scan/tune completed w/o SDCC 3.3.x.
204 #ifndef __SDCC
205     while(akc6955_chk_donescan() == 0)
206     {
207         idle_time_ms(5);
208     }
209 #endif
210     b.byte = akc6955_readcmd(AKC6955_POWER);
211     b.b3 = 0;
212     b.b4 = 0;
213 // 20130823 : Is this collect?
214 #ifdef __SDCC
215      b.b5 = 0;
216     akc6955_writecmd(AKC6955_POWER, b.byte);
217     idle_time_ms(35);
218 #endif
219
220     b.b5 = 1; // Tune 0->1.
221     akc6955_writecmd(AKC6955_POWER, b.byte);
222     idle_time_ms(35);
223
224     b.b4 = 1;
225     if(up != 0) {
226         b.b3= 1;
227     }
228     akc6955_writecmd(AKC6955_POWER, b.byte); // Raise seek bit to '1'.
229     idle_time_ms(35);
230 }
231
232 void akc6955_abort_scan(void)
233 {
234     unsigned char b;
235     b = akc6955_readcmd(AKC6955_POWER);
236     b &= 0xef;
237     akc6955_writecmd(AKC6955_POWER, b); // Falldown seek bit to '0'.
238 }
239
240 void akc6955_set_scanrate_fm(unsigned char rate)
241 {
242     unsigned char c;
243     c = akc6955_readcmd(AKC6955_SPACE);
244     c = (c & 0xcf) | ((rate & 0x03) << 4);
245     akc6955_writecmd(AKC6955_SPACE, c);
246 }
247
248 unsigned char akc6955_chk_donescan(void)
249 {
250     __bitops_t b;
251     b.byte = akc6955_readcmd(AKC6955_RCH_HI);
252     if(b.b6){
253         return 0xff;
254     }
255     return 0;
256 }
257
258 unsigned int akc6955_get_channel(void)
259 {
260     unsigned char h, l;
261     unsigned int u;
262     l = akc6955_readcmd(AKC6955_RCH_LO) ;
263     h = akc6955_readcmd(AKC6955_RCH_HI) & 0x1f;
264     u = (h << 8) | l;
265     return u;
266 }
267
268 /*
269  * Get AM/FM Frequency: ret = KHz at AM, 10KHz @FM.
270  */
271 unsigned int akc6955_get_freq(void)
272 {
273     __bitops_t f, b;
274     unsigned int i;
275     unsigned int freq;
276     unsigned char band;
277
278     f.byte = akc6955_readcmd(AKC6955_POWER);
279     i = akc6955_get_channel();
280     if(f.b6){ // 25KHz
281         freq = (i * 5) / 2 + 3000; // freq' = 25*i[KHz] = (25 / 10) *i [10KHz]
282     } else { // 5K
283        b.byte = akc6955_readcmd(AKC6955_CH_HI);
284        akc6955_get_amband(band);
285        freq = i * 5;
286        if((band == AKC6955_BAND_MW2) || (b.b5)){
287            freq = i * 3;
288        }
289     }
290     return freq;
291 }
292
293 void akc6955_set_freq(unsigned int freq)
294 {
295     unsigned int ch;
296     __bitops_t f;
297     __bitops_t mode3k;
298     unsigned char band;
299     unsigned int start, stop;
300
301     f.byte = akc6955_readcmd(AKC6955_POWER);
302     if(f.b6) { // FM
303         akc6955_get_fmband(band);
304 //        band &= 7;
305         if(band == AKC6955_BAND_FMUSER){
306             start = setup.fm_usrbands[setup.fm_userbandnum].start * 32;
307             stop = setup.fm_usrbands[setup.fm_userbandnum].stop * 32;
308         } else {
309             start = fmbands[band].start;
310             stop = fmbands[band].end;
311         }
312         ch = freq - 3000;
313         ch = (ch << 2) / 10;
314     } else {
315         akc6955_get_amband(band);
316 //        if(band >= AKC6955_BAND_AMEND) band = AKC6955_BAND_AMEND - 1;
317         if(band == AKC6955_BAND_AMUSER){
318             start = setup.am_usrbands[setup.am_userbandnum].start * 32;
319             stop = setup.am_usrbands[setup.am_userbandnum].stop * 32;
320         } else {
321             start = ambands[band].start;
322             stop = ambands[band].end;
323         }
324         mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
325         if(band == AKC6955_BAND_MW2) {
326             ch = (freq / 9) * 3; // See datasheet.
327         } else if(band == AKC6955_BAND_MW3) {
328             ch = freq / 5;
329         } else  if(mode3k.b7){
330             ch = freq / 3;
331         } else {
332             ch = freq / 5;
333         }
334     }
335     if(freq <  start) freq = start;
336     if(freq >= stop)   freq = stop - 1;
337     akc6955_set_tune(mode3k.b7, ch);
338 }
339
340 void akc6955_set_userband(unsigned char start, unsigned char stop, unsigned int ch, unsigned char mode3k)
341 {
342     __bitops_t f;
343
344     f.byte = akc6955_readcmd(AKC6955_POWER);
345     akc6955_writecmd(AKC6955_UCH_ST, start);
346     akc6955_writecmd(AKC6955_UCH_EN, stop);
347     if(f.b6){
348         akc6955_set_fmband(AKC6955_BAND_FMUSER);
349     } else {
350         akc6955_set_amband(AKC6955_BAND_AMUSER);
351     }
352     akc6955_set_tune(mode3k, ch);
353 }
354
355
356 unsigned char akc6955_get_cnr(void)
357 {
358     __bitops_t f;
359     __bitops_t b;
360     f.byte = akc6955_readcmd(AKC6955_POWER);
361     if(f.b6) { // FM
362         b.byte = akc6955_readcmd(AKC6955_CNR_FM);
363     } else { // AM
364         b.byte = akc6955_readcmd(AKC6955_CNR_AM);
365     }
366     b.b7 = 0;
367     return b.byte;
368 }
369
370 int akc6955_read_level(void)
371 {
372     __bitops_t f;
373     unsigned char rflevel, iflevel;
374     unsigned char b;
375     int rssi;
376     unsigned int freq;
377     int totallevel;
378     int level;
379
380     f.byte = akc6955_readcmd(AKC6955_POWER);
381     b =  akc6955_readcmd(AKC6955_PGALEVEL);
382     rflevel = (b & 0xe0) >> 5;
383     iflevel = (b & 0x1c) >> 2;
384     totallevel = rflevel + iflevel;
385
386     rssi = (int)(akc6955_readcmd(AKC6955_RSSI) & 0x7f);
387     // totallevel = rssi + 6*totallevel;
388     level = (int)(totallevel * 6 + rssi);
389     if(f.b6){
390         level = 103 - level; // totallevel * 6
391     } else {
392         freq = akc6955_get_freq();
393         if(freq > 2560) { // ASSUME SW
394             level = 103 - level;
395         } else { // ASSUME MW,LW
396             level = 123 - level;
397         }
398     }
399     return level;
400 }
401
402
403 // Get diff. unit = 100Hz.
404 int akc6955_get_diff(void)
405 {
406     __bitops_t diff;
407     __bitops_t f;
408     int n;
409
410     diff.byte = akc6955_readcmd(AKC6955_FDNUM);
411     if(diff.b7) {
412         diff.b7 = 0;
413         n = -((int) diff.byte);
414     } else {
415         diff.b7 = 0;
416         n = (int)diff.byte;
417     }
418
419     f.byte = akc6955_readcmd(AKC6955_POWER);
420     if(f.b6) { // FM
421         return n * 10;
422     }
423     return n; // 10n
424 }
425
426 void akc6955_up_freq(unsigned int step)
427 {
428     unsigned int freq;
429     __bitops_t mode3k;
430
431     freq = akc6955_get_channel();
432     freq += step;
433     mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
434     akc6955_set_tune(mode3k.b7, freq);
435 }
436
437
438 void akc6955_down_freq(unsigned int step)
439 {
440     unsigned int freq;
441     __bitops_t mode3k;
442
443     freq = akc6955_get_channel();
444     if(freq <= step) return;
445     freq -= step;
446     mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
447     akc6955_set_tune(mode3k.b7, freq);
448 }
449
450 void akc6955_setvolumemode(unsigned char flag)
451 {
452     __bitops_t c;
453     c.byte = akc6955_readcmd(AKC6955_ENABLE);
454     c.b3 = 0;
455     if(flag != 0x00){
456         c.b3 = 1;
457     }
458     akc6955_writecmd(AKC6955_ENABLE, c.byte);
459 }
460
461 unsigned char akc6955_getvolumemode(void)
462 {
463     __bitops_t c;
464     c.byte = akc6955_readcmd(AKC6955_ENABLE);
465     if(c.b3){
466         return 0xff;
467     }
468     return 0;
469 }
470
471 void akc6955_setvolume(unsigned char level)
472 {
473 //    unsigned char c;
474 //    c = akc6955_readcmd(AKC6955_VOLUME) & 0x03;
475     if(level > 63) level = 63;
476     akc6955_writecmd(AKC6955_VOLUME, ((akc6955_readcmd(AKC6955_VOLUME) & 0x03) | (level << 2)));
477 }
478
479 unsigned char akc6955_getvolume(void)
480 {
481     unsigned char c;
482     c = akc6955_readcmd(AKC6955_VOLUME) >> 2;
483     return c;
484 }
485
486 void akc6955_set_prevolume(unsigned char level)
487 {
488     unsigned char c;
489     c = akc6955_readcmd(AKC6955_PRE) & 0xf3;
490     c |= ((level & 0x03) << 2);
491     akc6955_writecmd(AKC6955_PRE, c);
492 }
493
494 unsigned char akc6955_get_prevolume(void)
495 {
496     unsigned char c;
497     c = akc6955_readcmd(AKC6955_PRE) & 0x0c;
498     c >>= 2;
499     return c;
500 }
501
502
503 void akc6955_setphase(unsigned char flag)
504 {
505     __bitops_t c;
506     c.byte = akc6955_readcmd(AKC6955_VOLUME);
507
508     c.b0 = 1;
509     if(flag == 0) {
510         c.b0 = 0; //
511     }
512     akc6955_writecmd(AKC6955_VOLUME, c.byte);
513 }
514
515 void akc6955_setline(unsigned char flag)
516 {
517     __bitops_t c;
518     c.byte = akc6955_readcmd(AKC6955_VOLUME);
519     c.b1 = 1;
520     if(flag == 0) {
521         c.b1 = 0;
522     }
523     akc6955_writecmd(AKC6955_VOLUME, c.byte);
524 }
525
526 void akc6955_set_lowboost(unsigned char flag)
527 {
528     __bitops_t c;
529     c.byte = akc6955_readcmd(AKC6955_STEREO);
530     c.b3 = 1;
531     if(flag == 0) {
532         c.b3 = 0;
533     }
534     akc6955_writecmd(AKC6955_STEREO, c.byte);
535 }
536
537 void akc6955_set_stereomode(unsigned char mode)
538 {
539     unsigned char c;
540     c = akc6955_readcmd(AKC6955_STEREO);
541     mode = (mode & 0x03) << 2;
542     c = (c & 0xf3) | mode;
543     akc6955_writecmd(AKC6955_STEREO, c);
544 }
545
546 unsigned char akc6955_get_stereo(void)
547 {
548     unsigned char c;
549     c = akc6955_readcmd(AKC6955_RCH_HI) & 0x80;
550     return c;
551 }
552
553 /*
554  * Get battery level.
555  * Unit = 0.01V
556  */
557
558 unsigned int akc6955_get_battery(void)
559 {
560     unsigned int batt;
561     unsigned char c;
562     c = akc6955_readcmd(AKC6955_VBAT) & 0x3f;
563     batt = 180 + c * 5;
564     return batt;
565 }
566
567 void akc6955_set_thresh_fmstereo(unsigned char a)
568 {
569     unsigned char b;
570     a = a & 0x03;
571     setup.threshold_fmstereo = a;
572     b = akc6955_readcmd(AKC6955_THRESH) & 0xfc;
573     akc6955_writecmd(AKC6955_THRESH, a | b);
574 }
575
576 void akc6955_set_thresh_width(unsigned char a)
577 {
578     unsigned char b;
579     a = a & 0x03;
580     setup.threshold_width = a;
581     a = a << 2; // << 2
582     b = akc6955_readcmd(AKC6955_THRESH) & 0xf3;;
583     akc6955_writecmd(AKC6955_THRESH, a | b);
584 }
585
586 void akc6955_set_thresh_amcnr(unsigned char a)
587 {
588     unsigned char b;
589     a = a & 0x03;
590     setup.threshold_amcnr = a;
591     a = a << 4; // << 4
592     b = akc6955_readcmd(AKC6955_THRESH) & 0xcf;
593     akc6955_writecmd(AKC6955_THRESH, a | b);
594 }
595
596 void akc6955_set_thresh_fmcnr(unsigned char a)
597 {
598     unsigned char b;
599     a = a & 0x03;
600     setup.threshold_fmcnr = a;
601     a = a << 6; // << 4
602     b = akc6955_readcmd(AKC6955_THRESH) & 0x3f;
603     akc6955_writecmd(AKC6955_THRESH, a | b);
604 }