51单片机+TEF6686模块做收音机
·
在网上看到一款DP666彩屏收音机,内核用的ESP32驱动的TEF6686芯片,且TEF6686这款芯片在收音机圈子里都反应不错,FM灵敏度高,还有场强数据,RDS数据等各项功能,那咱们也用51做一个。

先去闲鱼买个TEF6686收音机高频头,回来画板做个转接板带功放,用STC8051单片机做主控。加按键和EC11旋转编码器,最终数据先串口打印出来,后续再加彩屏显示信息。





程序用了DeepSeek V4 AI模型给我整改,下来体验还不错,串口信息输出偶尔会停止,不过不影响,反正以后还要改成彩屏显示的。
以下是源码:
#include <STC8051U.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
#define s8 signed char
/*----------------------------- I2C pins -------------------------------*/
sbit I2C_SDA = P1^1;
sbit I2C_SCL = P1^0;
/*----------------------------- I2C addresses -------------------------*/
#define I2C_ADDR_WRITE 0xC8
#define I2C_ADDR_READ 0xC9
/*----------------------------- modules --------------------------------*/
#define MODULE_FM 0x20
#define MODULE_AM 0x21
#define MODULE_AUDIO 0x30
#define MODULE_APPL 0x40
/*----------------------------- commands -------------------------------*/
#define CMD_TUNE_TO 0x01
#define CMD_SET_TUNE_OPTIONS 0x02
#define CMD_SET_BANDWIDTH 0x0A
#define CMD_SET_RFAGC 0x0B
#define CMD_SET_RDS 0x51
#define CMD_SET_QUALITY_STATUS 0x52
#define CMD_GET_QUALITY_DATA 0x81
#define CMD_GET_RDS_STATUS 0x82
#define CMD_GET_RDS_DATA 0x83
#define CMD_GET_SIGNAL_STATUS 0x85
#define CMD_SET_VOLUME 0x0A
#define CMD_SET_MUTE 0x0B
#define CMD_SET_REFERENCE_CLOCK 0x04
#define CMD_ACTIVATE 0x05
/*----------------------------- bands / frequency ----------------------*/
#define BAND_FM 0
#define BAND_AM 1
#define FM_FREQ_MIN 8750 /* 87.50 MHz, 10 kHz units */
#define FM_FREQ_MAX 10800 /* 108.00 MHz */
#define FM_FREQ_STEP 10
#define AM_FREQ_MIN 522 /* 522 kHz, 1 kHz units */
#define AM_FREQ_MAX 1620 /* 1620 kHz */
#define AM_FREQ_STEP 9 /* CHN MW step */
/*----------------------------- tuning action modes --------------------*/
#define TUNE_MODE_PRESET 1
#define TUNE_MODE_SEARCH 2
#define TUNE_MODE_END 7
/*----------------------------- RDS ------------------------------------*/
#define RDS_PS_LEN 8
#define RDS_BCD(v) (unsigned char)((((v) >> 4) * 10) + ((v) & 0x0F))
/*----------------------------- keys ----------------------------------*/
sbit KEY_UP = P2^2;
sbit KEY_DOWN = P3^2;
sbit KEY_VOLUP = P2^1;
sbit KEY_VOLDN = P2^0;
sbit KEY_BAND = P5^6;
sbit KEY_MUTE = P5^7;
bit
KeySta0 = 1, //KEY0当前按键状态
KeySta1 = 1, //KEY1当前按键状态
KeySta2 = 1, //KEY2当前按键状态
KeySta3 = 1, //KEY3当前按键状态
KeySta4 = 1, //KEY4当前按键状态
KeySta5 = 1; //KEY5当前按键状态
bit
backup0 = 1, //KEY0按键值备份,保存前一次的扫描值
backup1 = 1, //KEY1按键值备份,保存前一次的扫描值
backup2 = 1, //KEY2按键值备份,保存前一次的扫描值
backup3 = 1, //KEY3按键值备份,保存前一次的扫描值
backup4 = 1, //KEY4按键值备份,保存前一次的扫描值
backup5 = 1; //KEY5按键值备份,保存前一次的扫描值
sbit EC11_A = P2^5;
sbit EC11_G = P2^6;
sbit EC11_B = P2^7;
u8 g_value = 0; /* 被调节的数值 */
u8 last_state = 0; /* 记录上一次的A、B相状态 */
void EC11_Scan(void);
s8 code EC11_Table[16] = {//EC11 状态转移表
0, -1, 1, 0, /* 上次状态 00 */
1, 0, 0, -1, /* 上次状态 01 */
-1, 0, 0, 1, /* 上次状态 10 */
0, 1, -1, 0 /* 上次状态 11 */
};
unsigned int SysTick=0;
uchar TEF6686_DAT[16];
typedef struct {
unsigned int pi; /* PI 码(来自 RDS 块 A) */
unsigned char ps[RDS_PS_LEN + 1]; /* 台名 PS,0 结尾 */
unsigned char rt[65]; /* 广播文本 RT,0 结尾 */
unsigned char ps_ready; /* 1 = 已收满 8 字符 */
unsigned char rt_ready; /* 1 = 已收满 64 字符 */
unsigned char pty; /* 节目类型 0..31 */
unsigned char ta; /* 交通公告标志 */
unsigned char tp; /* 交通节目标志 */
unsigned char ms; /* 音乐/语音(M=音乐 S=语音) */
unsigned char sync; /* RDS 同步锁定 */
unsigned char ecc; /* 扩展国家码(组 3A variant 0) */
unsigned char lic; /* 语言码低 2 位 */
unsigned char eon_pi_valid; /* EON 服务 PI 有效 */
unsigned int eon_pi; /* EON 服务 PI */
unsigned char af[16]; /* AF 频率码表(码 1..204) */
unsigned char af_count; /* AF 码数量 */
unsigned char rt_plus_valid; /* RT+ 信息有效 */
unsigned char rt_plus_type; /* RT+ 内容类型 0..63 */
unsigned char rt_plus_start; /* RT+ 起始位置(字符) */
unsigned char rt_plus_len; /* RT+ 长度(字符) */
unsigned char rt_plus_running; /* RT+ 运行标志 */
unsigned char ct_valid; /* 时钟时间有效 */
unsigned char ct_hour; /* 小时(BCD 已转十进制) */
unsigned char ct_min; /* 分钟 */
unsigned char ct_day; /* 日 */
unsigned char ct_month; /* 月 */
unsigned char ct_year; /* 年(低 2 位,非完整年份) */
unsigned int errA, errB, errC, errD; /* A..D 块错误计数 */
unsigned int groups; /* 收到的组数 */
} TEF6686_RDS;
/*------------------ 质量数据(0x81 返回 14 字节)---------------------*/
typedef struct {
unsigned int status; /* 质量时间戳 0.1ms,>0 表示调谐完成 */
int level; /* 场强 0.1 dBuV */
unsigned int usn; /* 超声噪声 0.1 %(仅 FM) */
unsigned int wam; /* 多径干扰 0.1 %(仅 FM) */
int offset; /* 中频偏移 0.1 kHz(有符号) */
unsigned int bandwidth; /* 中频带宽 0.1 kHz */
unsigned int modulation; /* 调制度 0.1 % */
} TEF6686_Quality;
/*----------------------------- prototypes -----------------------------*/
unsigned char TEF6686_Init(void);
unsigned char TEF6686_SetBand(unsigned char band);
unsigned char TEF6686_Tune(unsigned char band, unsigned int freq);
unsigned char TEF6686_SetVolume(int vol); /* dB, -60 .. +24 */
unsigned char TEF6686_Mute(unsigned char on);
unsigned char TEF6686_GetQualityData(unsigned char band, TEF6686_Quality *q);
unsigned char TEF6686_Seek(unsigned char band, unsigned char up);
unsigned char TEF6686_PollRDS(unsigned char band);
//TEF6686_RDS *TEF6686_GetRDS(void);
void I2C_Delay(void);
void TEF6686_DelayMs(unsigned int ms);
unsigned char code TEF6686_PatchByteValues[] = {
0xf0,0x00,0x38,0x2f,0xd0,0x80,0xf0,0x00,0x38,0x37,0xd0,0x80,0x43,0xb2,0x38,0x3a,
0xd0,0x80,0xf0,0x00,0x70,0x00,0xc2,0xf7,0xf0,0x00,0x38,0x6b,0xd0,0x80,0x80,0xfc,
0x39,0x0e,0xd0,0x80,0xf0,0x00,0x39,0x13,0xd0,0x80,0xf0,0x00,0x39,0x16,0xd0,0x80,
0xf0,0x00,0x39,0xbc,0xd0,0x80,0xf0,0x00,0x39,0x32,0xd0,0x80,0xf0,0x00,0x39,0xbe,
0xd0,0x80,0xc4,0xa2,0x02,0x11,0x60,0x04,0xf0,0x00,0x39,0x9a,0xd0,0x80,0x90,0x01,
0x39,0x34,0xd0,0x80,0xf0,0x00,0x38,0xf0,0xd0,0x80,0xf0,0x00,0x39,0x3b,0xd2,0x80,
0xf0,0x00,0x39,0x3f,0xd0,0x80,0xf0,0x00,0x39,0x49,0xd0,0x80,0xf0,0x00,0x39,0x4c,
0xd0,0x80,0x9e,0x30,0x18,0xf9,0xd2,0x80,0xf0,0x00,0x39,0x51,0xd0,0x80,0xf0,0x00,
0x39,0x54,0xd0,0x80,0xf0,0x00,0x39,0x57,0xd0,0x80,0x32,0x00,0x39,0x59,0xd0,0x80,
0xf0,0x00,0x39,0x5b,0xd0,0x80,0xa8,0x01,0x39,0xaa,0xd0,0x80,0xf0,0x00,0x39,0xc3,
0xd0,0x80,0xf0,0x00,0x39,0xc5,0xd0,0x80,0xf0,0x00,0x39,0xc7,0xd0,0x80,0xf0,0x00,
0x39,0xda,0xd0,0x80,0xf0,0x00,0x39,0xdd,0xd0,0x80,0xf0,0x00,0x39,0xe0,0xd0,0x80,
0xf0,0x00,0x39,0xe3,0xd0,0x80,0xf0,0x00,0x70,0x00,0xf0,0x00,0xf0,0x00,0x39,0xe8,
0xd0,0x80,0xf0,0x00,0x39,0xb5,0xd2,0x80,0xf0,0x00,0x39,0xf6,0xd0,0x80,0x00,0x43,
0x3a,0x05,0xd9,0x80,0xf0,0x00,0x3a,0x0f,0xd0,0x80,0xf0,0x00,0x3a,0x45,0xd0,0x80,
0xf0,0x00,0x3a,0x48,0xd0,0x80,0xf0,0x00,0x3a,0x59,0xd0,0x80,0x2e,0x40,0x3a,0xf8,
0xd0,0x80,0xf0,0x00,0x3b,0x02,0xd0,0x80,0xf0,0x00,0x0e,0x3f,0x60,0x00,0x50,0x10,
0x28,0xd8,0xd2,0x80,0x91,0x01,0x01,0x36,0x60,0x00,0xf0,0x00,0x70,0x00,0xa0,0x18,
0xf0,0x00,0x70,0x00,0xa0,0xd8,0xf0,0x00,0x70,0x00,0xa0,0xe8,0xf0,0x00,0x70,0x00,
0xa1,0x6f,0xf0,0x00,0x70,0x00,0xa1,0x99,0xf0,0x00,0x70,0x00,0xa1,0xc4,0xf0,0x00,
0x70,0x00,0xa1,0xdc,0xf0,0x00,0x20,0x31,0xd0,0x80,0xf0,0x00,0x04,0xc1,0x60,0x08,
0xf0,0x00,0x01,0x01,0xd2,0x80,0xf0,0x00,0x00,0x30,0xd0,0x80,0x00,0x7f,0x60,0x02,
0xe2,0x00,0xf0,0x00,0x0e,0x22,0x60,0x0a,0xf0,0x00,0x00,0xff,0x60,0x03,0xf0,0x00,
0x01,0x42,0xd2,0x80,0x90,0x03,0x40,0x02,0xf0,0x00,0x90,0x43,0x01,0x70,0xd1,0x80,
0xf0,0x00,0x01,0x69,0xd0,0x80,0x0e,0x69,0x60,0x0a,0xa2,0xc3,0x20,0x23,0x00,0x01,
0x60,0x01,0xf0,0x00,0x70,0x00,0xf0,0x00,0xc4,0xcb,0x70,0x00,0xf0,0x00,0xca,0x09,
0x30,0x23,0xf0,0x00,0xc2,0xcb,0x70,0x00,0xf0,0x00,0xf0,0x00,0x30,0x23,0xd0,0x08,
0x82,0x00,0x0d,0x50,0x60,0x08,0xf0,0x00,0x0d,0x51,0x60,0x09,0x30,0x00,0x21,0x80,
0x60,0x01,0xf0,0x00,0x40,0x32,0xf0,0x00,0x30,0x11,0x45,0xf3,0xf0,0x00,0x30,0x92,
0x2d,0x30,0x60,0x04,0x31,0x13,0x2d,0x40,0x60,0x05,0x31,0x94,0x7f,0xff,0x60,0x06,
0x32,0x15,0x0d,0x61,0x60,0x0a,0x32,0x96,0x0d,0x6b,0x60,0x0b,0x33,0x10,0x0d,0x50,
0x60,0x01,0x33,0x90,0x0d,0x5c,0x60,0x02,0x30,0x21,0x0d,0x63,0x60,0x03,0x30,0x31,
0x0d,0x75,0x60,0x0c,0x30,0xa2,0x8d,0x00,0x60,0x01,0x30,0xb3,0x01,0x73,0x60,0x02,
0x30,0x41,0x00,0x25,0x60,0x03,0x30,0xc2,0x40,0x44,0xf0,0x00,0x31,0x43,0x40,0x35,
0xf0,0x00,0x31,0xc4,0x64,0x00,0x60,0x06,0x32,0x45,0x1f,0x40,0x60,0x07,0x32,0xc6,
0x70,0x00,0xf0,0x00,0x33,0x47,0x1e,0xbc,0x60,0x0d,0x33,0xc0,0x01,0x22,0x60,0x01,
0x34,0x40,0xfd,0xee,0x60,0x02,0x30,0x51,0x7b,0x8f,0x60,0x03,0x30,0xd2,0xc4,0x29,
0x60,0x04,0x31,0x51,0x1e,0xc2,0x60,0x0e,0x32,0x53,0xff,0x0d,0x60,0x02,0x32,0xd4,
0x7d,0x2e,0x60,0x03,0x30,0x61,0xc1,0x9a,0x60,0x04,0x30,0xe2,0x70,0x00,0xf0,0x00,
0x31,0x61,0x70,0x00,0xf0,0x00,0x32,0x63,0x70,0x00,0xf0,0x00,0x32,0xe4,0x70,0x00,
0xd0,0x08,0xf0,0x00,0x03,0x70,0xd2,0x80,0xf0,0x00,0x70,0x00,0xa0,0x02,0xf0,0x00,
0x70,0x00,0xa0,0x59,0xf0,0x00,0x02,0x15,0xd0,0x80,0xf0,0x00,0x0d,0x51,0x60,0x0f,
0xf0,0x00,0x05,0x17,0x60,0x0e,0x23,0xf6,0x70,0x00,0xf0,0x00,0xf0,0x00,0x21,0x63,
0x41,0xf5,0x91,0x8f,0x21,0xf8,0x40,0x74,0xc3,0xef,0x21,0xe0,0xf0,0x00,0xc3,0xa4,
0x33,0xf7,0xf0,0x00,0xd8,0x5b,0x70,0x00,0xf0,0x00,0x82,0x18,0x70,0x00,0xf0,0x00,
0x9f,0xaf,0x18,0x00,0xf0,0x00,0x9f,0x0f,0x31,0xf8,0x90,0x02,0xf0,0x00,0x70,0x00,
0x90,0x28,0xf0,0x00,0x70,0x00,0xd0,0x08,0xf0,0x00,0x22,0x78,0xf0,0x00,0x16,0xd3,
0x60,0x09,0xa0,0x7f,0x35,0xf0,0x1e,0xbc,0x60,0x0d,0xf0,0x00,0x0d,0x61,0x60,0x08,
0xf0,0x00,0x03,0xa5,0xd2,0x80,0xf0,0x00,0x1e,0xc2,0x60,0x0d,0xf0,0x00,0x0d,0x6b,
0x60,0x08,0xf0,0x00,0x03,0xa5,0xd2,0x80,0xf0,0x00,0x21,0x00,0xf0,0x00,0x83,0x6d,
0x22,0xf1,0xf0,0x00,0xf0,0x00,0x23,0x77,0xf0,0x00,0x90,0x41,0x36,0x70,0xf0,0x00,
0x9e,0x79,0x70,0x00,0x90,0x01,0xf0,0x00,0x32,0xf1,0xd0,0x08,0x91,0xc7,0x33,0x75,
0xf0,0x00,0xf0,0x00,0x34,0x70,0xe6,0x00,0xf0,0x00,0x34,0xf0,0xe6,0x00,0xf0,0x00,
0x24,0x74,0xf0,0x00,0xf0,0x00,0x24,0xf3,0xf0,0x00,0x8c,0x24,0x26,0xf2,0x40,0x16,
0x8a,0x1b,0x34,0x74,0x4f,0xf5,0x82,0xb7,0x34,0xf3,0xf0,0x00,0xf0,0x00,0x20,0x71,
0x90,0x05,0x83,0x04,0x70,0x00,0xf0,0x00,0x8e,0x67,0x70,0x00,0xf0,0x00,0xf0,0x00,
0x70,0x00,0x90,0x02,0xf0,0x00,0x36,0xf6,0xf0,0x00,0xf0,0x00,0x34,0xf0,0x80,0x06,
0x82,0xaf,0x70,0x00,0xf0,0x00,0x82,0x1b,0x70,0x00,0xd0,0x09,0x8e,0x5f,0x70,0x00,
0xf0,0x00,0xf0,0x00,0x70,0x00,0xd0,0x09,0xf0,0x00,0x36,0xf5,0xf0,0x00,0xf0,0x00,
0x34,0x70,0xf0,0x00,0x40,0x11,0x27,0x72,0xa2,0x66,0x90,0x8a,0x20,0xf3,0xa2,0x65,
0x8e,0xd7,0x37,0x72,0xf0,0x00,0xf0,0x00,0x37,0xf1,0xe6,0x00,0xf0,0x00,0x70,0x00,
0xd0,0x08,0xf0,0x00,0x22,0x7a,0xf0,0x00,0x16,0xc3,0x60,0x09,0xa0,0x58,0xf0,0x00,
0x18,0x20,0xf0,0x00,0xf0,0x00,0x35,0x70,0xf0,0x00,0xf0,0x00,0x32,0x7a,0xd0,0x08,
0x82,0x00,0x0d,0x51,0x60,0x08,0x40,0x03,0x70,0x00,0xf0,0x00,0x33,0x80,0x70,0x00,
0xf0,0x00,0x21,0x06,0x70,0x00,0xf0,0x00,0x37,0x00,0x70,0x00,0xf0,0x00,0x37,0x80,
0x40,0x15,0xf0,0x00,0x36,0x83,0x70,0x00,0xf0,0x00,0x33,0x05,0x0d,0x61,0x60,0x09,
0x32,0x86,0x0d,0x6b,0x60,0x0a,0x32,0x10,0x70,0x00,0xf0,0x00,0x32,0x90,0x70,0x00,
0xf0,0x00,0x33,0x10,0x70,0x00,0xf0,0x00,0x33,0x90,0x70,0x00,0xf0,0x00,0x34,0x10,
0x70,0x00,0xf0,0x00,0x34,0x90,0x70,0x00,0xf0,0x00,0x31,0x10,0x70,0x00,0xf0,0x00,
0x31,0x90,0x70,0x00,0xf0,0x00,0x32,0x20,0x70,0x00,0xf0,0x00,0x32,0xa0,0x70,0x00,
0xf0,0x00,0x33,0x20,0x70,0x00,0xf0,0x00,0x33,0xa0,0x70,0x00,0xf0,0x00,0x34,0x20,
0x70,0x00,0xf0,0x00,0x34,0xa0,0x70,0x00,0xf0,0x00,0x31,0x20,0x70,0x00,0xf0,0x00,
0x31,0xa0,0x70,0x00,0xf0,0x00,0x82,0x00,0x0d,0x30,0x60,0x0a,0x0d,0x40,0x60,0x0b,
0xc0,0x10,0xf0,0x00,0x10,0x20,0xf0,0x00,0x0d,0x51,0x60,0x0c,0xc0,0x10,0xf0,0x00,
0x10,0x30,0xf0,0x00,0xf0,0x00,0x35,0xc0,0xd0,0x08,0xf0,0x00,0x0d,0x75,0x60,0x0f,
0xf0,0x00,0x05,0x63,0x60,0x0e,0x24,0xf7,0x05,0x1d,0x60,0x0d,0x25,0x76,0x70,0x00,
0xf0,0x00,0x91,0xc7,0x20,0xe8,0x40,0x15,0x91,0x8f,0x21,0xe9,0xd4,0x09,0xc3,0xef,
0x20,0x00,0x40,0x12,0x9f,0xbe,0x20,0x11,0x58,0x03,0xa0,0x80,0x35,0x77,0x90,0x01,
0xf0,0x00,0x70,0x00,0xd0,0x08,0xf0,0x00,0x21,0xf5,0xf0,0x00,0xa0,0xca,0x22,0x54,
0xf0,0x00,0xcc,0x09,0x05,0x17,0x60,0x0c,0x83,0x2c,0x70,0x00,0xf0,0x00,0x8a,0x61,
0x70,0x00,0xf0,0x00,0xae,0x48,0x22,0x45,0xa2,0x2e,0xa2,0x28,0x20,0x78,0xf0,0x00,
0xf0,0x00,0x35,0xf0,0xf0,0x00,0xf0,0x00,0x18,0x00,0xf0,0x00,0xf0,0x00,0x30,0x78,
0xf0,0x00,0x16,0xe3,0x60,0x09,0xa0,0x27,0x89,0x01,0x23,0xf4,0xf0,0x00,0xf0,0x00,
0x20,0xf2,0xf0,0x00,0x82,0x61,0x21,0x73,0xf0,0x00,0xa0,0x50,0x36,0x70,0xf0,0x00,
0xa0,0x58,0x23,0x72,0xe1,0x40,0xa8,0x01,0x22,0xf3,0xf0,0x00,0x90,0x49,0x22,0x75,
0xe0,0x40,0x80,0x61,0x70,0x00,0xf0,0x00,0x8a,0x51,0x33,0xf1,0xf0,0x00,0xa0,0x58,
0x70,0x00,0xf0,0x00,0xaf,0x48,0x70,0x00,0xf0,0x00,0xf0,0x00,0x34,0x70,0xd0,0x08,
0x82,0x00,0x0d,0x75,0x60,0x08,0x90,0x09,0x0d,0x00,0x60,0x09,0xf0,0x00,0x35,0x00,
0xf0,0x00,0xf0,0x00,0x33,0x80,0xc0,0x28,0xf0,0x00,0x10,0x10,0xf0,0x00,0xf0,0x00,
0x34,0x81,0xd0,0x08,0x82,0x49,0x0d,0x75,0x60,0x08,0xf0,0x00,0x70,0x00,0x8f,0xfd,
0x04,0x00,0x60,0x00,0xa2,0x14,0x8e,0xc0,0x40,0x00,0x60,0x05,0x60,0x00,0x60,0x05,
0xe6,0x00,0xc8,0x1b,0x70,0x00,0xf0,0x00,0xd8,0xdb,0x0d,0x51,0x60,0x08,0x83,0x5b,
0x70,0x00,0xf0,0x00,0x9e,0xba,0x30,0x03,0xf0,0x00,0xf0,0x00,0x30,0x84,0xd4,0x09,
0xf0,0x00,0x70,0x00,0x8f,0xaf,0xf0,0x00,0x0d,0x75,0x60,0x08,0xf0,0x00,0x0d,0x51,
0x60,0x09,0xf0,0x00,0x24,0x03,0xf0,0x00,0xf0,0x00,0x27,0x94,0xd0,0x08,0xa0,0x03,
0x70,0x00,0xf0,0x00,0x00,0x11,0x08,0x00,0xf0,0x00,0x00,0x11,0x08,0x00,0xc0,0x0e,
0xa0,0x09,0x00,0x11,0x08,0x00,0xa0,0x09,0x70,0x00,0xf0,0x00,0xa4,0x08,0x70,0x00,
0xd0,0x08,0xa0,0x03,0x70,0x00,0xf0,0x00,0x00,0x11,0x08,0x00,0xf0,0x00,0x00,0x11,
0x08,0x00,0xc0,0x26,0xa0,0x09,0x00,0x11,0x08,0x00,0xa0,0x09,0x70,0x00,0xf0,0x00,
0xa4,0x08,0x70,0x00,0xd0,0x08,0xf0,0x00,0x1d,0x01,0x60,0x08,0xf0,0x00,0x0a,0x2c,
0x60,0x00,0xf0,0x00,0x01,0x1a,0x60,0x01,0x31,0x00,0x70,0x00,0xf0,0x00,0x31,0x81,
0x70,0x00,0xd0,0x08,0xa8,0x01,0x7f,0xff,0x60,0x06,0xcc,0x0a,0x70,0x00,0xf0,0x00,
0x8e,0xa1,0x31,0x06,0xf0,0x00,0xf0,0x00,0x32,0x06,0xd4,0x09,0xae,0xe8,0x04,0xdf,
0xd0,0x80,0x10,0x00,0x60,0x03,0xa1,0xf1,0x30,0x23,0x07,0x73,0xd2,0x80,0xf0,0x00,
0x07,0xc6,0xd0,0x80,0x08,0x00,0x60,0x03,0xa0,0x02,0x0e,0x6f,0x60,0x09,0xf0,0x00,
0x02,0x00,0x60,0x03,0x80,0x00,0xf0,0x00,0x07,0x73,0xd0,0x80,0x40,0xe0,0x00,0x1f,
0x60,0x01,0x13,0xd5,0x60,0x07,0xa0,0x0b,0x90,0x40,0x70,0x00,0xf0,0x00,0x13,0xfb,
0x60,0x06,0xa0,0x08,0x14,0x05,0x60,0x06,0xa0,0x07,0x14,0x0f,0x60,0x06,0xa0,0x06,
0x45,0x60,0x00,0x3a,0x60,0x01,0x13,0xb6,0x60,0x07,0xa0,0x05,0x90,0x40,0x70,0x00,
0xf0,0x00,0x13,0xf7,0x60,0x06,0xa0,0x02,0x14,0x01,0x60,0x06,0xa0,0x01,0x14,0x0b,
0x60,0x06,0x80,0x00,0xf0,0x00,0x0d,0x28,0xd0,0x80,0xd7,0xca,0x00,0xff,0x60,0x04,
0x81,0xd7,0x0c,0xf7,0x60,0x09,0xd0,0x56,0x70,0x00,0xf0,0x00,0x82,0x76,0x30,0x17,
0xf0,0x00,0xd0,0xf6,0x40,0x83,0xf0,0x00,0xc1,0xa4,0x20,0x19,0xf0,0x00,0x82,0xf6,
0x70,0x00,0xf0,0x00,0xc1,0x80,0x20,0x17,0xa1,0xd6,0xc3,0xe7,0x70,0x00,0xf0,0x00,
0xc5,0xc7,0x70,0x00,0xf0,0x00,0xf0,0x00,0x30,0x17,0xd0,0x08,0xf0,0x00,0x70,0x00,
0xa0,0xbf,0xf0,0x00,0x70,0x00,0x80,0x84,0x1e,0xc8,0x60,0x08,0xa1,0xd0,0xf0,0x00,
0x20,0x00,0xa1,0xcf,0x90,0x00,0x70,0x00,0xf0,0x00,0xf0,0x00,0x70,0x00,0xd4,0x09,
0xf0,0x00,0x70,0x00,0x8f,0xc0,0x1e,0xc8,0x60,0x08,0xa1,0xcb,0xf0,0x00,0x30,0x00,
0xd0,0x08,0x00,0x28,0x60,0x00,0xa1,0xc9,0x9e,0x38,0x0e,0xf4,0x60,0x09,0x9e,0x38,
0x70,0x00,0x9f,0xff,0xf0,0x00,0x70,0x00,0xd0,0x08,0x40,0x40,0x0c,0x8a,0xd5,0x80,
0xf0,0x00,0x0c,0x8b,0xd2,0x80,0xf0,0x00,0x0f,0xb1,0xd2,0x80,0x9c,0x39,0x70,0x00,
0xf0,0x00,0x9c,0x31,0x70,0x00,0x90,0x03,0xf0,0x00,0x70,0x00,0x90,0x02,0x40,0x10,
0x70,0x00,0xaf,0xf3,0x41,0xf1,0x40,0x40,0x80,0x08,0x40,0x00,0x70,0x00,0xaf,0xf1,
0x41,0xf1,0x40,0x40,0x80,0x07,0x40,0x71,0x40,0x20,0xa0,0x06,0x43,0xa1,0x40,0x30,
0xa0,0x05,0xf0,0x00,0x10,0x75,0xd0,0x80,0x40,0x71,0x40,0x20,0xa0,0x03,0x43,0xa1,
0x40,0x30,0xa0,0x01,0xf0,0x00,0x10,0x81,0xd0,0x80,0xf0,0x00,0x0c,0x92,0xd0,0x80,
0xf0,0x00,0x0c,0x94,0xd0,0x80,0xf0,0x00,0x0b,0xc9,0x60,0x08,0xf0,0x00,0x1d,0x8d,
0xd2,0x80,0xf0,0x00,0x16,0xd5,0xd0,0x80,0xf0,0x00,0x0b,0xc9,0x60,0x08,0xf0,0x00,
0x1d,0x8f,0xd2,0x80,0xf0,0x00,0x16,0xda,0xd0,0x80,0x3e,0x91,0x1f,0x5f,0xd2,0x80,
0xf0,0x00,0x23,0x8a,0xd0,0x80,0x0d,0x82,0x60,0x08,0xa1,0xab,0xf0,0x00,0x30,0x00,
0xd0,0x08,0xf0,0x00,0x0f,0x88,0x60,0x0b,0xf0,0x00,0x02,0x30,0x60,0x03,0xf0,0x00,
0x09,0x38,0x60,0x04,0x9f,0x98,0x01,0x2c,0x60,0x05,0xf0,0x00,0x2e,0xb3,0xee,0x00,
0xf0,0x00,0x0f,0xb1,0xd2,0x80,0x9e,0x09,0x0d,0x84,0x60,0x0c,0x9f,0x90,0x70,0x00,
0x90,0x02,0x9f,0x88,0x2f,0x34,0xee,0x00,0xf0,0x00,0x2f,0xb5,0xee,0x00,0x30,0x43,
0x0b,0x42,0x60,0x08,0xf0,0x00,0x30,0xc4,0xf0,0x00,0xf0,0x00,0x31,0x45,0xf0,0x00,
0xf0,0x00,0x2c,0xb1,0x40,0x17,0xf0,0x00,0x2d,0x32,0xf0,0x00,0xc6,0x79,0x22,0x05,
0xf0,0x00,0xf0,0x00,0x3d,0x81,0xf0,0x00,0xf0,0x00,0x3d,0x01,0xf0,0x00,0xdd,0x6d,
0x1b,0x93,0xd2,0x80,0x90,0x46,0x0d,0x82,0x60,0x0a,0x20,0x42,0x1b,0x93,0xd2,0x80,
0xda,0xc9,0x20,0x25,0xa1,0x94,0x8c,0x69,0x2d,0xb3,0xf0,0x00,0xdd,0x49,0x32,0x01,
0xf0,0x00,0x8d,0x89,0x70,0x00,0xf0,0x00,0x3c,0x81,0xfe,0x35,0x60,0x00,0x35,0x81,
0x00,0x16,0x60,0x01,0xa0,0x18,0x21,0x46,0xf0,0x00,0xaa,0x07,0x01,0x2d,0x60,0x00,
0x81,0xcf,0x70,0x00,0xf0,0x00,0x8f,0x80,0x70,0x00,0xf0,0x00,0xf0,0x00,0x70,0x00,
0x94,0x02,0x40,0x45,0x57,0x4b,0x60,0x00,0xe0,0x00,0x60,0x01,0x80,0x02,0x40,0x65,
0x40,0x00,0x60,0x00,0xc6,0x66,0x60,0x01,0x80,0x00,0xa0,0x30,0x40,0x00,0x60,0x04,
0xaf,0x4e,0x00,0xa4,0x60,0x05,0x81,0x8e,0x0b,0x75,0x60,0x08,0xf0,0x00,0x14,0x74,
0xd2,0x80,0xf0,0x00,0x1b,0x90,0xd2,0x80,0x2e,0x34,0x04,0x00,0x60,0x06,0x20,0xc2,
0x1b,0x93,0xd2,0x80,0xd2,0xc9,0x03,0xe9,0x60,0x05,0x81,0x8e,0x0b,0x59,0x60,0x08,
0x8f,0x2d,0x31,0xc6,0xf0,0x00,0xf0,0x00,0x70,0x00,0x94,0x02,0x40,0x45,0xb1,0x5c,
0x60,0x03,0x46,0x66,0x60,0x07,0x80,0x02,0x40,0x65,0xaa,0xce,0x60,0x03,0xc6,0x66,
0x60,0x07,0x80,0x00,0xa0,0xe0,0x00,0x38,0x60,0x04,0xaf,0x48,0x00,0x1d,0x60,0x05,
0x81,0xc7,0x31,0x84,0xf0,0x00,0x31,0x05,0x14,0x74,0xd2,0x80,0xf0,0x00,0x1b,0x90,
0xd2,0x80,0xf0,0x00,0xd8,0x00,0x60,0x00,0xf0,0x00,0x0b,0x67,0x60,0x08,0x21,0xc6,
0x20,0x00,0x60,0x04,0xf0,0x00,0x13,0x33,0x60,0x05,0x81,0x86,0x31,0x84,0x40,0x07,
0x31,0x05,0x14,0x74,0xd2,0x80,0xf0,0x00,0x1b,0x90,0xd0,0x80,0xf0,0x00,0x6e,0x6c,
0x60,0x03,0x40,0x07,0x00,0xe5,0x60,0x05,0xa0,0x58,0xff,0xff,0x60,0x03,0xaa,0x24,
0x0b,0x52,0x60,0x08,0x81,0x1c,0x70,0x00,0xf0,0x00,0x31,0x05,0x7f,0xdf,0x60,0x06,
0x31,0x84,0x14,0x74,0xd2,0x80,0xf0,0x00,0x1b,0x90,0xd0,0x80,0xf0,0x00,0x0b,0x60,
0x60,0x0e,0xf0,0x00,0x00,0x04,0x60,0x03,0x40,0xa7,0x3f,0xfc,0x60,0x04,0x32,0x63,
0x80,0x08,0x60,0x05,0x32,0xe4,0x19,0x9a,0x60,0x06,0x33,0x65,0x0d,0x83,0x60,0x0f,
0x31,0xe6,0x70,0x00,0xf0,0x00,0x30,0x77,0x70,0x00,0xd0,0x08,0x80,0xe5,0x7f,0xff,
0x60,0x00,0xcc,0x0a,0x70,0x00,0xf0,0x00,0x8e,0xa9,0x33,0x70,0xf0,0x00,0xaf,0x20,
0x34,0x70,0xd4,0x09,0xae,0xe8,0x70,0x00,0xf0,0x00,0xa8,0x05,0x00,0x80,0x60,0x07,
0xa8,0xf6,0x33,0x75,0xf0,0x00,0xc3,0x86,0x70,0x00,0xf0,0x00,0x8f,0x7f,0x33,0xf6,
0xf0,0x00,0xa8,0x85,0x1d,0xe4,0xd1,0x80,0xf0,0x00,0x34,0x75,0xd0,0x08,0x0d,0x83,
0x60,0x09,0xa1,0x4f,0x20,0x12,0x1f,0x32,0xd2,0x80,0xf0,0x00,0x35,0x82,0xd0,0x08,
0x90,0x82,0x0d,0x83,0x60,0x09,0x40,0xa7,0x40,0x77,0xe6,0x40,0xf0,0x00,0x70,0x00,
0xf0,0x00,0xf0,0x00,0x30,0x17,0xd0,0x08,0x0b,0xb4,0x60,0x08,0xa1,0x48,0xf0,0x00,
0x31,0x82,0xd0,0x08,0xf0,0x00,0x09,0x61,0x60,0x08,0xf0,0x00,0x09,0xc9,0x60,0x09,
0xf0,0x00,0x21,0x80,0xf0,0x00,0xf0,0x00,0x20,0x91,0xa1,0x43,0xa2,0x08,0x70,0x00,
0xd0,0x08,0x00,0xcf,0x60,0x00,0xa0,0x05,0x40,0x11,0x0c,0x14,0xd0,0x80,0x00,0xcf,
0x60,0x00,0xa0,0x03,0xf0,0x00,0x20,0x22,0xd0,0x80,0x01,0x51,0x60,0x00,0xa0,0x01,
0xf0,0x00,0x20,0x1e,0xd0,0x80,0xf0,0x00,0x0e,0x69,0x60,0x08,0xf0,0x00,0x01,0xd0,
0x60,0x01,0xf0,0x00,0x30,0x80,0xf0,0x00,0xf0,0x00,0x30,0x01,0xd0,0x08,0x83,0x6d,
0x0c,0x35,0x60,0x08,0x40,0x60,0x39,0xd8,0x60,0x01,0x41,0xe2,0x21,0x96,0x60,0x03,
0x33,0x00,0x41,0x44,0xf0,0x00,0x33,0x81,0x70,0x00,0xf0,0x00,0x34,0x02,0x70,0x00,
0xf0,0x00,0x34,0x83,0x0c,0x29,0x60,0x09,0x35,0x04,0x39,0xe6,0x60,0x00,0x35,0x85,
0x39,0xeb,0x60,0x03,0x30,0x90,0x70,0x00,0xf0,0x00,0x33,0x93,0x70,0x00,0xd0,0x08,
0xf0,0x00,0x70,0x00,0xae,0xcf,0xf0,0x00,0x70,0x00,0x8f,0x14,0xf0,0x00,0x70,0x00,
0xaf,0x0d,0xf0,0x00,0x0c,0x51,0xd2,0x80,0xf0,0x00,0x21,0xa0,0xd0,0x80,0xf0,0x00,
0x05,0x2e,0xd2,0x80,0xf0,0x00,0x70,0x00,0xa0,0x0e,0xf0,0x00,0x21,0xb7,0xd0,0x80,
0xf0,0x00,0x1f,0x32,0xd2,0x80,0xf0,0x00,0x1e,0x84,0xd2,0x80,0xf0,0x00,0x21,0xe0,
0xd0,0x80,0xf0,0x00,0x1e,0xa4,0xd2,0x80,0xf0,0x00,0x07,0xf7,0xd2,0x80,0xf0,0x00,
0x22,0x15,0xd0,0x80,0xf0,0x00,0x07,0xfb,0xd2,0x80,0xf0,0x00,0x22,0x8f,0xd0,0x80,
0x40,0x40,0x22,0xe1,0xd2,0x80,0x40,0x80,0x22,0xe2,0xd2,0x80,0xf0,0x00,0x22,0x9c,
0xd0,0x80,0xf0,0x00,0x07,0xfb,0xd2,0x80,0xf0,0x00,0x22,0xb6,0xd0,0x80,0xf0,0x00,
0x20,0xf0,0xd2,0x80,0x90,0x02,0x27,0xdf,0xd2,0x80,0x9e,0x69,0x70,0x00,0xf0,0x00,
0xf0,0x00,0x07,0x00,0xd1,0x80,0xf0,0x00,0x23,0x20,0xd0,0x80,0x90,0x82,0x0c,0x29,
0x60,0x09,0x40,0x17,0x40,0x67,0xe6,0x40,0xf0,0x00,0x70,0x00,0xf0,0x00,0xf0,0x00,
0x32,0x17,0xd0,0x08,0xf0,0x00,0x07,0xf7,0xd2,0x80,0xf0,0x00,0x27,0xea,0xd2,0x80,
0xf0,0x00,0x11,0xb5,0xd0,0x80,0x40,0x55,0x15,0x17,0x60,0x08,0xf0,0x00,0x1d,0x40,
0x60,0x00,0x31,0x05,0x1e,0x60,0x60,0x01,0x31,0x85,0x70,0x00,0xf0,0x00,0x32,0x05,
0x70,0x00,0xf0,0x00,0x32,0x85,0x70,0x00,0xf0,0x00,0x33,0x00,0x70,0x00,0xf0,0x00,
0x33,0x81,0x0d,0x88,0x60,0x09,0x34,0x00,0x02,0x54,0x60,0x02,0x34,0x81,0x38,0x80,
0x60,0x03,0x30,0x12,0x70,0x00,0xf0,0x00,0x30,0x93,0x70,0x00,0xd0,0x08,0x17,0x0b,
0x60,0x0c,0xa0,0xff,0x00,0x40,0x40,0x05,0xf0,0x00,0x00,0x41,0x24,0x3f,0xd0,0x80,
0xf0,0x00,0x0c,0x83,0x60,0x08,0x90,0x00,0x0c,0x6b,0x60,0x0b,0xf0,0x00,0x70,0x0c,
0xe6,0x00,0xf0,0x00,0x20,0x03,0xf0,0x00,0xf0,0x00,0x22,0x04,0xf0,0x00,0xf0,0x00,
0x3b,0xb3,0xf0,0x00,0xf0,0x00,0x3c,0x34,0xd0,0x08,0xf0,0x00,0x70,0x00,0xae,0x31,
0xf0,0x00,0x0c,0x8d,0x60,0x08,0xf0,0x00,0x26,0x0a,0xd0,0x80,0x83,0xff,0x0d,0x95,
0x60,0x08,0xf0,0x00,0x01,0xf4,0x60,0x00,0xf0,0x00,0x03,0xb1,0x60,0x01,0x10,0x00,
0x03,0xb2,0x60,0x02,0x10,0x01,0x04,0x0e,0x60,0x00,0x10,0x02,0x04,0x0f,0x60,0x01,
0x10,0x00,0x04,0x5c,0x60,0x02,0x10,0x01,0x04,0x5d,0x60,0x00,0x10,0x02,0x13,0x80,
0x60,0x01,0x10,0x00,0x0d,0xa5,0x60,0x09,0x10,0x01,0x02,0xee,0x60,0x00,0x10,0x07,
0x43,0x06,0x60,0x01,0x10,0x10,0x04,0x69,0x60,0x02,0x10,0x11,0x44,0x87,0x60,0x00,
0x10,0x12,0x05,0xe3,0x60,0x01,0x10,0x10,0x46,0x08,0x60,0x02,0x10,0x11,0x06,0xae,
0x60,0x00,0x10,0x12,0x0d,0x9e,0x60,0x08,0x10,0x10,0x9e,0x3c,0x60,0x00,0x10,0x17,
0x0d,0xad,0x60,0x09,0x10,0x00,0x25,0xda,0x60,0x00,0x10,0x07,0xc0,0x41,0x60,0x01,
0x10,0x10,0x28,0xa0,0x60,0x02,0x10,0x11,0x40,0x3c,0x60,0x00,0x10,0x12,0x29,0xcc,
0x60,0x01,0x10,0x10,0x00,0x37,0x60,0x02,0x10,0x11,0x29,0xd1,0x60,0x00,0x10,0x12,
0x00,0x37,0x60,0x01,0x10,0x10,0x29,0xd6,0x60,0x02,0x10,0x11,0x00,0x37,0x60,0x00,
0x10,0x12,0x29,0xdb,0x60,0x01,0x10,0x10,0x00,0x37,0x60,0x02,0x10,0x11,0x0d,0xba,
0x60,0x08,0x10,0x12,0x25,0xda,0x60,0x00,0x10,0x17,0xc0,0x40,0x60,0x01,0x10,0x00,
0x27,0x15,0x60,0x02,0x10,0x01,0x40,0x3e,0x60,0x00,0x10,0x02,0x27,0x1a,0x60,0x01,
0x10,0x00,0x80,0x3c,0x60,0x02,0x10,0x01,0x28,0x64,0x60,0x00,0x10,0x02,0x40,0x3c,
0x60,0x01,0x10,0x00,0x28,0x69,0x60,0x02,0x10,0x01,0x40,0x3c,0x60,0x00,0x10,0x02,
0x28,0x6e,0x60,0x01,0x10,0x00,0x80,0x3a,0x60,0x02,0x10,0x01,0x28,0x73,0x60,0x00,
0x10,0x02,0x80,0x3a,0x60,0x01,0x10,0x00,0x0d,0xc9,0x60,0x09,0x10,0x01,0x70,0x00,
0xf0,0x00,0x10,0x07,0x70,0x00,0xf0,0x00,0x10,0x17,0x70,0x00,0xd0,0x08,0x0c,0xdf,
0x60,0x0b,0xa0,0xbf,0x30,0x30,0x23,0xd6,0xd2,0x80,0xf0,0x00,0x26,0xe8,0xd0,0x80,
0x0d,0x95,0x60,0x08,0xa0,0xbc,0xf0,0x00,0x00,0x02,0xa0,0xbb,0x90,0x82,0x70,0x00,
0xf0,0x00,0x82,0x8a,0x70,0x00,0x90,0x03,0x90,0x8a,0x70,0x00,0x90,0x01,0xf0,0x00,
0x70,0x00,0x8f,0xfb,0x82,0xbf,0x70,0x00,0xf0,0x00,0xf0,0x00,0x01,0x99,0xd2,0x80,
0xf0,0x00,0x0d,0x94,0x60,0x08,0xf0,0x00,0x26,0xc1,0xf0,0x00,0xf0,0x00,0x00,0x02,
0xa0,0xb2,0x90,0x82,0x70,0x00,0xf0,0x00,0x82,0x8a,0x70,0x00,0x90,0x03,0x90,0x8a,
0x70,0x00,0x90,0x01,0xf0,0x00,0x70,0x00,0x8f,0xfb,0x82,0x80,0x70,0x00,0xf0,0x00,
0xf0,0x00,0x70,0x00,0xd0,0x08,0xf0,0x00,0x0d,0xa5,0x60,0x0d,0xf0,0x00,0x3f,0xff,
0x60,0x02,0xf0,0x00,0x00,0x51,0xa0,0xa9,0xc2,0x53,0x70,0x00,0xf0,0x00,0x8e,0xc4,
0x70,0x00,0x90,0x01,0xf0,0x00,0x70,0x00,0x97,0xfc,0xd4,0x8f,0x01,0x99,0xd2,0x80,
0x40,0x05,0x0d,0x9e,0x60,0x0d,0x40,0x17,0x3f,0xff,0x60,0x02,0x9f,0x7d,0x00,0x51,
0xa0,0xa2,0xc2,0x53,0x70,0x00,0xf0,0x00,0x82,0xc4,0x27,0x1c,0xd1,0x80,0xf0,0x00,
0x70,0x00,0x97,0xfc,0x91,0x46,0x27,0x20,0xd0,0x80,0x40,0x07,0x01,0x99,0xd2,0x80,
0xf0,0x00,0x0d,0x88,0x60,0x0e,0x40,0x07,0x25,0xc1,0xa0,0x9b,0x9e,0x79,0x2e,0x40,
0x40,0x14,0x40,0x36,0x31,0x67,0x90,0x1e,0x2f,0x45,0x19,0x64,0x60,0x02,0x4f,0xf0,
0x1a,0x5e,0x60,0x03,0x83,0x54,0x40,0x36,0xf0,0x00,0x83,0x5c,0x40,0x00,0xe2,0x00,
0xf0,0x00,0x40,0x10,0xe2,0x00,0xf0,0x00,0x70,0x00,0xf0,0x00,0x90,0x00,0x70,0x00,
0xf0,0x00,0xf0,0x00,0x70,0x00,0x9c,0x25,0x40,0x36,0x22,0xf0,0xd2,0x80,0x40,0x14,
0x21,0x40,0x94,0x06,0x0d,0xba,0x60,0x0d,0xa0,0x8e,0xf0,0x00,0x20,0x51,0xa0,0x8d,
0x90,0x41,0x70,0x00,0xf0,0x00,0x82,0x45,0x70,0x00,0x90,0x02,0xf0,0x00,0x70,0x00,
0x90,0x07,0xf0,0x00,0x70,0xdc,0x8f,0xfb,0x0d,0xad,0x60,0x0d,0xa0,0x88,0xf0,0x00,
0x20,0x51,0xa0,0x87,0x90,0x41,0x70,0x00,0xf0,0x00,0x82,0x45,0x70,0x00,0x90,0x19,
0xf0,0x00,0x70,0x00,0x90,0x01,0xf0,0x00,0x70,0xdc,0x8f,0xfb,0x20,0xd1,0x3f,0xff,
0x60,0x02,0xf0,0x00,0x0c,0xdf,0x60,0x0b,0xc2,0x53,0x31,0x61,0xf0,0x00,0xd4,0x8e,
0x30,0x33,0xf0,0x00,0xd4,0x4a,0x37,0xc6,0xf0,0x00,0xc6,0xa2,0x70,0x00,0xf0,0x00,
0xc3,0xa0,0x3d,0x42,0xf0,0x00,0xf0,0x00,0x31,0xe0,0xd0,0x08,0xc6,0x24,0x31,0xe0,
0xf0,0x00,0x90,0x00,0x3d,0x44,0xf0,0x00,0x83,0xb6,0x70,0x00,0xe0,0x40,0xf0,0x00,
0x37,0xc6,0xa0,0x4b,0x21,0x42,0x32,0x00,0x60,0x03,0xf0,0x00,0x22,0x60,0xf0,0x00,
0xb0,0x98,0x22,0xe1,0xf0,0x00,0xf0,0x00,0x23,0xea,0xd2,0x80,0x40,0x16,0x23,0xde,
0xd2,0x80,0xa9,0x83,0x70,0x00,0xf0,0x00,0xc2,0xf0,0x0c,0xdf,0x60,0x0b,0x80,0xc3,
0x70,0x00,0xf0,0x00,0xf0,0x00,0x33,0x63,0xf0,0x00,0xf0,0x00,0x34,0xe3,0xf0,0x00,
0xf0,0x00,0x30,0x33,0x80,0x12,0x40,0xd5,0x21,0x41,0xa0,0x6b,0xcc,0x0b,0x40,0x00,
0xf0,0x00,0x80,0xed,0x23,0xea,0xd2,0x80,0xbf,0x60,0x20,0x60,0xf0,0x00,0xf0,0x00,
0x20,0xe1,0xf0,0x00,0xf0,0x00,0x23,0xea,0xd2,0x80,0x90,0xc6,0x23,0xde,0xd2,0x80,
0x4f,0x95,0x40,0x14,0xa0,0x64,0x81,0x75,0x70,0x00,0x40,0x06,0xaf,0x43,0x70,0x00,
0xf0,0x00,0xc2,0xe0,0x0c,0xdf,0x60,0x0b,0xf0,0x00,0x31,0xe0,0xf0,0x00,0x80,0xc3,
0x40,0x36,0xe6,0x00,0xc6,0x24,0x30,0x33,0xf0,0x00,0xf0,0x00,0x33,0x63,0xf0,0x00,
0xf0,0x00,0x34,0xe3,0xf0,0x00,0xf0,0x00,0x3d,0x44,0xf0,0x00,0xf0,0x00,0x37,0xc6,
0xa0,0x2e,0xf0,0x00,0x23,0x66,0xa0,0x31,0x82,0x92,0x0b,0xb8,0x60,0x03,0x47,0xf4,
0x23,0xe0,0xd2,0x80,0x52,0x08,0x60,0x05,0x98,0x03,0x82,0x92,0x52,0x08,0x60,0x03,
0x47,0xf4,0x23,0xe0,0xd2,0x80,0x52,0x08,0x60,0x05,0x98,0x23,0xf0,0x00,0x33,0xe4,
0xf0,0x00,0xf0,0x00,0x34,0x65,0xf0,0x00,0xf0,0x00,0x35,0x64,0xf0,0x00,0xf0,0x00,
0x35,0xe5,0xf0,0x00,0xf0,0x00,0x23,0x66,0xa0,0x4e,0x91,0x8e,0x70,0x00,0xf0,0x00,
0xf0,0x00,0x33,0x66,0xa0,0x24,0x82,0x92,0x52,0x08,0x60,0x03,0xf0,0x00,0x23,0xe0,
0xd2,0x80,0xf0,0x00,0x70,0x00,0x9c,0x05,0x82,0x92,0x0b,0xb8,0x60,0x03,0xf0,0x00,
0x23,0xe0,0xd2,0x80,0xf0,0x00,0x70,0x00,0x9b,0xf7,0x0d,0x8e,0x60,0x0d,0xa0,0x2b,
0xf0,0x00,0x70,0x00,0x8f,0xf5,0xf0,0x00,0x24,0xe6,0xa0,0x43,0x9f,0xbe,0x70,0x00,
0xf0,0x00,0xf0,0x00,0x34,0xe6,0xa0,0x19,0x82,0x92,0x52,0x08,0x60,0x03,0xf0,0x00,
0x23,0xe0,0xd2,0x80,0xf0,0x00,0x70,0x00,0x9c,0x05,0x82,0x92,0x0b,0xb8,0x60,0x03,
0xf0,0x00,0x23,0xe0,0xd2,0x80,0xf0,0x00,0x70,0x00,0x9b,0xf7,0x0d,0x91,0x60,0x0d,
0xa0,0x20,0xf0,0x00,0x70,0x00,0x8f,0xf5,0x40,0x14,0x23,0xe1,0xa0,0x38,0xc2,0x63,
0x25,0x62,0xf0,0x00,0xf0,0x00,0x24,0x65,0x90,0x07,0xc2,0xa3,0x25,0xe6,0xf0,0x00,
0x90,0x80,0x70,0x00,0x90,0x02,0x83,0x77,0x70,0x00,0xf0,0x00,0x25,0x60,0x23,0xe0,
0xeb,0xc0,0x0c,0xdf,0x60,0x0b,0xa0,0x31,0xf0,0x00,0x30,0x30,0xf0,0x00,0xf0,0x00,
0x21,0xe0,0xd0,0x08,0xc2,0xa3,0x25,0xe6,0xf0,0x00,0xf0,0x00,0x70,0x00,0x93,0xf9,
0x90,0x40,0x70,0x00,0x8f,0xfa,0xf0,0x00,0x21,0xe0,0xaf,0x2e,0xf0,0x00,0x24,0x62,
0xd2,0x80,0xf0,0x00,0x32,0x60,0xf0,0x00,0xf0,0x00,0x32,0xe1,0xd0,0x08,0xf0,0x00,
0x23,0xed,0xd2,0x80,0xb8,0x68,0x22,0x60,0xf0,0x00,0xf0,0x00,0x22,0xe1,0xf0,0x00,
0xf0,0x00,0x23,0xea,0xd2,0x80,0xf0,0x00,0x23,0xde,0xd2,0x80,0xa9,0x88,0x70,0x00,
0xf0,0x00,0xab,0xf8,0x23,0xe4,0xd2,0x80,0x46,0x43,0x21,0x42,0xa0,0x20,0xa0,0x98,
0x70,0x00,0xf0,0x00,0xf0,0x00,0x23,0xe7,0xd2,0x80,0xf0,0x00,0x23,0xc6,0xd2,0x80,
0x90,0x00,0x70,0x00,0xf0,0x00,0xf0,0x00,0x70,0x00,0xdc,0x09,0xf0,0x00,0x23,0xce,
0xd0,0x80,0x47,0xe5,0x70,0x00,0xf0,0x00,0x40,0x16,0x20,0xd3,0xa0,0x18,0x83,0x5d,
0x20,0x52,0xf0,0x00,0xc2,0xf5,0x21,0x54,0x98,0x07,0xc2,0xb6,0x70,0x00,0x90,0x02,
0xf0,0x00,0x70,0x00,0x90,0x05,0xf0,0x00,0x70,0x00,0x80,0x02,0xc2,0xb6,0x70,0x00,
0xf0,0x00,0xf0,0x00,0x70,0x00,0xd4,0x09,0x82,0x64,0x70,0x00,0xf0,0x00,0xf0,0x00,
0x70,0x00,0xdc,0x09,0xf0,0x00,0x31,0x51,0xf0,0x00,0xf0,0x00,0x30,0xd2,0xd0,0x08,
0x0d,0xc9,0x60,0x0b,0xa0,0x0c,0x9e,0x79,0x20,0x36,0xf0,0x00,0xf0,0x00,0x20,0x45,
0xf0,0x00,0x9f,0xbc,0x70,0x00,0xe0,0x40,0x91,0x45,0x70,0x00,0xd0,0x09,0x26,0x44,
0x27,0x2d,0xd5,0x80,0x91,0x86,0x70,0x00,0xf0,0x00,0xf0,0x00,0x27,0x32,0xd5,0x80,
0xf0,0x00,0x70,0x00,0xaf,0x66,0x2f,0x41,0x27,0x36,0xd0,0x80,0xf0,0x00,0x29,0x15,
0xd2,0x80,0xf0,0x00,0x3b,0x06,0xd2,0x80,0xf0,0x00,0x28,0x88,0xd0,0x80,0xf0,0x00,
0x70,0x00,0xd0,0x08,0xf0,0x00,0x16,0xc3,0x60,0x08,0xf0,0x00,0x00,0x9a,0x60,0x00,
0xf0,0x00,0x02,0xe3,0x60,0x00,0x10,0x00,0x04,0xf4,0x60,0x00,0x10,0x00,0x06,0xff,
0x60,0x00,0x10,0x00,0x09,0x07,0x60,0x00,0x10,0x00,0x0b,0x10,0x60,0x00,0x10,0x00,
0x0d,0x1f,0x60,0x00,0x10,0x00,0x0f,0x65,0x60,0x00,0x10,0x00,0x0f,0x65,0x60,0x00,
0x10,0x00,0x0d,0x1f,0x60,0x00,0x10,0x00,0x0b,0x10,0x60,0x00,0x10,0x00,0x09,0x07,
0x60,0x00,0x10,0x00,0x06,0xff,0x60,0x00,0x10,0x00,0x04,0xf4,0x60,0x00,0x10,0x00,
0x02,0xe3,0x60,0x00,0x10,0x00,0x00,0x9a,0x60,0x00,0xf0,0x00,0x10,0x00,0xf0,0x00,
0xf0,0x00,0x10,0x00,0xf0,0x00,0xf0,0x00,0x16,0xd3,0x60,0x08,0xf0,0x00,0xff,0x93,
0x60,0x00,0xf0,0x00,0xfe,0x37,0x60,0x00,0x10,0x00,0xfd,0xd9,0x60,0x00,0x10,0x00,
0xfe,0x9f,0x60,0x00,0x10,0x00,0x03,0x85,0x60,0x00,0x10,0x00,0x0d,0x6b,0x60,0x00,
0x10,0x00,0x16,0x84,0x60,0x00,0x10,0x00,0x1e,0x49,0x60,0x00,0x10,0x00,0x1e,0x49,
0x60,0x00,0x10,0x00,0x16,0x84,0x60,0x00,0x10,0x00,0x0d,0x6b,0x60,0x00,0x10,0x00,
0x03,0x85,0x60,0x00,0x10,0x00,0xfe,0x9f,0x60,0x00,0x10,0x00,0xfd,0xd9,0x60,0x00,
0x10,0x00,0xfe,0x37,0x60,0x00,0x10,0x00,0xff,0x93,0x60,0x00,0xf0,0x00,0x10,0x00,
0xf0,0x00,0xf0,0x00,0x10,0x00,0xf0,0x00,0xf0,0x00,0x16,0xe3,0x60,0x08,0xf0,0x00,
0x00,0x64,0x60,0x00,0xf0,0x00,0xff,0xa8,0x60,0x00,0x10,0x00,0xff,0xa6,0x60,0x00,
0x10,0x00,0xff,0xdf,0x60,0x00,0x10,0x00,0x00,0x01,0x60,0x00,0x10,0x00,0x01,0x28,
0x60,0x00,0x10,0x00,0x01,0x2f,0x60,0x00,0x10,0x00,0xfd,0x23,0x60,0x00,0x10,0x00,
0xfd,0xa1,0x60,0x00,0x10,0x00,0x03,0x89,0x60,0x00,0x10,0x00,0x02,0x54,0x60,0x00,
0x10,0x00,0xfe,0x7d,0x60,0x00,0x10,0x00,0x00,0x8c,0x60,0x00,0x10,0x00,0xfb,0xe1,
0x60,0x00,0x10,0x00,0xf9,0x42,0x60,0x00,0x10,0x00,0x0c,0x47,0x60,0x00,0x10,0x00,
0x0e,0xa2,0x60,0x00,0x10,0x00,0xec,0x43,0x60,0x00,0x10,0x00,0xea,0xce,0x60,0x00,
0x10,0x00,0x17,0x46,0x60,0x00,0x10,0x00,0x17,0x46,0x60,0x00,0x10,0x00,0xea,0xce,
0x60,0x00,0x10,0x00,0xec,0x43,0x60,0x00,0x10,0x00,0x0e,0xa2,0x60,0x00,0x10,0x00,
0x0c,0x47,0x60,0x00,0x10,0x00,0xf9,0x42,0x60,0x00,0x10,0x00,0xfb,0xe1,0x60,0x00,
0x10,0x00,0x00,0x8c,0x60,0x00,0x10,0x00,0xfe,0x7d,0x60,0x00,0x10,0x00,0x02,0x54,
0x60,0x00,0x10,0x00,0x03,0x89,0x60,0x00,0x10,0x00,0xfd,0xa1,0x60,0x00,0x10,0x00,
0xfd,0x23,0x60,0x00,0x10,0x00,0x01,0x2f,0x60,0x00,0x10,0x00,0x01,0x28,0x60,0x00,
0x10,0x00,0x00,0x01,0x60,0x00,0x10,0x00,0xff,0xdf,0x60,0x00,0x10,0x00,0xff,0xa6,
0x60,0x00,0x10,0x00,0xff,0xa8,0x60,0x00,0x10,0x00,0x00,0x64,0x60,0x00,0xf0,0x00,
0x10,0x00,0xf0,0x00,0xf0,0x00,0x10,0x00,0xf0,0x00,0xf0,0x00,0x17,0x0b,0x60,0x08,
0xf0,0x00,0x00,0x03,0x60,0x00,0xf0,0x00,0x54,0xc0,0x60,0x00,0x10,0x00,0x00,0x05,
0x60,0x00,0x10,0x00,0x00,0x05,0x60,0x00,0x10,0x00,0x00,0x0f,0x60,0x00,0x10,0x00,
0x00,0x0f,0x60,0x00,0x10,0x00,0x09,0xc0,0x60,0x00,0x10,0x00,0x0a,0x20,0x60,0x00,
0x10,0x00,0x1d,0x40,0x60,0x00,0x10,0x00,0x1e,0x60,0x60,0x00,0xf0,0x00,0x10,0x00,
0xf0,0x00,0xf0,0x00,0x10,0x00,0xf0,0x00,0xf0,0x00,0x70,0x00,0xd0,0x08,
};
unsigned char code TEF6686_LutByteValues[] = {
0x40,0x13,0x40,0x2f,0x41,0x68,0x41,0xc1,0x42,0x14,0x44,0xde,0x47,0xc5,0x47,0xfc,
0x4e,0x56,0x4e,0x58,0x4e,0x5b,0x4d,0x83,0x4e,0x0a,0x4e,0x49,0x4e,0x53,0x4f,0x92,
0x4f,0xea,0x50,0x74,0x50,0x80,0x56,0x60,0x56,0xd4,0x56,0xd9,0x59,0xb4,0x5a,0x3a,
0x5b,0x79,0x5d,0xdc,0x60,0x67,0x60,0x88,0x60,0xa8,0x61,0x9f,0x61,0xb6,0x61,0xdf,
0x62,0x14,0x62,0x59,0x62,0x9b,0x62,0xa1,0x63,0x69,0x64,0x3b,0x66,0x09,0x66,0xe7,
0x67,0x0b,0x67,0x1a,0x67,0x29,0x68,0x87,0x68,0x99,0x68,0xa7,0x68,0xb2,
};
unsigned char code TEF6686_set_FM_command[] = {
0x09,0x40,0x04,0x01,0x00,0x8c,0xa0,0x00,0x00,0x00,0x05,0x40,0x05,0x01,0x00,0x01,
0x07,0x20,0x01,0x01,0x00,0x01,0x26,0x52,0x05,0x20,0x16,0x01,0x00,0x01,0x05,0x20,
0x14,0x01,0x00,0x01,0x0b,0x20,0x28,0x01,0x00,0x78,0x01,0xf4,0x00,0x0a,0x00,0x14,
0x09,0x20,0x2c,0x01,0x00,0x00,0x00,0xc8,0x03,0xe8,0x09,0x20,0x2b,0x01,0x00,0x00,
0x00,0xc8,0x03,0xe8,0x0b,0x20,0x32,0x01,0x00,0xc8,0x07,0xd0,0x00,0x0a,0x00,0x50,
0x09,0x20,0x36,0x01,0x00,0x03,0x00,0x78,0x00,0xa0,0x09,0x20,0x35,0x01,0x00,0x03,
0x00,0x96,0x00,0xc8,0x07,0x20,0x37,0x01,0x00,0x01,0x09,0x60,0x07,0x20,0x39,0x01,
0x00,0x01,0x00,0x64,0x0b,0x20,0x3c,0x01,0x00,0xc8,0x0f,0xa0,0x00,0x14,0x00,0x50,
0x09,0x20,0x40,0x01,0x00,0x03,0x00,0x64,0x00,0x96,0x09,0x20,0x3f,0x01,0x00,0x03,
0x00,0x78,0x00,0xa0,0x09,0x20,0x4a,0x01,0x00,0x03,0x00,0x50,0x00,0x8c,0x09,0x20,
0x49,0x01,0x00,0x03,0x00,0x50,0x00,0x8c,0x09,0x40,0x03,0x01,0x00,0x00,0x00,0x21,
0x00,0x03,0x09,0x40,0x03,0x01,0x00,0x01,0x00,0x21,0x00,0x00,0x09,0x40,0x03,0x01,
0x00,0x02,0x00,0x21,0x00,0x00,0x09,0x40,0x03,0x01,0x00,0x00,0x00,0x20,0x00,0x03,
0x09,0x40,0x03,0x01,0x00,0x01,0x00,0x20,0x00,0x00,0x09,0x40,0x03,0x01,0x00,0x02,
0x00,0x20,0x00,0x00,0x0d,0x30,0x16,0x01,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,
0x11,0x3a,0x0d,0x30,0x16,0x01,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x11,0x3a,
0x05,0x30,0x0b,0x01,0x00,0x00,0x07,0x30,0x0d,0x01,0x00,0x80,0x00,0xe0,0x05,0x30,
0x0a,0x01,0x00,0x32,
};
unsigned char code TEF6686_set_AM_command[] = {
0x07,0x21,0x01,0x01,0x00,0x01,0x03,0xe7,0x07,0x21,0x52,0x01,0x00,0xc8,0x00,0x00,
0x07,0x21,0x52,0x01,0x00,0x00,0x00,0x00,0x05,0x30,0x0a,0x01,0x00,0x32,
};
/*
* tef6686.c - TEF6686 FM/AM tuner driver for 8051 (C89 / Keil C51)
*
* Soft-I2C bit-bang driver plus TEF6686 command layer.
* Initialization order follows the reference Tuner_Interface.c:
* 1C 00 00 / 1C 00 74 -> patch via 0x1B + 24-byte chunks
* 1C 00 00 / 1C 00 75 -> LUT via 0x1B + 24-byte chunks
* 1C 00 00 / 14 00 01 -> start firmware, wait 50 ms
* send band command table (contains ReferenceClock + Activate + config)
*
* 8051 memory map notes:
* - all tables live in CODE memory (const code unsigned char *)
* - I2C TX/RX buffers live in DATA/IDATA
*/
/*----------------------------- soft I2C ------------------------------*/
void Delay1us(uint time) //@11.0592MHz
{
unsigned long edata i;
for(;time>0;time--)
{
_nop_();
_nop_();
i = 1UL;
while (i) i--;
}
}
void I2C_Delay(void) //5us
{
unsigned long edata i;
_nop_();
_nop_();
i = 12UL;
while (i) i--;
}
void I2C_Start(void)
{
I2C_SDA = 1;
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 0;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
}
void I2C_Stop(void)
{
I2C_SDA = 0;
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay();
}
unsigned char I2C_WriteByte(unsigned char dat)
{
unsigned char i;
unsigned char ack;
for (i = 0; i < 8; i++) {
I2C_SDA = (dat & 0x80) ? 1 : 0;
dat <<= 1;
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
}
I2C_SDA = 1; /* release line, read ACK */
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
ack = I2C_SDA; /* 0 = ACK, 1 = NACK */
I2C_SCL = 0;
I2C_Delay();
return ack;
}
unsigned char I2C_ReadByte(unsigned char ack)
{
unsigned char i;
unsigned char dat;
dat = 0;
I2C_SDA = 1; /* release line */
I2C_Delay();
for (i = 0; i < 8; i++) {
I2C_SCL = 1;
I2C_Delay();
dat <<= 1;
if (I2C_SDA) dat |= 1;
I2C_SCL = 0;
I2C_Delay();
}
I2C_SDA = ack ? 1 : 0; /* 1 = NACK (last byte), 0 = ACK */
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay();
return dat;
}
unsigned char I2C_WriteBuffer(const unsigned char *buf, unsigned char len)
{
unsigned char i;
I2C_Start();
if (I2C_WriteByte(I2C_ADDR_WRITE) != 0) {
I2C_Stop();
return 0;
}
for (i = 0; i < len; i++) {
if (I2C_WriteByte(buf[i]) != 0) {
I2C_Stop();
return 0;
}
}
I2C_Stop();
return 1;
}
unsigned char I2C_ReadBuffer(unsigned char *buf, unsigned char len)
{
unsigned char i;
I2C_Start();
I2C_WriteByte(I2C_ADDR_READ);
for (i = 0; i < len; i++) {
buf[i] = I2C_ReadByte((i < (unsigned char)(len - 1)) ? 0 : 1);
}
I2C_Stop();
return 1;
}
/*----------------------------- command layer --------------------------*/
unsigned char TEF6686_WriteCmd(unsigned char module, unsigned char cmd,unsigned char n, const unsigned int *p)
{
unsigned char buf[19];
unsigned char i;
if (n > 8) return 0;
buf[0] = module;
buf[1] = cmd;
buf[2] = 1; // index, always 1
for (i = 0; i < n; i++) { // 16-bit big-endian parameters
buf[3 + 2 * i] = (unsigned char)(p[i] >> 8);
buf[4 + 2 * i] = (unsigned char)p[i];
}
return I2C_WriteBuffer(buf, (unsigned char)(3 + 2 * n));
}
unsigned char TEF6686_GetCmd(unsigned char module, unsigned char cmd,unsigned char *rx, unsigned char len)
{
unsigned char req[3];
req[0] = module;
req[1] = cmd;
req[2] = 1;
if (I2C_WriteBuffer(req, 3) != 1) return 0;
return I2C_ReadBuffer(rx, len);
}
/*----------------------------- table / patch load --------------------*/
#define TEF6686_SPLIT_SIZE 24
unsigned char TEF6686_LoadData(const unsigned char code *dat,unsigned int sizee)
{
unsigned char buf[TEF6686_SPLIT_SIZE + 1];
unsigned char len, i;
unsigned char r;
buf[0] = 0x1B;
while (sizee) {
len = (sizee > TEF6686_SPLIT_SIZE) ? TEF6686_SPLIT_SIZE
: (unsigned char)sizee;
for (i = 0; i < len; i++) buf[1 + i] = dat[i];
dat += len;
sizee -= len;
r = I2C_WriteBuffer(buf, (unsigned char)(len + 1));
if (r != 1) return r;
}
return 1;
}
unsigned char TEF6686_SendTable(const unsigned char code *tab,
unsigned int sizee)
{
unsigned int i;
unsigned char buf[24];
unsigned char len, k;
unsigned char r;
i = 0;
while (i < sizee) {
len = tab[i]; /* length-prefixed entry */
for (k = 0; k < len; k++) buf[k] = tab[i + 1 + k];
r = I2C_WriteBuffer(buf, len);
if (r != 1) return r;
i += (unsigned int)len + 1;
}
return 1;
}
/*----------------------------- public API ----------------------------*/
void TEF6686_DelayMs(unsigned int ms)
{
unsigned long edata i;
for(;ms>0;ms--)
{
_nop_();
_nop_();
i = 2763UL;
while (i) i--;
}
}
unsigned char TEF6686_Init(void)
{
unsigned char ctrl[3];
unsigned char r;
unsigned char reset_dat[5]={0x1e,0x5a,0x01,0x5a,0x5a};//软复位数据
unsigned char fre_dat[9]={0x40,0x04,0x01,0x00,0x8c,0xa0,0x00,0x00,0x00};//9.216M晶振频率数据
unsigned char activate_dat[5]={0x40,0x05,0x01,0x00,0x01};//APPL_Activate数据
r = I2C_WriteBuffer(reset_dat, 5);//软复位
if (r != 1) return r;
TEF6686_DelayMs(100);
ctrl[0] = 0x1C;
ctrl[1] = 0x00;
ctrl[2] = 0x00;
/* Clear Required Initialization Control */
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
/* Set Required Initialization Control (1) */
ctrl[2] = 0x74;
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
/* Load Required Initialization(s): patch */
r = TEF6686_LoadData(TEF6686_PatchByteValues,sizeof(TEF6686_PatchByteValues));
if (r != 1) return r;
/* Clear / Set Required Initialization Control (2) */
ctrl[2] = 0x00;
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
ctrl[2] = 0x75;
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
/* Load Required Initialization(s): LUT */
r = TEF6686_LoadData(TEF6686_LutByteValues,sizeof(TEF6686_LutByteValues));
if (r != 1) return r;
/* Clear Required Initialization Control, Start Firmware */
ctrl[2] = 0x00;
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
ctrl[0] = 0x14;
ctrl[1] = 0x00;
ctrl[2] = 0x01;
r = I2C_WriteBuffer(ctrl, 3);
if (r != 1) return r;
/* Boot state -> Idle state */
TEF6686_DelayMs(50);
r=TEF6686_GetCmd(64,128,TEF6686_DAT,2);//读取 APPL module:64 cmd:128 寄存器数据
if (r != 1) return r;
if (TEF6686_DAT[1]==0x00) return 0;//状态模式检测 0=boot state;no command support
//型号版本检测 略
r = I2C_WriteBuffer(fre_dat, 9);//写入晶振频率数据
if (r != 1) return r;
r = I2C_WriteBuffer(activate_dat, 5);//写入APPL_Activate数据
if (r != 1) return r;
TEF6686_DelayMs(100);
r=TEF6686_GetCmd(64,128,TEF6686_DAT,2);//读取 APPL module:64 cmd:128 寄存器数据
if (r != 1) return r;
if (TEF6686_DAT[1]!=0x02) return 0;//状态0x02模式检测
/* FM table includes ReferenceClock + Activate + FM config + volume */
r = TEF6686_SendTable(TEF6686_set_FM_command,sizeof(TEF6686_set_FM_command));
if (r != 1) return r;
/* Idle state -> Active state settle */
TEF6686_DelayMs(100);
r=TEF6686_GetCmd(64,128,TEF6686_DAT,2);//读取 APPL module:64 cmd:128 寄存器数据
if (r != 1) return r;
return 1;
}
unsigned char TEF6686_SetBand(unsigned char band)
{
if (band == BAND_FM) {
return TEF6686_SendTable(TEF6686_set_FM_command,
sizeof(TEF6686_set_FM_command));
}
return TEF6686_SendTable(TEF6686_set_AM_command,
sizeof(TEF6686_set_AM_command));
}
unsigned char TEF6686_Tune(unsigned char band, unsigned int freq)
{
unsigned int p[2];
p[0] = TUNE_MODE_PRESET;
p[1] = freq;
return TEF6686_WriteCmd((band == BAND_FM) ? MODULE_FM : MODULE_AM,
CMD_TUNE_TO, 2, p);
}
unsigned char TEF6686_SetVolume(int vol)
{
unsigned int p[1];
if (vol < -60) vol = -60;
if (vol > 24) vol = 24;
p[0] = (unsigned int)(vol * 10); /* 0.1 dB units */
return TEF6686_WriteCmd(MODULE_AUDIO, CMD_SET_VOLUME, 1, p);
}
unsigned char TEF6686_Mute(unsigned char on)
{
unsigned int p[1];
p[0] = on ? 1 : 0;
return TEF6686_WriteCmd(MODULE_AUDIO, CMD_SET_MUTE, 1, p);
}
unsigned char TEF6686_GetQualityData(unsigned char band, TEF6686_Quality *q)
{
unsigned char rx[14];
unsigned char r;
r = TEF6686_GetCmd((band == BAND_FM) ? MODULE_FM : MODULE_AM,
CMD_GET_QUALITY_DATA, rx, 14);
if (r != 1) return 0;
q->status = ((unsigned int)rx[0] << 8) | rx[1]; /* 时间戳 0.1ms */
q->level = (int)(((int)rx[2] << 8) | rx[3]); /* 0.1 dBuV 有符号 */
q->usn = ((unsigned int)rx[4] << 8) | rx[5]; /* 0.1 % */
q->wam = ((unsigned int)rx[6] << 8) | rx[7]; /* 0.1 % */
q->offset = (int)(((int)rx[8] << 8) | rx[9]); /* 0.1 kHz 有符号 */
q->bandwidth = ((unsigned int)rx[10] << 8) | rx[11]; /* 0.1 kHz */
q->modulation = ((unsigned int)rx[12] << 8) | rx[13]; /* 0.1 % */
return 1;
}
/*==================== 软件自动搜台 ======================*/
/* 应用层全局变量前向声明(定义在文件下部) */
static unsigned char CurBand;
static unsigned int CurFreq;
static unsigned int FmFreq;
static unsigned int AmFreq;
static unsigned char TuneMode;
/*
* 搜台阈值(参考 Tuner_Api.h / Tuner_Api.c Radio_CheckStation):
* FM: 场强 level >= 25 dB(即 >=250, 0.1dBuV)
* usn < 27% (即 <270) 且 wam < 23% (即 <230)
* 偏移 offset < 10kHz(|offset| < 100, 0.1kHz)
* AM: 仅要求偏移 offset < 1.5kHz(|offset| < 15, 0.1kHz)
* 电平稳定时间: FM 4ms, AM 36ms(电平可用后再判 usn/wam)。
*/
#define FM_SCAN_LEVEL_100 250 /* 25.0 dBuV */
#define FM_SCAN_USN_100 270 /* 27.0 % */
#define FM_SCAN_WAM_100 230 /* 23.0 % */
#define FM_SCAN_OFFSET_100 100 /* 10.0 kHz */
#define AM_SCAN_OFFSET_100 15 /* 1.5 kHz */
/* 单步进频(带边界回绕),up=1 向上, up=0 向下 */
static unsigned int SeekStepFreq(unsigned char band, unsigned char up, unsigned int f)
{
if (band == BAND_FM) {
if (up) {
if (f + FM_FREQ_STEP > FM_FREQ_MAX) f = FM_FREQ_MIN;
else f += FM_FREQ_STEP;
} else {
if (f < FM_FREQ_MIN + FM_FREQ_STEP) f = FM_FREQ_MAX;
else f -= FM_FREQ_STEP;
}
} else {
if (up) {
if (f + AM_FREQ_STEP > AM_FREQ_MAX) f = AM_FREQ_MIN;
else f += AM_FREQ_STEP;
} else {
if (f < AM_FREQ_MIN + AM_FREQ_STEP) f = AM_FREQ_MAX;
else f -= AM_FREQ_STEP;
}
}
return f;
}
/* 软件搜台:从 CurFreq 起按方向逐步进频并检测;整圈未命中返回 0。
* 命中后 CurFreq/FmFreq/AmFreq 同步更新并保持调在该台。 */
unsigned char TEF6686_Seek(unsigned char band, unsigned char up)
{
unsigned int start, f, count;
unsigned int maxsteps;
TEF6686_Quality q;
start = CurFreq;
f = CurFreq;
if (band == BAND_FM)
maxsteps = (FM_FREQ_MAX - FM_FREQ_MIN) / FM_FREQ_STEP + 2;
else
maxsteps = (AM_FREQ_MAX - AM_FREQ_MIN) / AM_FREQ_STEP + 2;
for (count = 0; count < maxsteps; count++) {
f = SeekStepFreq(band, up, f);
TEF6686_Tune(band, f);
if (band == BAND_FM) {
TEF6686_DelayMs(34); /* FM 电平+USN/WAM 稳定 */
if (!TEF6686_GetQualityData(band, &q)) return 0;
if (q.level >= FM_SCAN_LEVEL_100 &&
q.usn < FM_SCAN_USN_100 &&
q.wam < FM_SCAN_WAM_100 &&
q.offset > -FM_SCAN_OFFSET_100 && q.offset < FM_SCAN_OFFSET_100) {
break; /* 命中 */
}
} else {
TEF6686_DelayMs(36); /* AM 电平稳定 */
if (!TEF6686_GetQualityData(band, &q)) return 0;
if (q.offset > -AM_SCAN_OFFSET_100 && q.offset < AM_SCAN_OFFSET_100) {
break; /* 命中 */
}
}
}
if (count >= maxsteps) { /* 整圈未命中,回到起始频率 */
TEF6686_Tune(band, start);
return 0;
}
CurFreq = f; /* 停在命中的频率 */
if (band == BAND_FM) FmFreq = f;
else AmFreq = f;
return 1;
}
/*----------------------------- RDS -----------------------------------*/
static TEF6686_RDS xdata Rds; /* RDS 解码结果较大,放扩展 RAM */
TEF6686_RDS *TEF6686_GetRDS(void)
{
return &Rds;
}
unsigned char TEF6686_PollRDS(unsigned char band)
{
unsigned char st[2];
unsigned char dat[12];
unsigned char r;
unsigned int status, a, b, c, d;
unsigned int dec_err;
unsigned int gt, ver, seg;
unsigned char ch1, ch2;
if (band != BAND_FM) return 0;
r = TEF6686_GetCmd(MODULE_FM, CMD_GET_RDS_STATUS, st, 2);
if (r != 1) return 0;
status = ((unsigned int)st[0] << 8) | st[1];
if ((status & 0x8000) == 0) return 0; /* 无数据可用 */
Rds.sync = (status & 0x0200) ? 1 : 0; /* 位9 = RDS 同步 */
r = TEF6686_GetCmd(MODULE_FM, CMD_GET_RDS_DATA, dat, 12);
if (r != 1) return 0;
a = ((unsigned int)dat[2] << 8) | dat[3];
b = ((unsigned int)dat[4] << 8) | dat[5];
c = ((unsigned int)dat[6] << 8) | dat[7];
d = ((unsigned int)dat[8] << 8) | dat[9];
dec_err = ((unsigned int)dat[10] << 8) | dat[11];
/* 块错误计数:dec_error[15:14]=A,[13:12]=B,[11:10]=C,[9:8]=D */
if (((dec_err >> 14) & 0x03) != 0) Rds.errA++;
if (((dec_err >> 12) & 0x03) != 0) Rds.errB++;
if (((dec_err >> 10) & 0x03) != 0) Rds.errC++;
if (((dec_err >> 8) & 0x03) != 0) Rds.errD++;
Rds.pi = a; /* PI 码在块 A */
gt = (b >> 11) & 0x0F; /* 组类型 0..15(位 14..11) */
ver = (b >> 15) & 0x01; /* 0 = A 型, 1 = B 型 */
Rds.tp = (b & 0x0400) ? 1 : 0; /* TP 位 10 */
Rds.pty = (unsigned char)((b >> 5) & 0x1F); /* PTY 位 9..5 */
if (gt == 0) { /* 组 0:PS 台名 */
if (ver == 0) { /* 0A */
seg = (c >> 8) & 0x03; /* C1/C0 位 9..8 选择 PS 字符对 */
ch1 = (unsigned char)(d & 0xFF);
ch2 = (unsigned char)((d >> 8) & 0xFF);
Rds.ps[seg * 2] = (ch1 >= 0x20 && ch1 <= 0x7E) ? ch1 : ' ';
Rds.ps[seg * 2 + 1] = (ch2 >= 0x20 && ch2 <= 0x7E) ? ch2 : ' ';
Rds.ps[RDS_PS_LEN] = 0;
Rds.ta = (b & 0x0010) ? 1 : 0; /* TA 位 4 */
Rds.ms = (b & 0x0008) ? 1 : 0; /* M/S 位 3 */
if (seg == 3) Rds.ps_ready = 1;
} else { /* 0B:PI 在块 C,段地址在块 B 位 1:0 */
Rds.pi = c;
seg = b & 0x03;
ch1 = (unsigned char)(d & 0xFF);
ch2 = (unsigned char)((d >> 8) & 0xFF);
Rds.ps[seg * 2] = (ch1 >= 0x20 && ch1 <= 0x7E) ? ch1 : ' ';
Rds.ps[seg * 2 + 1] = (ch2 >= 0x20 && ch2 <= 0x7E) ? ch2 : ' ';
Rds.ps[RDS_PS_LEN] = 0;
Rds.ta = (b & 0x0010) ? 1 : 0;
Rds.ms = (b & 0x0008) ? 1 : 0;
if (seg == 3) Rds.ps_ready = 1;
}
}
else if (gt == 2) { /* 组 2:RT 广播文本 */
if (ver == 0) { /* 2A */
seg = b & 0x0F;
Rds.rt[seg * 4] = (unsigned char)(c & 0xFF);
Rds.rt[seg * 4 + 1] = (unsigned char)((c >> 8) & 0xFF);
Rds.rt[seg * 4 + 2] = (unsigned char)(d & 0xFF);
Rds.rt[seg * 4 + 3] = (unsigned char)((d >> 8) & 0xFF);
Rds.rt[64] = 0;
if (seg == 15) Rds.rt_ready = 1;
} else { /* 2B:PI 在块 C */
Rds.pi = c;
seg = b & 0x0F;
Rds.rt[seg * 2] = (unsigned char)(d & 0xFF);
Rds.rt[seg * 2 + 1] = (unsigned char)((d >> 8) & 0xFF);
Rds.rt[64] = 0;
if (seg == 31) Rds.rt_ready = 1;
}
}
else if (gt == 3) { /* 组 3:AF / EON */
if (ver == 0) {
unsigned int variant = (c >> 12) & 0x07; /* 位 14..12 */
if (variant == 0) {
/* variant 0:block C 高 8 位 = ECC;
block D 高 2 位 = LIC,block D 低字节 = 一个 AF 码 */
Rds.ecc = (unsigned char)((c >> 8) & 0xFF);
Rds.lic = (unsigned char)((d >> 14) & 0x03);
Rds.af[0] = (unsigned char)(d & 0xFF);
Rds.af_count = 1;
} else {
/* variant 1..4:EON 服务的 PI + 4 个 AF 码 */
Rds.eon_pi = a;
Rds.eon_pi_valid = 1;
Rds.af[0] = (unsigned char)((c >> 8) & 0xFF);
Rds.af[1] = (unsigned char)(c & 0xFF);
Rds.af[2] = (unsigned char)((d >> 8) & 0xFF);
Rds.af[3] = (unsigned char)(d & 0xFF);
Rds.af_count = 4;
}
}
}
else if (gt == 4) { /* 组 4:CT 时钟时间 */
if (ver == 0) {
Rds.ct_hour = RDS_BCD((c >> 8) & 0xFF);
Rds.ct_min = RDS_BCD(c & 0xFF);
Rds.ct_day = RDS_BCD((d >> 6) & 0x3F);
Rds.ct_month = RDS_BCD((d >> 2) & 0x0F);
Rds.ct_year = (unsigned char)(d & 0x03); /* 仅低 2 位 */
Rds.ct_valid = 1;
}
}
else if (gt == 15) { /* 组 15:RT+ */
if (ver == 0) {
Rds.rt_plus_type = (unsigned char)((c >> 10) & 0x3F);
Rds.rt_plus_start = (unsigned char)((d >> 12) & 0x0F);
Rds.rt_plus_len = (unsigned char)((d >> 6) & 0x3F);
Rds.rt_plus_running = (unsigned char)((d >> 5) & 0x01);
Rds.rt_plus_valid = 1;
}
}
Rds.groups++;
return 1;
}
/*----------------------------- application state ---------------------*/
/* CurBand/CurFreq/FmFreq/AmFreq/TuneMode 已在搜台段前向声明 */
static int Volume;
static unsigned char Muted;
static unsigned char SqEnabled; /* 静噪开关(映射为搜台电平门限) */
void TuneFreq(unsigned char up)
{
TuneMode = 0; /* 手动步进 */
if (CurBand == BAND_FM) {
if (up) {
if (CurFreq + FM_FREQ_STEP > FM_FREQ_MAX) CurFreq = FM_FREQ_MIN;
else CurFreq += FM_FREQ_STEP;
}
else {
if (CurFreq - FM_FREQ_STEP < FM_FREQ_MIN) CurFreq = FM_FREQ_MAX;
else CurFreq -= FM_FREQ_STEP;
}
FmFreq = CurFreq;
}
else {
if (up) {
if (CurFreq + AM_FREQ_STEP > AM_FREQ_MAX) CurFreq = AM_FREQ_MIN;
else CurFreq += AM_FREQ_STEP;
}
else {
if (CurFreq - AM_FREQ_STEP < AM_FREQ_MIN) CurFreq = AM_FREQ_MAX;
else CurFreq -= AM_FREQ_STEP;
}
AmFreq = CurFreq;
}
TEF6686_Tune(CurBand, CurFreq);
}
void SwitchBand(void)
{
if (CurBand == BAND_FM) {
CurBand = BAND_AM;
if (AmFreq == 0) AmFreq = AM_FREQ_MIN;
CurFreq = AmFreq;
}
else {
CurBand = BAND_FM;
if (FmFreq == 0) FmFreq = FM_FREQ_MIN;
CurFreq = FmFreq;
}
TEF6686_SetBand(CurBand);
TEF6686_Tune(CurBand, CurFreq);
}
void HandleKey()
{
// static unsigned int pressTick0, pressTick1; /* 按下时刻(10ms 单位) */
// static unsigned char longDone0, longDone1; /* 长按已触发标志 */
/* // KEY_UP:短按手动上步进,长按向上自动搜台
if (KeySta0 != backup0)
{ //当前值与前次值不相等说明此时KEY_UP按键有动作
if(backup0==1)
{
pressTick0 = SysTick;P00=!P00;
longDone0 = 0;
TuneFreq(1);//
}
else
{ // 松开:清除长按标志
longDone0 = 1;
}
backup0 = KeySta0;//更新备份为当前值,以备进行下次比较
}
if (KeySta0 == 0 && !longDone0)
{ // 长按 500ms(50 * 10ms)触发自动搜台
if ((unsigned int)(SysTick - pressTick0) >= 50)
{
longDone0 = 1;P01=!P01;
TuneMode = 1;
TEF6686_Seek(CurBand, 1);
}
}
// KEY_DOWN:短按手动下步进,长按向下自动搜台
if (KeySta1 != backup1)
{ //当前值与前次值不相等说明此时KEY_DOWN按键有动作
if(backup1==1)
{
pressTick1 = SysTick;P02=!P02;
longDone1 = 0;
TuneFreq(0);
}
else
{
longDone1 = 1;
}
backup1 = KeySta1;//更新备份为当前值,以备进行下次比较
}
if (KeySta1 == 0 && !longDone1)
{
if ((unsigned int)(SysTick - pressTick1) >= 50)
{
longDone1 = 1;P03=!P03;
TuneMode = 1;
TEF6686_Seek(CurBand, 0);
}
}*/
// KEY_UP:短按自动搜台
if (KeySta0 != backup0)
{ //当前值与前次值不相等说明此时KEY_UP按键有动作
if(backup0==1)
{
TEF6686_Seek(CurBand, 1);
}
backup0 = KeySta0;//更新备份为当前值,以备进行下次比较
}
// KEY_DOWN:短按向下自动搜台
if (KeySta1 != backup1)
{ //当前值与前次值不相等说明此时KEY_DOWN按键有动作
if(backup1==1)
{
TEF6686_Seek(CurBand, 0);
}
backup1 = KeySta1;//更新备份为当前值,以备进行下次比较
}
if (KeySta2 != backup2)
{ //当前值与前次值不相等说明此时KEY_VOLUP按键有动作
if(backup2==1)
{
Volume += 5;
if (Volume > 24) Volume = 24;
TEF6686_SetVolume(Volume);
}
backup2 = KeySta2;//更新备份为当前值,以备进行下次比较
}
if (KeySta3 != backup3)
{ //当前值与前次值不相等说明此时KEY_VOLDN按键有动作
if(backup3==1)
{
Volume -= 5;
if (Volume < -60) Volume = -60;
TEF6686_SetVolume(Volume);
}
backup3 = KeySta3;//更新备份为当前值,以备进行下次比较
}
if (KeySta4 != backup4)
{ //当前值与前次值不相等说明此时KEY_BAND按键有动作
if(backup4==1)
{
SwitchBand();
TuneMode = 0; /* 换波段回到手动 */
}
backup4 = KeySta4;//更新备份为当前值,以备进行下次比较
}
if (KeySta5 != backup5)
{ //当前值与前次值不相等说明此时KEY_MUTE按键有动作
if(backup5==1)
{
Muted ^= 1;
TEF6686_Mute(Muted);
}
backup5 = KeySta5;//更新备份为当前值,以备进行下次比较
}
}
void Timer0_Init(void)//2ms
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Uart1_Init(void) //115200bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE8; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
void UART_Send_Byte(unsigned char mydata) //串口发送一字节
{
SBUF=mydata;
while(!TI);
TI=0;
}
// 串口发送字符串
void UART_SendString(char *str) {
while (*str) {
UART_Send_Byte(*str++);
}
}
/*==================== UART 状态输出(GBK 中文)=====================*/
/* 发送有符号十进制数 */
void UART_SendNum(int v)
{
char buf[7];
char i = 0;
if (v < 0) { UART_Send_Byte('-'); v = -v; }
do { buf[i++] = (char)('0' + (v % 10)); v /= 10; } while (v);
while (i) UART_Send_Byte(buf[--i]);
}
/* 发送 0.1 单位值:v=425 -> "42.5" */
void UART_SendTenth(unsigned int v)
{
UART_SendNum((int)(v / 10));
UART_Send_Byte('.');
UART_Send_Byte((char)('0' + (v % 10)));
}
/* 发送 16 位十六进制 */
void UART_SendHex(unsigned int v)
{
char i;
char c;
for (i = 3; i >= 0; i--) {
c = (char)((v >> (i * 4)) & 0x0F);
UART_Send_Byte((c < 10) ? ('0' + c) : ('A' + c - 10));
}
}
/* 发送 10 格柱条,val/max 比例填充 */
void UART_SendBar(unsigned int val, unsigned int max)
{
char i;
char n = 0;
if (max) n = (char)((val * 10) / max);
if (n > 10) n = 10;
for (i = 0; i < 10; i++)
UART_Send_Byte((i < n) ? '#' : '-');
}
/* 周期调用:输出一行完整状态(GBK 编码中文) */
void UART_SendStatus(void)
{
TEF6686_Quality q;
TEF6686_RDS *r;
unsigned char i;
if (!TEF6686_GetQualityData(CurBand, &q)) {
UART_SendString("质量读取失败\r\n");
return;
}
r = TEF6686_GetRDS();
/* 波段 + 频率(0.01MHz 精度) */
if (CurBand == BAND_FM) {
UART_SendString("FM ");
UART_SendNum((int)(CurFreq / 100));
UART_Send_Byte('.');
if ((CurFreq % 100) < 10) UART_Send_Byte('0');
UART_SendNum((int)(CurFreq % 100));
UART_SendString("MHz ");
} else {
UART_SendString("AM ");
UART_SendNum((int)CurFreq);
UART_SendString("kHz ");
}
UART_SendString("\r\n");//换行
/* 调谐模式 MAN/AUTO */
UART_SendString(TuneMode ? "AUTO " : "MAN ");
/* 场强 dBuV + 柱条(0..60 dBuV 满格) */
UART_SendString("场强:");
if (q.level < 0) {
UART_Send_Byte('-');
UART_SendTenth((unsigned int)(0 - q.level));
} else {
UART_SendTenth((unsigned int)q.level);
}
UART_SendString("dBuV[");
UART_SendBar((unsigned int)(q.level < 0 ? 0 : q.level), 600);
UART_Send_Byte(']');
UART_SendString("\r\n");//换行
/* 静噪 SQ */
UART_SendString(" 静噪SQ:");
UART_SendString(SqEnabled ? "开" : "关");
if (CurBand == BAND_FM) {
/* USN/WAM 干扰(0.1%) */
UART_SendString(" 超声噪声USN:");
UART_SendTenth(q.usn);
UART_SendString("% 多径干扰WAM:");
UART_SendTenth(q.wam);
UART_SendString("%");
}
UART_SendString("\r\n");//换行
/* 中频偏移(0.1kHz 有符号) */
UART_SendString(" 偏移:");
if (q.offset >= 0) UART_Send_Byte('+');
UART_SendNum((int)q.offset / 10);
UART_Send_Byte('.');
UART_Send_Byte((char)('0' + ((q.offset < 0) ? (-q.offset) % 10 : q.offset % 10)));
UART_SendString("kHz");
/* 带宽(0.1kHz) */
UART_SendString(" 带宽:");
UART_SendNum((int)(q.bandwidth / 10));
UART_SendString("kHz");
UART_SendString("\r\n");//换行
/* 调制度 S/M 双条(0..100% 满格) */
UART_SendString(" 调制S:");
UART_SendBar(q.modulation, 1000);
UART_SendString(" M:");
UART_SendBar(q.modulation, 1000);
UART_SendString("\r\n");//换行
/* RDS 状态(仅 FM) */
if (CurBand == BAND_FM) {
UART_SendString(" RDS:");
UART_SendString(r->sync ? "已锁定" : "未锁定");
UART_SendString("\r\n");//换行
if (r->ps_ready) {
UART_SendString(" 电台名PS=");
UART_SendString((char *)r->ps);
}
UART_SendString(" 节目类型PTY=");
UART_SendNum((int)r->pty);
UART_SendString("\r\n");//换行
UART_SendString(" 交通广播通告TP=");
UART_SendNum((int)r->tp);
UART_SendString(" TA=");
UART_SendNum((int)r->ta);
UART_SendString("\r\n");//换行
UART_SendString(" 音乐/语音M/S=");
UART_SendNum((int)r->ms);
UART_SendString(" 节目识别码PI=");
UART_SendHex(r->pi);
UART_SendString("\r\n");//换行
if (r->ct_valid) {
UART_SendString(" 时间信息CT=");
UART_SendNum((int)r->ct_hour);
UART_Send_Byte(':');
if (r->ct_min < 10) UART_Send_Byte('0');
UART_SendNum((int)r->ct_min);
}
UART_SendString("\r\n");//换行
if (r->af_count) {
UART_SendString(" 电台备选频率AF=");
for (i = 0; i < r->af_count; i++) {
if (r->af[i] >= 1 && r->af[i] <= 204) {
UART_SendNum((int)(875 + r->af[i]) / 10);
UART_Send_Byte('.');
UART_Send_Byte((char)('0' + ((875 + r->af[i]) % 10)));
UART_SendString("MHz ");
}
}
}
UART_SendString("\r\n");//换行
if (r->eon_pi_valid) {
UART_SendString(" EON服务_PI=");
UART_SendHex(r->eon_pi);
UART_SendString(" ECC=");
UART_SendNum((int)r->ecc);
}
UART_SendString("\r\n");//换行
if (r->rt_plus_valid) {
UART_SendString(" RT+[");
UART_SendNum((int)r->rt_plus_start);
UART_Send_Byte('+');
UART_SendNum((int)r->rt_plus_len);
UART_Send_Byte(']');
}
UART_SendString("\r\n");//换行
if (r->rt_ready) {
UART_SendString(" RT文本=");
UART_SendString((char *)r->rt);
}
UART_SendString("\r\n");//换行
UART_SendString(" 块错误A:");
UART_SendNum((int)(r->errA & 0xFF));
UART_SendString(" B:");
UART_SendNum((int)(r->errB & 0xFF));
UART_SendString(" C:");
UART_SendNum((int)(r->errC & 0xFF));
UART_SendString(" D:");
UART_SendNum((int)(r->errD & 0xFF));
}
UART_SendString("\r\n");
}
void Timer0_ISR(void) interrupt 1
{
static unsigned char keybuf [6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//按键扫描缓冲区,保存一段时间内的扫描值
static cnt=0;
cnt++;
if(cnt>=5) //10ms
{
cnt=0;
if(SysTick<65535) SysTick++;//防溢出自加
}
/*************************按键扫描***************************/
keybuf[0] = (keybuf[0]<<1) | KEY_UP;//缓冲区左移一位,并将当前KEY_UP扫描值移入最低位
keybuf[1] = (keybuf[1]<<1) | KEY_DOWN;//缓冲区左移一位,并将当前KEY_DOWN扫描值移入最低位
keybuf[2] = (keybuf[2]<<1) | KEY_VOLUP;//缓冲区左移一位,并将当前KEY_VOLUP扫描值移入最低位
keybuf[3] = (keybuf[3]<<1) | KEY_VOLDN;//缓冲区左移一位,并将当前KEY_VOLDN扫描值移入最低位
keybuf[4] = (keybuf[4]<<1) | KEY_BAND;//缓冲区左移一位,并将当前KEY2扫描值移入最低位
keybuf[5] = (keybuf[5]<<1) | KEY_MUTE;//缓冲区左移一位,并将当前KEY3扫描值移入最低位
if (keybuf[0] == 0x00) KeySta0 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_UP按键已按下
else if (keybuf[0] == 0xFF) KeySta0 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_UP按键已弹起
if (keybuf[1] == 0x00) KeySta1 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_DOWN按键已按下
else if (keybuf[1] == 0xFF) KeySta1 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_DOWN按键已弹起
if (keybuf[2] == 0x00) KeySta2 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_VOLUP按键已按下
else if (keybuf[2] == 0xFF) KeySta2 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_VOLUP按键已弹起
if (keybuf[3] == 0x00) KeySta3 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_VOLDN按键已按下
else if (keybuf[3] == 0xFF) KeySta3 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_VOLDN按键已弹起
if (keybuf[4] == 0x00) KeySta4 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_BAND按键已按下
else if (keybuf[4] == 0xFF) KeySta4 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_BAND按键已弹起
if (keybuf[5] == 0x00) KeySta5 = 0;//连续 8 次扫描值都为 0,即 16ms 内都只检测到按下状态时,可认为KEY_MUTE按键已按下
else if (keybuf[5] == 0xFF) KeySta5 = 1;//连续 8 次扫描值都为 1,即 16ms 内都只检测到弹起状态时,可认为KEY_MUTE按键已弹起
}
/* ==========================================
EC11 编码器轮询扫描函数 (查表法)
========================================== */
void EC11_Scan(void)
{
u8 current_state;
s8 direction;
/*
* 1. 读取当前A、B相的状态
* 注意:必须先将 sbit 强转为 u8 才能进行位运算,
* 否则 Keil C51 会报 invalid left operand type 错误。
*/
current_state = ((u8)EC11_A << 1) | (u8)EC11_B;
/* 2. 如果状态没有发生变化,直接返回,节省CPU时间 */
if (current_state == last_state)
{
return;
}
/* 3. 查表获取方向
* 将上一次的状态左移2位作为高2位,当前状态作为低2位,
* 组合成一个 0~15 的索引,直接查表。
*/
direction = EC11_Table[(last_state << 2) | current_state];
/* 4. 根据查表结果修改数值 */
if (direction == 1)
{
g_value++;
TuneFreq(1);
}
else if (direction == -1)
{
g_value--;
TuneFreq(0);
}
/* 5. 更新上一次的状态 */
last_state = current_state;
}
void IO_Init ()//IO初始化
{
P0M0 = 0X00; P0M1 = 0X00;
P1M0 = 0X00; P1M1 = 0X00;
P2M0 = 0X00; P2M1 = 0X00;
P3M0 = 0X00; P3M1 = 0X00;
P4M0 = 0X00; P4M1 = 0X00;
P5M0 = 0X00; P5M1 = 0X00;
I2C_SDA = 1;
I2C_SCL = 1;
KEY_UP = 1;
KEY_DOWN = 1;
KEY_VOLUP = 1;
KEY_VOLDN = 1;
KEY_BAND = 1;
KEY_MUTE = 1;
EC11_A = 1;
EC11_G = 0;
EC11_B = 1;
}
/* ===================== 主函数 ===================== */
void main(void)
{
unsigned int lastTick;
// unsigned char ev;
uchar i,j;
WTST = 0;
EAXFR = 1;
CKCON = 0;
IO_Init ();//IO初始化
S1_S1=0;S1_S0=1;//串口1切换到3.6 3.7
Uart1_Init();
EA=1;
/* 初始化:读取当前引脚状态作为初始状态 */
last_state = ((u8)EC11_A << 1) | (u8)EC11_B;
CurBand = BAND_FM;
CurFreq = FM_FREQ_MIN;
FmFreq = FM_FREQ_MIN;
AmFreq = 0;
Volume = 0;
Muted = 0;
TuneMode = 0;
SqEnabled = 1; /* 默认开启静噪(映射搜台电平门限) */
lastTick = 0;
Timer0_Init();
for(i=0;i<16;i++)
TEF6686_DAT[i]=0;
TEF6686_DelayMs(200);
TEF6686_Init();
TEF6686_SetVolume(Volume);
TEF6686_SetBand(CurBand);
TEF6686_Tune(CurBand, CurFreq);
UART_SendString("TEF6686 初始化完成\r\n");
while(1)
{
/* 每 10ms 检查一次状态节拍 */
if (SysTick != lastTick) {
lastTick = SysTick;
if ((SysTick % 10) == 0) { //每 100ms 轮询一次 RDS
TEF6686_PollRDS(CurBand);
}
if ((SysTick % 100) == 0) { //每 1s 输出一行完整状态
UART_SendStatus();
}
}
HandleKey();
EC11_Scan();//编码器扫描
// P00=P25;
// P01=P27;
}
}
整个程序用到6个按键加一个EC11旋转编码器控制,按键控制上下自动搜台,音量加减,FM/AM中波转换,静音功能,旋转编码器控制0.1MHz步进微调。还没加彩屏驱动,RDS功能还没法验证,因为附近没有带RDS信息的广播台,用了自制的si4713发送rds信息,已确定能解码出电台名和PI码。
DIY爱好者可以拿去试用改编。
更多推荐



所有评论(0)