OSDN Git Service

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