OSDN Git Service

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