Project sebelumnya klik disini, karena bahasa program yang di gunakan kurang di mengerti oleh pemula seperti saya, akhirnya browsing searching ketemu juga yang pakai arduino, googling aja CCB Master, nanti ketemu file .ino dan contoh projectnya, berikut dokumentasi untuk sementara, sambil di update terus projectnya di sela-sela kesibukan.
Copy sketch di bawah ini ke Arduino IDE
/*
The YST93x (YST936, YST939, etc.) is an AM/FM tuner module used on some cheap
Chinese home theaters and sound systems. It is made by a company named Winever
(http://www.winever.cn/) - and maybe some others. It is very cheap and of a
a reasonable quality. It is easy to find on eBay and Alibaba.com
The module is based on a Sanyo LC72131 PLL and a tuner IC. The tuner chip varies
from model to model: YST939 uses the Sanyo LA1823 (or clone) radio-on-chip and
YST936 uses a Chinese-branded "CS1000" tuner.
The PLL can communicate with a microcontroller via the Sanyo CCB bus, and have
5 I/O pins which controls the tuner:
PLL pin Direction Function
BO0 PLL -> Tuner Not used
BO1 PLL -> Tuner Band selector (0 = FM; 1 = AM)
BO2 PLL -> Tuner Mute / IF output (0 = Mute / IF counter mode
1 = Normal tuner mode)
BO3 PLL -> Tuner Audio mode (0 = Stereo; 1 = Mono)
BO4 PLL -> Tuner Not used
IO0 Tuner -> PLL Not used (pulled high. Reads "1")
IO1 Tuner -> PLL Stereo indicator (0 = Stereo; 1 = Mono)
Note: BO0 must be set to "0" for the tuner to output the IF signal to the PLL.
This means the tuner will have to be muted every time one want the PLL to count
the IF frequency.
YST93x module Pinout:
FM
Ant +------------------------+
+---| |- RDS out (not all models have this pin)
+---| |- Out-L
| YST93x |- GND
| |- Out-R
| |- VDD (12V)
| |
AM | |
Ant | |- DO
+---| |- CL
| | |- DI
| | |- CE
+---| |- GND
+------------------------+
YST93x to Arduino connections:
Arduino YST93x
A5 (DO) DI
A4 (CL) CL
A3 (DI) DO
A2 (CE) CE
GND GND
Note: This example uses an analog keypad with the following schematics:
A0
|
2k2 | 330R 620R 1k 3k3
VCC -----\/\/\---+---\/\/\---+---\/\/\---+---\/\/\-------+---\/\/\-----+
| | | | |
SCAN_UP UP DOWN SCAN_DOWN BAND
| | | | |
GND GND GND GND GND
X = keys (N.O.)
*/
#include <inttypes.h>
#include <LiquidCrystal.h>
#include <SanyoCCB.h>
// This example uses an analog 5-key keypad tied to A0
#define KEYPAD_PIN A0
// Keypad keys
#define KEY_BAND 5
#define KEY_SCAN_DOWN 4
#define KEY_DOWN 3
#define KEY_UP 2
#define KEY_SCAN_UP 1
#define KEY_NONE 0
// LC72131 IN1, byte 0
#define IN10_R3 7
#define IN10_R2 6
#define IN10_R1 5
#define IN10_R0 4
#define IN10_XS 3
#define IN10_CTE 2
#define IN10_DVS 1
#define IN10_SNS 0
// LC72131 IN2, byte 0
#define IN20_TEST2 7
#define IN20_TEST1 6
#define IN20_TEST0 5
#define IN20_IFS 4
#define IN20_DLC 3
#define IN20_TBC 2
#define IN20_GT1 1
#define IN20_GT0 0
// LC72131 IN2, byte 1
#define IN21_DZ1 7
#define IN21_DZ0 6
#define IN21_UL1 5
#define IN21_UL0 4
#define IN21_DOC2 3
#define IN21_DOC1 2
#define IN21_DOC0 1
#define IN21_DNC 0
// LC72131 IN2, byte 2
#define IN22_BO4 7
#define IN22_BO3 6
#define IN22_BO2 5
#define IN22_BO1 4
#define IN22_IO2 3
#define IN22_IO1 2
#define IN22_IOC2 1
#define IN22_IOC1 0
// LC72131 DO0, byte 0
#define DO0_IN2 7
#define DO0_IN1 6
#define DO0_UL 4
// For function YST93xSetMode
#define YST93x_MONO 1
#define YST93x_STEREO 2
#define YST93x_MUTE 3
#define YST93x_UNMUTE 4
#define YST93x_BAND_FM 5
#define YST93x_BAND_AM 6
// Acceptable IF frequency deviation window (for the PLL) when searching for radio stations
// You may need to tweek these values to have a reliable "scan" mode
#define FM_TUNED_WINDOW 180
#define AM_TUNED_WINDOW 20
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //RS,E,D4,D5,D6,D7
SanyoCCB ccb(A5, A4, A3, A2); // Pins: DO CL DI CE
byte pll_in1[3];
byte pll_in2[3];
// Initial frequencies
uint16_t FMFrequency = 880; // MHz * 10
uint16_t AMFrequency = 53; // KHZ / 10
uint8_t band = YST93x_BAND_FM;
uint8_t tuned = 0;
/************************************************\
* YST93xInit() *
* Initialize the PLL settings vectors with *
* parameters common to booth AM and FM modes *
\************************************************/
void YST93xInit() {
memset(pll_in1, 0, 3);
memset(pll_in2, 0, 3);
bitSet(pll_in2[0], IN20_IFS); // IF counter in normal mode
bitSet(pll_in2[1], IN21_UL0); // Phase error detection width = 0us
bitSet(pll_in2[2], IN22_BO2); // Mute off / normal tuner mode
bitSet(pll_in1[0], IN10_XS); // aktifkan jika menggunakan Xtal. frequency 7.2 Mhz, matikan jika pakai 4,5Mhz
}
/************************************************\
* YST93xSetMode() *
* Some predefined setups for the YST93x module *
\************************************************/
void YST93xSetMode(uint8_t mode) {
switch(mode) {
case YST93x_STEREO:
bitClear(pll_in2[2], IN22_BO3);
break;
case YST93x_MONO:
bitSet(pll_in2[2], IN22_BO3);
break;
case YST93x_MUTE:
bitClear(pll_in2[2], IN22_BO2);
break;
case YST93x_UNMUTE:
bitSet(pll_in2[2], IN22_BO2);
break;
case YST93x_BAND_FM:
band = YST93x_BAND_FM;
bitWrite(pll_in1[0], IN10_R0, 1); // Reference frequency = 50kHz
bitWrite(pll_in1[0], IN10_R3, 0); //
bitWrite(pll_in1[0], IN10_DVS, 1); // Programmable Divider divisor = 2
bitWrite(pll_in2[0], IN20_GT0, 0); // IF counter mesurement period = 32ms
bitWrite(pll_in2[0], IN20_GT1, 1); //
bitWrite(pll_in2[1], IN21_DZ0, 1); // Dead zone = DZB
bitWrite(pll_in2[1], IN21_DZ1, 0); //
bitWrite(pll_in2[2], IN22_BO1, 0); // FM mode
break;
case YST93x_BAND_AM:
band = YST93x_BAND_AM;
bitWrite(pll_in1[0], IN10_R0, 0); // Reference frequency = 10kHz
bitWrite(pll_in1[0], IN10_R3, 1); //
bitWrite(pll_in1[0], IN10_DVS, 0); // Programmable Divider divisor = 1
bitWrite(pll_in2[0], IN20_GT0, 1); // IF counter mesurement period = 8ms
bitWrite(pll_in2[0], IN20_GT1, 0); //
bitWrite(pll_in2[1], IN21_DZ0, 0); // Dead zone = DZC
bitWrite(pll_in2[1], IN21_DZ1, 1); //
bitWrite(pll_in2[2], IN22_BO1, 1); // AM mode
break;
}
ccb.write(0x82, pll_in1, 3);
ccb.write(0x92, pll_in2, 3);
}
/************************************************************\
* YST93xTune() *
* Set the tuner frequency and return 1 if it is tuned *
* or 0 otherwise. *
* *
* The frequency divisors was chosen in a way the frequency *
* representation can be directly sent to the PLL and is *
* easy to represent: *
* - FM mode (divisor = 100): frequency (MHz) * 10 *
* - AM mode (divisor = 10): frequency (kHZ) / 10 *
\************************************************************/
uint8_t YST93xTune(uint16_t frequency) {
uint16_t fpd = 0;
uint8_t i = 0;
uint8_t r[3];
unsigned long IFCounter = 0;
switch(band) {
case YST93x_BAND_FM:
// FM: fpd = (frequency + FI) / (50 * 2)
fpd = (frequency + 107);
break;
case YST93x_BAND_AM:
// AM: fpd = ((frequency + FI) / 10) << 4
fpd = (frequency + 45) << 4;
break;
default: return 1;
}
YST93xSetMode(YST93x_MUTE); // YST93x only injects FI signal into the PLL when in MUTE mode
// Reset the IF counter and program the Frequency Programmable Divider (fpd)
bitClear(pll_in1[0], IN10_CTE);
pll_in1[1] = byte(fpd >> 8);
pll_in1[2] = byte(fpd & 0x00ff);
ccb.write(0x82, pll_in1, 3);
// Start the IF counter
bitSet(pll_in1[0], IN10_CTE);
ccb.write(0x82, pll_in1, 3);
// Wait for PLL to be locked (DO0_UL == 1)
while(i < 20) {
delay(50);
ccb.read(0xa2, r, 3); // Discard the 1st result: it is latched from the last count (as said on the datasheet)
ccb.read(0xa2, r, 3); // The 20 rightmost bits from r[0..2] are the IF counter result
i = (bitRead(r[0], DO0_UL)) ? 100 : i + 1;
}
YST93xSetMode(YST93x_UNMUTE); // Mute off / normal tuner mode
if(i == 100) {
// PLL is locked. If the IF deviation is within the defined (window) interval,
// the radio is likely to be tuned.
// Note: this "tuned" detection method is not recommended on the LC72131 datasheet as
// it can give false positive results. A better approach would be to get the "tuned"
// flag from a RDS decoder with signal quality detection (e.g.: PT2579 or Philips SAA6588)
// connected to the YST93x tuner module "RDS Output" pin. SAA6588 is more powerful/popular,
// but PT2579 looks a lot easier to use as it is not programmable and has a dedicated
// signal quality output pin.
IFCounter = (r[0] & 0x0f);
IFCounter = (IFCounter << 16) | (unsigned long)(r[1] << 8) | (r[2]);
Serial.println(IFCounter);
// signal stop saat mode scan
switch(band) {
case YST93x_BAND_FM:
// Expected value: IF (10.7MHz) * Mesurement period (32ms, as set via GT[1..0]) = 342400
if((IFCounter > 342400) && ((IFCounter - 342400) < FM_TUNED_WINDOW)) return 1;
if((IFCounter < 342400) && ((342400 - IFCounter) < FM_TUNED_WINDOW)) return 1;
break;
case YST93x_BAND_AM:
// Expected value: IF (450kHz) * Mesurement period (8ms, as set via GT[1..0]) = 3600
// Note: scan mode in AM is really poor. I have done my best in tweaking it, but it barely works
if((IFCounter > 3600) && ((IFCounter - 3600) < AM_TUNED_WINDOW)) return 1;
if((IFCounter < 3600) && ((3600 - IFCounter) < AM_TUNED_WINDOW)) return 1;
break;
}
}
return 0;
}
/**************************************************\
* YST93xIsStereo() *
* Returns 1 if the tuned radio station is stereo *
\**************************************************/
uint8_t YST93xIsStereo() {
uint8_t r[3];
ccb.read(0xa2, r, 3);
return(bitRead(r[0], DO0_IN2) ? 0 : 1);
}
/*******************************************************\
* getKey() *
* Read the (analog) keypad. *
* If you are using an digital (one key per input pin) *
* keypad, just this function to return the correct *
* values *
\*******************************************************/
uint8_t getKey(uint8_t keypadPin) {
uint16_t keypad;
uint8_t key = KEY_NONE;
keypad = analogRead(keypadPin);
if(keypad < 870) key = KEY_BAND;
if(keypad < 600) key = KEY_SCAN_DOWN;
if(keypad < 390) key = KEY_DOWN;
if(keypad < 220) key = KEY_UP;
if(keypad < 60) key = KEY_SCAN_UP;
return key;
}
/*******************\
* Arduino setup() *
\*******************/
void setup() {
lcd.begin(16, 2);
Serial.begin(9600);
lcd.print(" -** OMRIN **- ");
ccb.init();
delay(1000);
YST93xInit();
YST93xSetMode(YST93x_BAND_FM);
tuned = YST93xTune(FMFrequency);
lcd.clear();
}
/******************\
* Arduino loop() *
\******************/
void loop() {
uint8_t scan = 0;
int8_t delta = 0;
uint8_t key = getKey(KEYPAD_PIN);
lcd.setCursor(0, 0);
switch(band) {
case YST93x_BAND_FM:
lcd.print("FM ");
lcd.setCursor((FMFrequency < 1000) ? 4 : 3, 0); lcd.print((float)FMFrequency / 10, 1);
lcd.print("MHz ");
break;
case YST93x_BAND_AM:
lcd.print("AM ");
lcd.setCursor((AMFrequency < 100) ? 4 : 3, 0); lcd.print(AMFrequency * 10);
lcd.print("KHz ");
break;
}
// Updates the Stereo indicator
lcd.setCursor(12, 0);
if(YST93xIsStereo())
lcd.print("[ST]");
else
lcd.print("[ ]");
// The "Tuned" indicator is updated only when the station changes
lcd.setCursor(2, 1);
if(tuned)
lcd.print(" Tuned ");
else
lcd.print(" ");
// Processo keypad inputs
if(key != KEY_NONE) {
switch(key) {
case KEY_UP: scan = 0; delta = +1; break;
case KEY_DOWN: scan = 0; delta = -1; break;
case KEY_SCAN_UP: scan = 1; delta = +1; break;
case KEY_SCAN_DOWN: scan = 1; delta = -1; break;
case KEY_BAND:
switch(band) {
case YST93x_BAND_FM:
YST93xSetMode(YST93x_BAND_AM);
tuned = YST93xTune(AMFrequency);
break;
case YST93x_BAND_AM:
YST93xSetMode(YST93x_BAND_FM);
tuned = YST93xTune(FMFrequency);
break;
}
}
if(scan) {
lcd.setCursor(2, 1);
lcd.print("Scanning...");
}
// Change the station
switch(band) {
case YST93x_BAND_FM:
do{
FMFrequency += delta;
if(FMFrequency > 1080) FMFrequency = 880;
if(FMFrequency < 880) FMFrequency = 1080;
tuned = YST93xTune(FMFrequency);
lcd.setCursor(3, 0);
if(FMFrequency < 1000) lcd.print(' ');
lcd.print((float)FMFrequency / 10, 1);
} while(scan && (! tuned));
break;
case YST93x_BAND_AM:
do{
AMFrequency += delta;
if(AMFrequency > 170) AMFrequency = 53;
if(AMFrequency < 53) AMFrequency = 170;
tuned = YST93xTune(AMFrequency);
lcd.setCursor(3, 0);
if(AMFrequency < 100) lcd.print(' ');
lcd.print(AMFrequency * 10);
} while(scan && (! tuned));
break;
} // switch
} // if(key)
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
Sketch di atas bisa di modifikasi sesuai kebutuhan, silahkan berkreasi sendiri.
di bawah ini menggunakan PCB yang di gabungkan dengan LC72131, control nya menggunakan Arduino Nano, untuk i/o langsung dari pin arduino nano, penambahan fitur mute saat mode scan, signal meter, indikator tune dan stereo.
menggunakan Arduino Nano untuk kontrolnya
Bagian Tuner/ Front End dan IF amplifier Stereo
Tampilan LCD di lengkapi indikator Stereo, Tune dan Signal Meter
Untuk Project selanjutnya di gabung dengan TX FM Rajawali..
Masih Proses melukis PCB, akan di update untuk progressnya...
mantab Om
BalasHapusAyo bikin om
Hapusom ada yg versi pake encoder ga yg buat tuning nya
BalasHapusAda om...
BalasHapusMantap
BalasHapuskl pin nya diganti 3 pin input gimna om
BalasHapus