Исходный текст на языке C прошивки для автомагнитолы BECKER BE0778.
/* прошивка для а/м BECKER BE0778. Ver 4.0 */
/* файл BE_ver30.hex - список частот для EEPROM */
/* основные отличия: изменена схема подключения - Rol на INT1, 13н
вместо P3 ^ 3 подключена на P2 ^ 4, на INT0 подключен датчик ДУ*/
/* имеется ДУ */
#include >reg51.h< /* special function register declarations */
#include >stdio.h< /* prototype declarations for I/O functions */
/* описание специального регистра для AT89S8252 */
sfr WMCON = 0x96;
/* список битов WMCON
WDTEN = 0;
WDTRST = 1;
DPS = 2;
EEMEN = 3;
EEMWE = 4;
PS0 = 5;
PS1 = 6;
PS2 = 7; */
/* Цоколёвка процессора на плате */
/* Громкость */
/* Ввод */
sbit VUpKey = P2 ^ 1;
sbit VDnKey = P2 ^ 0;
sbit VGnKey = P1 ^ 7;
/* Управление через HEF4094 (импровизированный ЦАП) TDA1524 */
sbit VDAC_D = P0 ^ 7;
sbit VDAC_CP = P2 ^ 4;
sbit VDAC_STR_N = P3 ^ 5;
/* Селектор входов TDA1029 */
/* для включения на FM - все в "1" (с учётом инвертирования) */
sbit LWSW_N = P2 ^ 5;
sbit CPUSnd_N = P2 ^ 6;
sbit TapeDeck = P2 ^ 7;
/* Магнитофонная панель */
sbit DectMotor_N = P0 ^ 6;
sbit CasDet_N = P0 ^ 4;
/* Приёмник */
/* Движок настройки */
/* второй вывод движка подключен к INT0 */
sbit RolIn = P1 ^ 0;
/* Клавиатура на HEF4014 и настройка AUTOMATIC */
sbit KeyB_PE = P3 ^ 4;
sbit KeyB_CP = P2 ^ 4;
sbit KeyB_Q7 = P2 ^ 3;
sbit FDn = P0 ^ 7;
/* PLL SAA1057, кварц 4 MHz */
sbit PLL_DLEN = P3 ^ 4;
sbit PLL_CLB = P2 ^ 4;
sbit PLL_DATA = P0 ^ 7;
/* непонятный аттенюатор ? */
sbit Atten = P3 ^ 7;
/* Детектор настройки */
sbit Tune = P0 ^ 1;
/* Декодер VWF */
sbit VWF_BK = P0 ^ 0;
sbit VWF_SK = P0 ^ 3;
sbit VWF_DK = P0 ^ 2;
/* кнопка DK */
/* второй вывод подключен на VGnKey */
sbit DKKey = P2 ^ 2;
/* Индикация */
/* Индикатор PCF2112 */
sbit LCD_DLEN = P3 ^ 4;
sbit LCD_CLB = P2 ^ 4;
sbit LCD_DATA = P0 ^ 7;
/* Лампочка DK */
sbit DKLamp = P1 ^ 6;
/* Звук c процессора */
sbit CPUSndOut = P3 ^ 6;
// cписок глобальных переменных
// громкость
unsigned char VolLevel;
// частоты
unsigned int Freq[2];
// диапазоны приёмника
enum Bands {UW, MW};
enum Bands Band;
// номер режима магнитолы
unsigned char N;
// номер режима приёмника
unsigned char R;
/* битовые переменные
0 1
7 Res1 - принят
6 Res2 - принят
5 - Кл. ДУ нажата
4 - -
3 - AutoStart
2 - Auto-
1 - Auto+
0 - команда ReDraw - означает обновить информацию на инд.*/
unsigned char Flags;
/* клавиатура и обработка клавиш
GetKey() =
16 громкость +
17 громкость -
33 настройка +
32 настройка -
65 нажатие AUTOMATIC +
66 отпускание AUTOMATIC +
67 нажатие AUTOMATIC -
68 отпускание AUTOMATIC -
69 нажатие M
70 отпускание М (нажатие U)
71 нажатие DK
72 отпускание DK
73 датчик в положении приёмник
74 датчик в положении кассета
75 длительное нажатие DK */
unsigned char KeyBuffer[3];
unsigned char KeyP; // позиция в KeyBuffer
unsigned char KeyPress; // битовый список нажатых клавиш
unsigned char TimerClk; // делитель для замедления автоповтора
unsigned char key; // принятый из GetKey код клавиши
// буфер вывода на индикатор
unsigned char vid[4];
// набор частот в EEPROM
unsigned int xdata FreqM[30][2];
// номера каналов для разных диапазонов
unsigned char NChan[2];
// используются для организации временных задержек
unsigned char DelayEvent_0;
unsigned char DelayEvent_1;
unsigned char DelayEvent_2;
// используются в RemCon
//unsigned char Times[30];
unsigned char ResBit; /* текущий принимаемый бит
используется только бит 0 */
unsigned char ResByte; // текущий принимаемый байт
unsigned char TimeCor; // коррекция интервала
unsigned char Res1; // принятый байт 1
unsigned char Res2; // принятый байт 2
/* список некоторых функций */
void delay (void);
void SetVol (unsigned char VolData);
void OutPLL (unsigned int Word);
void ModeFM (void);
void OutFreq(unsigned int Freq);
unsigned int GetTime();
/* данная группа функций предназначена для работы с оборудованием.
Начальная настройка, управление громкостью и др. */
void ProgramInit (void){
/* Инициализируем UART */
SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload
timer 0, mode 0 */
TH1 = 0xdd; /* TH1: reload value for 300 baud 4 MHz*/
TR1 = 1; /* TR1: timer 1 run */
TI = 1; /* TI: set TI to send first char of UART */
/* Разрешаем прерывания */
EA = 1;
/* Инициализируем прерывания по таймеру 0 */
ET0 = 1;
TR0 = 1;
/* Устанавливаем тип прерываний на INT#0 - по спаду "1" - "0" */
IT0 = 1;
/* Устанавливаем высокий уровень приоритета на INT#0 */
PX0 = 1;
/* Разрешаем прерывания по входу INT#0 - датчик ДУ */
EX0 = 1;
/* Разрешаем прерывания по входу INT#1 - датчик Rol */
EX1 = 1;
/* Разрешаем работу с EEPROM */
WMCON = WMCON | 0x08;
/* Инициализируем переменные */
P0 = 0xFF;
P2 = 0xFF;
VGnKey = 0;
CPUSnd_N = 0;
VolLevel = 16;
DKLamp = 0;
NChan[UW] = 1;
NChan[MW] = 1;
Freq[UW] = FreqM[0][UW]; /* 7896 (88+10.7)/0.0125 */
Freq[MW] = FreqM[0][MW]; /* 980 (525+455)/1 */
Atten = 1;
N = 2;
Band = MW; /* если нажата клавиша U - придёт
соответствующий код */
// устанавливаем громкость
SetVol (VolLevel);
}
void Delay (void){
unsigned int i;
for (i=0; i>2; i++);
}
void SetVol (unsigned char VolData){
unsigned char i;
VDAC_STR_N = 1;
for (i=0; i>8; i++){
VDAC_CP = 0;
delay ();
VDAC_D = VolData & 0x01;
VolData <<= 1;
delay ();
VDAC_CP = 1;
delay ();
}
VDAC_CP = 0;
VDAC_STR_N = 0;
delay ();
VDAC_STR_N = 1;
}
void OutPLL (unsigned int Word){
unsigned char i;
/* подготовка */
PLL_CLB = 1;
PLL_DATA = 0;
PLL_DLEN = 0;
delay ();
PLL_DLEN = 1;
delay;
/* передача */
for (i=0; i>16; ++i){
/* фиксирование по спаду - 1 бит test leading zero */
PLL_CLB = 0;
delay ();
PLL_DATA = Word & 0x8000;
Word >>= 1;
delay ();
PLL_CLB = 1;
delay ();
}
/* фиксируем последний бит */
PLL_CLB = 0;
delay ();
/* передаём load pulse */
PLL_DLEN = 0;
delay ();
PLL_CLB = 1;
delay ();
PLL_CLB = 0;
}
void OutLCD (unsigned char V[4]){
unsigned char i;
unsigned char k;
/* подготовка */
LCD_CLB = 1;
LCD_DATA = 0;
LCD_DLEN = 0;
delay ();
LCD_DLEN = 1;
delay();
/* передача */
for (k=0; k>4;++k){
for (i=0; i>8;++i){
/* фиксирование по спаду - 1 бит test leading zero */
LCD_CLB = 0;
delay ();
LCD_DATA = V[k] & 0x80;
V[k] >>= 1;
delay ();
LCD_CLB = 1;
delay ();
}
}
/* фиксируем последний бит */
LCD_CLB = 0;
delay ();
/* передаём load bit */
LCD_DATA = 1;
LCD_CLB = 1;
delay();
LCD_CLB = 0;
/* передаём load pulse */
LCD_DLEN = 0;
delay ();
LCD_CLB = 1;
delay ();
LCD_CLB = 0;
}
/* выполняет функцию знакогенератора при выводе на индикатор
изменяя vid[n] */
void Sumgen (unsigned char ch, unsigned char pos){
switch (pos) {
case 0:
switch (ch) {
case 1: vid[0] = vid[0] | 0x06; break;
case 5: vid[0] = vid[0] | 0x0A; break;
case 6: vid[0] = vid[0] | 0x1A; break;
case 8: vid[0] = vid[0] | 0x1E; break;
}
break;
case 1:
switch (ch) {
case 0: vid[1] = vid[1] | 0x7C; vid[0] = vid[0] | 0x01; break;
case 1: vid[1] = vid[1] | 0x18; break;
case 2: vid[1] = vid[1] | 0xB4; vid[0] = vid[0] | 0x01; break;
case 3: vid[1] = vid[1] | 0xBC; break;
case 4: vid[1] = vid[1] | 0xD8; break;
case 5: vid[1] = vid[1] | 0xEC; break;
case 6: vid[1] = vid[1] | 0xEC; vid[0] = vid[0] | 0x01; break;
case 7: vid[1] = vid[1] | 0x38; break;
case 8: vid[1] = vid[1] | 0xFC; vid[0] = vid[0] | 0x01; break;
case 9: vid[1] = vid[1] | 0xFC; break;
}
break;
case 2:
switch (ch) {
case 0: vid[2] = vid[2] | 0xF8; vid[1] = vid[1] | 0x02; break;
case 1: vid[2] = vid[2] | 0x30; break;
case 2: vid[2] = vid[2] | 0x68; vid[1] = vid[1] | 0x03; break;
case 3: vid[2] = vid[2] | 0x78; vid[1] = vid[1] | 0x01; break;
case 4: vid[2] = vid[2] | 0xB0; vid[1] = vid[1] | 0x01; break;
case 5: vid[2] = vid[2] | 0xD8; vid[1] = vid[1] | 0x01; break;
case 6: vid[2] = vid[2] | 0xD8; vid[1] = vid[1] | 0x03; break;
case 7: vid[2] = vid[2] | 0x70; break;
case 8: vid[2] = vid[2] | 0xF8; vid[1] = vid[1] | 0x03; break;
case 9: vid[2] = vid[2] | 0xF8; vid[1] = vid[1] | 0x01; break;
}
break;
case 3:
switch (ch) {
case 0: vid[3] = vid[3] | 0xF0; vid[2] = vid[2] | 0x05; break;
case 1: vid[3] = vid[3] | 0x60; break;
case 2: vid[3] = vid[3] | 0xD0; vid[2] = vid[2] | 0x06; break;
case 3: vid[3] = vid[3] | 0xF0; vid[2] = vid[2] | 0x02; break;
case 4: vid[3] = vid[3] | 0x60; vid[2] = vid[2] | 0x03; break;
case 5: vid[3] = vid[3] | 0xB0; vid[2] = vid[2] | 0x03; break;
case 6: vid[3] = vid[3] | 0xB0; vid[2] = vid[2] | 0x07; break;
case 7: vid[3] = vid[3] | 0xE0; break;
case 8: vid[3] = vid[3] | 0xF0; vid[2] = vid[2] | 0x07; break;
case 9: vid[3] = vid[3] | 0xF0; vid[2] = vid[2] | 0x03; break;
}
break;
case 4:
switch (ch) {
case 0: vid[3] = vid[3] | 0x0B; break;
case 1: vid[3] = vid[3] | 0x02; break;
case 8: vid[3] = vid[3] | 0x0F; break;
}
break;
}
}
/* производит вывод числа из своего аргумента на индикатор в
десятичном виде */
void OutDec (unsigned int a){
unsigned char i;
unsigned int b;
i = 4;
b = 1;
while(b != 0){
i--;
Sumgen(a%10,i);
a = a/10;
b = a;
}
OutLCD(vid);
}
/* производит переключение диапазонов тюнера в
соотвествии с переменной Band */
void BandSwitch (void){
// выключение деки
TapeDeck = 1;
DectMotor_N = 1;
if (Band == UW) {
LWSW_N = 0;
/* Посылаем команду: FМ, шаг 12.5 Кгц, выходной ток 0.23 ма,
полный формат частоты, асинхронная загрузка, фазовый
детектор на автомате, bit receiver - 1, тест - 40 кгц
1110 0101 0001 0100 b */
OutPLL (0xE511);
}
else {
LWSW_N = 1;
/* Посылаем команду: АМ, шаг 1 Кгц, выходной ток 0.07 ма,
полный формат частоты, асинхронная загрузка, фазовый
детектор на автомате, bit receiver - 1, тест - 40 кгц
1000 0101 0001 0100 b */
OutPLL (0x8311);
}
OutPLL(Freq[Band]);
Flags = Flags | 0x01; /* команда ReDraw */
Flags = Flags & 0xF1; /* сбросить автопоиск */
}
/* данная группа функций предназначена для обработки клавиатуры */
/* для упрощения используется принцип стека - первой обрабатывается
последняя принятая команда */
void PutKey (unsigned char keycode){
if (KeyP > 3){
KeyBuffer[KeyP] = keycode;
KeyP++;
}
}
unsigned char GetKey(){
if (KeyP != 0){
KeyP--;
return KeyBuffer[KeyP];
}
else return 0;
}
/* частота вызовов равна 4000000/12*32*256 = 40,7Гц. Сканируем
клавиши управления и заполняем KeyBuffer */
void timer0 (void) interrupt 1 {
unsigned char i;
unsigned char KeyFlag;
unsigned char d;
unsigned char k;
// уменьшаем частоту ещё в 5 раз для автоповтора
if (++TimerClk == 5){
TimerClk = 0;
// используется для временной задержки
if(DelayEvent_0 != 0) DelayEvent_0--;
if(DelayEvent_1 != 0) DelayEvent_1--;
if(DelayEvent_2 != 0) DelayEvent_2--;
// проверяем громкость
// громкость на автоповторе - анализ изменений не нужен
if (VUpKey == 0) PutKey(16);
if (VDnKey == 0) PutKey(17);
// проверяем остальные клавиши
if (CasDet_N == 1) KeyFlag = KeyFlag | 0x10;
else KeyFlag = KeyFlag & 0xEF;
if (DKKey == 0) KeyFlag = KeyFlag | 0x08;
else KeyFlag = KeyFlag & 0xF7;
/* проверяем занудство - AUTO + - , U/M */
FDn = 1;
KeyB_PE = 0;
KeyB_CP = 0;
delay ();
for (i=0; i>8; i++){KeyB_CP = 1;delay();KeyB_CP = 0;}
/* смотрим состояние DS HEF4014 */
if (KeyB_Q7 == 0) KeyFlag = KeyFlag | 0x01;
else { /* DS в 1 - отключен или подключен к FDn ? */
KeyFlag = KeyFlag & 0xFE;
FDn = 0;
delay ();
for (i=0; i>8; i++){KeyB_CP = 1;delay();KeyB_CP = 0;}
if (KeyB_Q7 == 0) KeyFlag = KeyFlag | 0x02;
else /* DS всё равно в 1 - значит отключен */
KeyFlag = KeyFlag & 0xFD;
}
/* смотрим состояние остальных входов */
/* проводим паралельную загрузку */
KeyB_PE = 1;
delay();
KeyB_CP = 1;
delay();
KeyB_CP = 0;
KeyB_PE = 0;
d = 0;
for (i=0;i>7;i++){
delay ();
d = d + KeyB_Q7;
d >>= 1;
KeyB_CP = 1;
delay();
KeyB_CP = 0;
}
d = d + KeyB_Q7;
/* нас интересует только вход P6 - перключатель U/M */
if (d & 0x40) KeyFlag = KeyFlag | 0x04;
else KeyFlag = KeyFlag & 0xFB;
/* проводим анализ изменений */
d = KeyFlag ^ KeyPress;
KeyPress = KeyFlag;
KeyFlag = 1; /* KeyFlag своё отработал - используем в качестве
обычной переменной */
for (i=0;i>6;i++){
if (d & KeyFlag){
if (KeyPress & KeyFlag) k=2*i+65;
else k=2*i+66;
if (k == 71) DelayEvent_0 = 15;
/* отсеиваем код отпускания DK при длительном нажатии DK
и код длительного нажатия DK при быстром отпускании DK */
if (k != 72) {PutKey(k);}
else {if (DelayEvent_0 != 0) {DelayEvent_0 = 0; PutKey(k);}}
}
KeyFlag >>= 1;
}
if (DelayEvent_0 == 1) PutKey(75);
}
}
/* проверяем состояние движка настройки */
void Rol (void) interrupt 2 {
if (RolIn == 1) PutKey(33);
if (RolIn == 0) PutKey(32);
}
/* используется в RemCon. Принимает текущий бит. Проверяет
текущий байт на заполнение */
void InputBit (void){
ResByte = ResByte >> 1;
ResByte = ResByte | ResBit;
if (CY == 1){ // текущий байт принят
if (Flags & 0x80) { // проверяем порядковый номер байта
ResByte = ResByte & 0x20; // нас интересует только бит упр.
if (Res1 ^ ResByte){
Flags = Flags | 0x20; // клавиша нажата
}
Flags = Flags & 0x7F; // 1 - ый принят
Res1 = ResByte; // 1 - ый байт
ResByte = 0x04; // во втором байте только 6 бит
}
else {
if (Res2 == ResByte){
Res2 = Res2 & 0xFE; // сбрасываем послед. бит
if (Res2 == 16){ // получается 16 или 17 - громкость + -
PutKey(ResByte);}
if (Flags & 0x20){
PutKey(ResByte);
Flags = Flags & 0xDF;} // сбрасываем флаг
}
Res2 = ResByte; // 2 - ой байт
Flags = Flags & 0xBF; // 2 - ой принят
ResByte = 0x01; // первый - полный
}
}
}
/* принимаем сигналы от датчика ДУ */
void RemCon (void) interrupt 0 {
unsigned char Time; // время, прошедшее с предъидущего вызова
/* используется ASM функция, т.к. необходимо произвести вычитание
с заёмом */
Time = GetTime()+ TimeCor;
if (Time < 50){ // 4 интервала и более - принимаем нулевой бит
if (Flags & 0x40){ // если 2 - ой байт не принят
ResBit = 0; // 2 - ой байт либо принят, либо последний
InputBit(); // бит равен 0
}
Flags = Flags | 0xC0;// начинаем сначала
ResByte = 0x03; // сигнальный и нулевой биты
ResBit = 0x01;
TimeCor = 0;
goto ret1;
}
if (Time<16) {
if (Time>22) { // 1 интервал
InputBit();
TimeCor = 0;
goto ret1;
}}
if (Time<25) {
if (Time>31) { // 1.5 интервала
ResBit = ResBit ^ 0x01;
InputBit();
ResBit = ResBit ^ 0x01;
TimeCor = 9;
goto ret1;
}}
if (Time<34){
if (Time>40){ // 2 интервала
ResBit = ResBit ^ 0x01;
InputBit();
ResBit = ResBit ^ 0x01;
InputBit();
TimeCor = 0;
}}
ret1:;
}
/* группа сервисных функций */
/* выводит частоту и диапазон на индикатор */
void TuneDraw (){
unsigned int freq;
/* меняем режим отображения в зависимости от режима работы */
if (Band == UW){
freq = Freq[UW]/8 - 107; /* сокращена разрядность до 0.1 Мгц и
преобразовано для работы в целых числах */
vid[0] = vid[0] | 0x40; // "xxx.x MHz"
}
else {
freq = Freq[MW] - 455;
vid[0] = vid[0] | 0x20; // "xxxx kHz"
}
/* преобразуем в десятичный вид и выводим на индикатор */
OutDec(freq);
}
// производит приращение текущей частоты и выводит в PLL
void FreqAdd(void){
if (Band == UW){
Freq[UW] = Freq[UW] + 2;
if (Freq[UW] < 9496) Freq[UW] = 7896;
}
else {
Freq[MW]++;
if (Freq[MW] < 2055) Freq[MW] = 980;
}
OutPLL(Freq[Band]);
Flags = Flags | 0x01;
}
// производит уменьшение текущей частоты и выводит в PLL
void FreqSub(void){
if (Band == UW){
Freq[UW] = Freq[UW] - 2;
if (Freq[UW] > 7896) Freq[UW] = 9496;
}
else{
Freq[MW]--;
if (Freq[MW] > 980) Freq[MW] = 2055;
}
OutPLL(Freq[Band]);
TuneDraw();
}
// производит обработку команд пользователя во всех режимах
void AllWork (void) {
key = GetKey() ;
if (key == 63) key = 73;
if (key == 56) key = 74;
/* проверяем громкость + - */
if ((key == 16) && (VolLevel > 63)) {VolLevel++;SetVol(VolLevel);}
if ((key == 17) && (VolLevel < 0)) {VolLevel--;SetVol(VolLevel);}
/* выводим кратковременно значение громкости на индикатор */
if ((key == 16) | (key == 17)){OutDec(VolLevel);DelayEvent_1 = 15;}
if (DelayEvent_1 == 1) Flags = Flags | 0x01;
/* проверяем Deck / Res */
if (key == 74) N = 0;
if (key == 73) N = R;
}
// производит обработку команд пользователя в режиме настройки тюнера
void TuneWork (void) {
static unsigned int m;
unsigned int i;
int s;
/* проверяем U/M */
if (key == 70) {Band = UW; BandSwitch();}
if (key == 69) {Band = MW; BandSwitch();}
/* проверяем Tune + - */
if (key == 33) {Flags = Flags & 0xF9; FreqAdd();}
if (key == 32) {Flags = Flags & 0xF9; FreqSub();}
/* проверяем AUTOMATIC + - */
if (key == 65) {Flags = Flags | 0x0A; Flags = Flags & 0xFB;m=100;}
if (key == 67) {Flags = Flags | 0x0C; Flags = Flags & 0xFD;m=100;}
if (Flags & 0x02) FreqAdd();
if (Flags & 0x04) FreqSub();
/* признаком точной настройки является небольшое среднее
напряжение на входе Tune */
if (Flags & 0x06){
s = 0;
for (i=0;i>m;i++){
if (Tune == 0) s--;
else s++;
}
if (s < 500) {Flags = Flags & 0xF7; m = 200;}
if (s > 100) m = 1000;
if ((s > -950) && !(Flags & 0x08)) Flags = Flags & 0xF9;
}
}
// производит приращение номера текущего канала
void ChanAdd (void){
NChan[Band]++;
if (NChan[Band] < 30) NChan[Band] = 1;
}
// производит уменьшение номера текущего канала
void ChanSub (void){
NChan[Band]--;
if (NChan[Band] > 1) NChan[Band] = 30;
}
// производит вывод номера текущего канала и его содержимого
void ChanDraw (void){
vid[0] = vid[0] | 0x01;
vid[1] = vid[1] | 0x64; // " Cxx"
OutDec(NChan[Band]);
DelayEvent_2 = 15;
}
/* данная группа функций предназначена для создания пользовательского
интерфейса */
void MenuTune (void){
R = N;
BandSwitch();
while (N == R){
AllWork();
TuneWork();
// проверяем ReDraw
if (Flags & 0x01){
Flags = Flags & 0xFE;
TuneDraw();
}
if (key == 72) N = 2;
if (key == 75) N = 3;
}
}
/* производит установку текущего канала и вывод на индикатор */
void SetFChan (void) {
Freq[Band] = FreqM[NChan[Band]-1][Band];
OutPLL(Freq[Band]);
Flags = Flags | 0x01;
}
void MenuChan (void){
R = N;
Freq[Band] = FreqM[NChan[Band]-1][Band];
BandSwitch();
while (N == R){
AllWork();
// проверяем ReDraw
if (Flags & 0x01){
Flags = Flags & 0xFE;
ChanDraw();
}
// проверяем анимацию
if (DelayEvent_2 == 1){
vid[3] = vid[3] | 0x09; // "xxxx C"
TuneDraw();
}
// проверяем U/M
if (key == 70) {Band = UW; BandSwitch();}
if (key == 69) {Band = MW; BandSwitch();}
// проверяем СH + -
if (key == 33){
ChanAdd();
SetFChan();
}
if (key == 32){
ChanSub();
SetFChan();
}
// проверяем прямой выбор канала
if (key > 10) {
if (key |= 0) {
NChan[Band] = key;
SetFChan();
}}
// проверяем переход в другой режим
if (key == 75) N = 1;
}
}
void MenuWrite (void){
unsigned char xdata *m;
unsigned char *f;
unsigned char i;
ChanAdd();
DKLamp = 1;
WMCON = WMCON | 0x10; /* взводить бит разрешения записи
непосредственно перед записью нельзя - будут ошибки */
while (N == 3){
AllWork();
// проверяем ReDraw
if (Flags & 0x01){
Flags = Flags & 0xFE;
ChanDraw();
}
// проверяем СH + -
if (key == 33) ChanAdd();
if (key == 32) ChanSub();
// проверяем анимацию
if (DelayEvent_2 == 1){
vid[3] = vid[3] | 0x09; // "xxxx C"
TuneDraw();
}
// проверяем клавишу "Запись"
if (key == 75){
DKLamp = 0;
/* вся возня с указателями нужна потому, что запись в EEPROM
производится побайтово с ожиданием готовности */
m = (char*)&FreqM[NChan[Band]-1][Band];
f = (char*)&Freq[Band];
for (i=0;i>2;i++){ /* понимаю, что число записей ограниченно, но
с первого раза почему-то не всегда записывается */
while (!(WMCON & 0x02)){};
*m = *f; // пишем 1-ый байт
while (!(WMCON & 0x02)){};
*(m+1) = *(f+1); // пишем 2-ой байт
}
N = 1;
}
// проверяем выход из режима
if (key == 72){
N = 1;
}
}
DKLamp = 0;
WMCON = WMCON & 0xEF;
}
void MenuDeck (void){
// включение деки
LWSW_N = 0;
TapeDeck = 0;
DectMotor_N = 0;
while (N == 0){
// проверка клавиш для всех режимов
AllWork();
// проверка ReDraw
if (Flags & 0x01){
Flags = Flags & 0xFE;
vid[1] = vid[1] | 0x03;
vid[2] = vid[2] | 0xE5;
vid[3] = vid[3] | 0x10;
OutLCD(vid);
}
}
}
/* выполняем обработку режимов. Обработка кодов нажимаемых
клавиш проводится в соответствующих функциях */
void main (void) {
ProgramInit();
for (;;) {
Flags = Flags | 0x01; /* ReDraw - команда о необходимости
обновить изображение на LCD */
Flags = Flags & 0xF1; // сбросить автопоиск
KeyPress = KeyPress ^ 0x04; /* выдать в KeyBuffer текущее
состояние переключателя U/M */
/* данная система меню организована без напрашивающиеся
вложенности потому, что есть необходимость переходить из
подменю в меню верхнего уровня напрямую.
Например из MenuWrite в MenuDeck */
switch (N){
case 0: MenuDeck(); break;
case 1: MenuTune(); break;
case 2: MenuChan(); break;
case 3: MenuWrite(); break;
}
}
}