OSDN Git Service

b3da2550ee4e968205b5de1acabcc7a9fe114538
[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_OFF, 19);
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 //    CLOSEASMASTER();
58 #else
59     OpenI2C(MASTER, SLEW_OFF);
60     StartI2C();
61     WriteI2C(0x20);
62     //delay1ktcy(8);
63     WriteI2C(reg);
64     //delay1ktcy(8);
65     WriteI2C(data);
66     //delay1ktcy(8);
67     StopI2C();
68  //   delay1ktcy(8);
69     CloseI2C();
70 //    CLOSEASMASTER();
71 #endif  //    i2c_idle();
72 //    delay1ktcy(8);
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_OFF, 19);
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(1);
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     if(f != 0){
129 //        b |= 0x40;
130         b.b6 = 1;
131     } else {
132         b.b6 = 0;
133     }
134     akc6955_writecmd(AKC6955_POWER, b.byte);
135 }
136
137 unsigned char akc6955_get_fm(void)
138 {
139     __bitops_t b;
140     b.byte = akc6955_readcmd(AKC6955_POWER);
141     if(b.b6){
142         return 0xff;
143     }
144     return 0;
145 }
146
147
148 void akc6955_set_amband(unsigned char band)
149 {
150     unsigned char b;
151     b = akc6955_readcmd(AKC6955_BAND);
152     b &= 0x07; // extract FM
153     b = b | ((band & 0x1f) << 3);
154     akc6955_writecmd(AKC6955_BAND, b);
155 }
156
157 void akc6955_set_fmband(unsigned char band)
158 {
159     unsigned char b;
160     b = akc6955_readcmd(AKC6955_BAND);
161     b &= 0xf8; // extract AM
162     b = b | (band & 0x07);
163     akc6955_writecmd(AKC6955_BAND, b);
164 }
165
166 unsigned char akc6955_get_amband(void)
167 {
168     unsigned char b;
169     b = akc6955_readcmd(AKC6955_BAND);
170     b = (b & 0xf8) >> 3;
171     return b;
172 }
173
174 unsigned char akc6955_get_fmband(void)
175 {
176     unsigned char b;
177     b = akc6955_readcmd(AKC6955_BAND);
178     b = b & 0x07;
179     return b;
180 }
181
182 #if 1
183 void akc6955_set_power(unsigned char on)
184 {
185     __bitops_t b;
186     b.byte = akc6955_readcmd(AKC6955_POWER);
187     if(on != 0){
188         b.b7 = 1;
189         b.b2 = 1;
190     } else {
191         b.b7 = 0;
192     }
193     akc6955_writecmd(AKC6955_POWER, b.byte);
194 }
195 #endif
196
197 void akc6955_do_tune(void)
198 {
199     __bitops_t b;
200     b.byte = akc6955_readcmd(AKC6955_POWER);
201     b.b5 = 0; // Tun = '0'
202     akc6955_writecmd(AKC6955_POWER, b.byte);
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 >> 8;
258     b.b6 = 1;
259     if(mode_3k != 0){
260         b.b5 = 1; // Mode 3K ON
261     }
262     akc6955_writecmd(AKC6955_CH_HI, b.byte);
263
264     b.byte = i & 0xff;
265     akc6955_writecmd(AKC6955_CH_LO, b.byte);
266     akc6955_do_tune();
267 }
268
269 void akc6955_do_scan(unsigned char up)
270 {
271     __bitops_t b;
272     akc6955_do_tune();
273     b.byte = akc6955_readcmd(AKC6955_POWER);
274     b.b3 = 0;
275     b.b4 = 0;
276     if(up != 0) {
277         b.b3= 1;
278     }
279     akc6955_writecmd(AKC6955_POWER, b.byte); // Falldown seek bit to '0'.
280     b.b4 = 1;
281     akc6955_writecmd(AKC6955_POWER, b.byte); // Raise seek bit to '1'.
282 }
283
284 void akc6955_abort_scan(void)
285 {
286     unsigned char b;
287     b = akc6955_readcmd(AKC6955_POWER);
288     b &= 0xef;
289     akc6955_writecmd(AKC6955_POWER, b); // Falldown seek bit to '0'.
290 }
291
292 void akc6955_set_scanrate_fm(unsigned char rate)
293 {
294     unsigned char c;
295     c = akc6955_readcmd(AKC6955_SPACE);
296     c = (c & 0xcf) | ((rate & 0x03) << 4);
297     akc6955_writecmd(AKC6955_SPACE, c);
298 }
299
300 unsigned char akc6955_chk_donescan(void)
301 {
302     unsigned char b;
303     b = akc6955_readcmd(AKC6955_RCH_HI) & 0x40;
304     return b;
305 }
306
307
308 /*
309  * Get AM/FM Frequency: ret = KHz at AM, 10KHz @FM.
310  */
311 unsigned int akc6955_get_freq(void)
312 {
313     unsigned char h, l;
314     __bitops_t f, b;
315     unsigned int i;
316     unsigned int freq;
317
318 //    b = akc6955_readcmd(AKC6955_CNR_AM) & 0x80;
319     l = akc6955_readcmd(AKC6955_RCH_LO) ;
320     h = akc6955_readcmd(AKC6955_RCH_HI) & 0x1f;
321     f.byte = akc6955_readcmd(AKC6955_POWER);
322     i = l + (h << 8);
323     if(f.b6){ // 25KHz
324         freq = (i * 5) / 2 + 3000; // freq' = 25*i[KHz] = (25 / 10) *i [10KHz]
325                                        // = 2.5i[10KHz]
326                                        // freq = freq' + 30MHz = freq' + 3000[10KHz]
327     } else { // 5K
328        b.byte = akc6955_readcmd(AKC6955_CH_HI);
329         if(b.b5) { // 5KHz
330            freq = i * 3; // freq = 5*i[KHz] = (4+1)*i[KHz]
331         } else { // 3KHz
332            freq = i * 5; // freq = 3i[KHz] = (2+1)i[KHz]
333         }
334     }
335     return freq;
336 }
337
338 void akc6955_set_freq(unsigned int freq)
339 {
340     unsigned int ch;
341     __bitops_t f;
342     __bitops_t mode3k;
343     unsigned char band;
344
345     f.byte = akc6955_readcmd(AKC6955_POWER);
346     if(f.b6) { // FM
347         band = akc6955_get_fmband();
348         if(freq <  fmbands[band].start) freq = fmbands[band].start;
349         if(freq >= fmbands[band].end)   freq = fmbands[band].end - 1;
350         ch = freq - 3000;
351         ch = (ch * 4) / 10;
352     } else {
353         band = akc6955_get_amband();
354         if(band >= AKC6955_BAND_AMEND) band = AKC6955_BAND_AMEND - 1;
355         if(freq <  ambands[band].start) freq = ambands[band].start;
356         if(freq >= ambands[band].end)   freq = ambands[band].end - 1;
357         mode3k.byte = akc6955_readcmd(AKC6955_CNR_AM);
358         if(mode3k.b7){
359             ch = freq / 3;
360         } else {
361             ch = freq / 5;
362         }
363     }
364     akc6955_set_tune(mode3k.byte, ch);
365 }
366
367 void akc6955_set_userband(unsigned char start, unsigned char stop, unsigned int ch, unsigned char mode3k)
368 {
369     __bitops_t f;
370
371     f.byte = akc6955_readcmd(AKC6955_POWER);
372     akc6955_writecmd(AKC6955_UCH_ST, start);
373     akc6955_writecmd(AKC6955_UCH_EN, stop);
374     if(f.b6){
375         akc6955_set_fmband(AKC6955_BAND_FMUSER);
376     } else {
377         akc6955_set_amband(AKC6955_BAND_AMUSER);
378     }
379     akc6955_set_tune(mode3k, ch);
380 }
381
382
383 unsigned char akc6955_get_cnr(void)
384 {
385     __bitops_t f;
386     __bitops_t b;
387     f.byte = akc6955_readcmd(AKC6955_POWER);
388     if(f.b6) { // FM
389         b.byte = akc6955_readcmd(AKC6955_CNR_FM);
390     } else { // AM
391         b.byte = akc6955_readcmd(AKC6955_CNR_AM);
392     }
393     b.b7 = 0;
394     return b.byte;
395 }
396
397 int akc6955_read_level(void)
398 {
399     __bitops_t f;
400     unsigned char rflevel, iflevel;
401     unsigned char b;
402     int rssi;
403     unsigned int freq;
404     int totallevel;
405     int level;
406
407     f.byte = akc6955_readcmd(AKC6955_POWER);
408     b =  akc6955_readcmd(AKC6955_PGALEVEL);
409     rflevel = (b & 0xe0) >> 5;
410     iflevel = (b & 0x1c) >> 2;
411     totallevel = rflevel + iflevel;
412
413     rssi = (int)(akc6955_readcmd(AKC6955_RSSI) & 0x7f);
414     // totallevel = rssi + 6*totallevel;
415     level = (int)(totallevel * 6 + rssi);
416     if(f.b6){
417         level = 103 - level; // totallevel * 6
418     } else {
419         freq = akc6955_get_freq();
420         if(freq > 2560) { // ASSUME SW
421             level = 103 - level;
422         } else { // ASSUME MW,LW
423             level = 123 - level;
424         }
425     }
426     return level;
427 }
428
429 // Get diff. unit = 100Hz.
430 int akc6955_get_diff(void)
431 {
432     __bitops_t diff;
433     __bitops_t f;
434     int n;
435
436     diff.byte = akc6955_readcmd(AKC6955_FDNUM);
437     if(diff.b7) {
438         diff.b7 = 0;
439         n = -((int) diff.byte);
440     } else {
441         diff.b7 = 0;
442         n = (int)diff.byte;
443     }
444
445     f.byte = akc6955_readcmd(AKC6955_POWER);
446     if(f.b6) { // FM
447         return n * 10;
448     }
449     return n; // 10n
450 }
451
452 unsigned int akc6955_up_freq(unsigned int step)
453 {
454     unsigned int freq;
455     __bitops_t f;
456     unsigned char band;
457
458     f.byte = akc6955_readcmd(AKC6955_POWER);
459     freq = akc6955_get_freq();
460     freq += step;
461     if(f.b6){
462         band = akc6955_get_fmband();
463         if(band >= AKC6955_BAND_FMEND) band = AKC6955_BAND_FMEND - 1;
464         if(freq >= fmbands[band].end) freq = fmbands[band].end - 1;
465     } else {
466         band = akc6955_get_amband();
467         if(band >= AKC6955_BAND_AMEND) band = AKC6955_BAND_AMEND - 1;
468         if(freq >= ambands[band].end) freq = ambands[band].end - 1;
469     }
470     akc6955_set_freq(freq);
471     return akc6955_get_freq();
472 }
473
474
475 unsigned int akc6955_down_freq(unsigned int step)
476 {
477     unsigned int freq;
478     __bitops_t f;
479     unsigned char band;
480
481     freq = akc6955_get_freq();
482     if(freq <= step) return freq;
483     freq -= step;
484
485     f.byte = akc6955_readcmd(AKC6955_POWER);
486     if(f.b6 == 0){
487         band = akc6955_get_amband();
488         if(band >= AKC6955_BAND_AMEND) band = AKC6955_BAND_AMEND - 1;
489         if(freq < ambands[band].start) freq = ambands[band].start;
490     } else {
491         band = akc6955_get_fmband();
492         if(band >= AKC6955_BAND_FMEND) band = AKC6955_BAND_FMEND - 1;
493         if(freq < fmbands[band].start) freq = fmbands[band].start;
494     }
495     akc6955_set_freq(freq);
496     return akc6955_get_freq();
497 }
498 void akc6955_setvolumemode(unsigned char flag)
499 {
500     __bitops_t c;
501     c.byte = akc6955_readcmd(AKC6955_ENABLE);
502     c.b7 = 0;
503     if(flag != 0x00){
504         c.b7 = 1;
505     }
506     akc6955_writecmd(AKC6955_ENABLE, c.byte);
507 }
508
509 unsigned char akc6955_getvolumemode(void)
510 {
511     __bitops_t c;
512     c.byte = akc6955_readcmd(AKC6955_ENABLE);
513     if(c.b3){
514         return 0xff;
515     }
516     return 0;
517 }
518
519 void akc6955_setvolume(unsigned char level)
520 {
521 //    unsigned char c;
522 //    c = akc6955_readcmd(AKC6955_VOLUME) & 0x03;
523     if(level > 63) level = 63;
524     akc6955_writecmd(AKC6955_VOLUME, ((akc6955_readcmd(AKC6955_VOLUME) & 0x03) | (level << 2)));
525 }
526
527 unsigned char akc6955_getvolume(void)
528 {
529     unsigned char c;
530     c = (akc6955_readcmd(AKC6955_VOLUME) & 0xfc) >> 2;
531     return c;
532 }
533
534 void akc6955_set_prevolume(unsigned char level)
535 {
536     unsigned char c;
537     c = akc6955_readcmd(AKC6955_PRE) & 0xf3;
538     c |= ((level & 0x03) << 2);
539     akc6955_writecmd(AKC6955_PRE, c);
540 }
541
542 unsigned char akc6955_get_prevolume(void)
543 {
544     unsigned char c;
545     c = akc6955_readcmd(AKC6955_PRE) & 0x0c;
546     c >>= 2;
547     return c;
548 }
549
550
551 void akc6955_setphase(unsigned char flag)
552 {
553     __bitops_t c;
554     c.byte = akc6955_readcmd(AKC6955_VOLUME);
555
556     c.b0 = 0;
557     if(flag != 0) {
558         c.b0 = 1; //
559     }
560     akc6955_writecmd(AKC6955_VOLUME, c.byte);
561 }
562
563 void akc6955_setline(unsigned char flag)
564 {
565     __bitops_t c;
566     c.byte = akc6955_readcmd(AKC6955_VOLUME);
567     c.b1 = 0;
568     if(flag != 0) {
569         c.b1 = 1;
570     }
571     akc6955_writecmd(AKC6955_VOLUME, c.byte);
572 }
573
574 void akc6955_set_lowboost(unsigned char flag)
575 {
576     __bitops_t c;
577     c.byte = akc6955_readcmd(AKC6955_STEREO);
578     c.b3 = 0;
579     if(flag != 0) {
580         c.b3 = 1;
581     }
582     akc6955_writecmd(AKC6955_STEREO, c.byte);
583 }
584
585 void akc6955_set_stereomode(unsigned char mode)
586 {
587     unsigned char c;
588     c = akc6955_readcmd(AKC6955_STEREO);
589     mode = (mode & 0x03) << 2;
590     c = (c & 0xf3) | mode;
591     akc6955_writecmd(AKC6955_STEREO, c);
592 }
593
594 unsigned char akc6955_get_stereo(void)
595 {
596     unsigned char c;
597     c = akc6955_readcmd(AKC6955_RCH_HI) & 0x80;
598     return c;
599 }
600
601 /*
602  * Get battery level.
603  * Unit = 0.01V
604  */
605
606 unsigned int akc6955_get_battery(void)
607 {
608     unsigned int batt;
609     unsigned char c;
610     c = akc6955_readcmd(AKC6955_VBAT) & 0x3f;
611     batt = 180 + c * 5;
612     return batt;
613 }
614