;*******************************************************************************
.DEVICE AT90S1200
;*******************************************************************************
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; ПРОГРАММА Частотомер - шкала для UW3DI на НТ1611
; Автор UA4NX - Дергаев Эдуард Юрьевич
; ua4nx@ezmail.ru
; www.qsl.net/ua4nx
; www.kirov.ru/~ua4nx
;
; V1.01 9.01.2002 Кварц - 16000КГц, интервал счета 0,1cek;
; Программно устранено мерцание - при неизменных данных перезапись дисплея
; раз в 6 секунд.
; Исключена программно ошибка на 10 герц (один младший разряд), то есть
; точность ухудшена до 20 герц.
; В режиме частотомера кнопками грубо корректируется частота кварца, а в режиме
; шкалы - частота записанных гетеродинов.
;
;
;
;
;
; Порт D ........................ Порт В
; P3.0 - HT1611 - CLK...Out...... Р1.0 - Band 1,8 | Р1.0 и P1.1 Band 10
; P3.1 - HT1611 - DATA..Out.......P1.1 - Band 3,5 |
; P3.2 - Больше...................P1.2 - Band 7 | P1.2 и P1.3 Band 18
; P3.3 - Меньше.................. P1.3 - Band 14 |
; P3.4 - F0-вход.... .............P1.4 - Band 21 | P1.4 и P1.5 Band 24
; P3.5 - .........................P1.5 - Band 28 |
; ................................P1.6 - Band 28,5 | P1.6 и P1.7 Band 29,5
; P3.7............................P1.7 - Band 29 |
;
; Register:
.def zero =r0
.def F1 =r1; Хранить подстройку кварцевого резонатора!!!!!(0x54)
.def si =r2; Счетчик для обновления дисплея
.def F3 =r3;
.def TOV0 =r4; Сбросить бит TOV0 УСтаНОвиВ ЕГО!!!
.def LCD1_2 =r5;
.def LCD3_4 =r6;
.def LCD5_6 =r7;
.def LCD7_8 =r8;
.def LCD9_10 =r9;
.def FM1 =r10;
.def FM2 =r11;
.def FM3 =r12;
.def FM4 =r13;
.def me14 =r14; -> Предыдущее значение FM4
.def steep= r16; -> Начальный адрес ЕЕПРОМа коррекции ( три ячейки)
.def ss26 =r26; -> Счетчик для задержки клавиш
.def COR1 =r27; -> Коррекция ст.
.def COR2 =r28; -> Коррекция ср.
.def COR3 =r29; -> Коррекция мл.
.def ODIN =r30; ->
.def BAND =r31;-> код диапазона
;
;
.equ iifr=50000; значение 2й ПЧ частота опорного кварца 500 00 (500 kHz)
;
.equ ifr0= 800000 - iifr; 1.9 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr1= 1000000 - iifr; 3.5 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr2= 1350000 - iifr; 7 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr3= 1650000 - iifr; 10 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr4= 800000 + iifr; 14 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr5= 1200000 + iifr; 18 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr6= 1500000 + iifr; 21 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr7= 1880000 + iifr; 24 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr8= 2200000 + iifr; 28 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr9= 2250000 + iifr; 28,5 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr10=2300000 + iifr; 29 значение 1го гетеродина с учетом 2й ПЧ
.equ ifr11=2350000 + iifr; 29,5 значение 1го гетеродина с учетом 2й ПЧ
;*******************************************************************************
.ESEG
; Сегмент ЕЕПРОМ - записаны значения коррекции диапазонов (по 3 ячейки):
; 1.8 - 00h 3,5 - 03h 7 - 06h 10 - 09h 14 - 0Ch 18 - 0Fh 21 - 12h
; 24 - 15h 28 - 18h 28,5 - 1Bh 29 - 1Eh 29,5 - 21h Частотомер - 24h
.db byte3(ifr0),high(ifr0),low(ifr0); 1.9
.db byte3(ifr1),high(ifr1),low(ifr1); 3.5
.db byte3(ifr2),high(ifr2),low(ifr2); 7
.db byte3(ifr3),high(ifr3),low(ifr3); 10
.db byte3(ifr4),high(ifr4),low(ifr4); 14
.db byte3(ifr5),high(ifr5),low(ifr5); 18
.db byte3(ifr6),high(ifr6),low(ifr6); 21
.db byte3(ifr7),high(ifr7),low(ifr7); 24
.db byte3(ifr8),high(ifr8),low(ifr8); 28
.db byte3(ifr9),high(ifr9),low(ifr9); 28,5
.db byte3(ifr10),high(ifr10),low(ifr10); 29
.db byte3(ifr11),high(ifr11),low(ifr11); 29,5
.db 0x00,0x00,0x00; Частотомер
.db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5D
;*******************************************************************************
.CSEG
;*******************************************************************************
; Начальные установки
;*******************************************************************************
START:   ldi r18,0x0F
         out 0x21,r18         ;Включение СТОРОЖЕВОГО ТАЙМЕРА 2,048 секунды.
         clr zero
         clr band
         clr FM1
         clr FM2
         clr FM3
         clr FM4
         ldi r20,0x30         ; адрес EEPROM (30)
         out 0x1E,r20         ; адрес EEPROM (30)
         sbi 0x1C,0           ; Установка бита 0 в рег.EECR-> разрешение
         sbi 0x1C,0           ; чтения из EEPROM по адресу 30.
         in F1,0x1D           ; Данные из EEPROM -> F1 коррекция кварца
         ldi ODIN,0x01
         ldi r18,0x02
         mov TOV0,r18
         out 0x3B,zero        ; Общий регистр маски прерываний.GIMSK
         ldi r18,0x03         ;
         out 0x11,r18         ; Направление данных P3 - Ввод
         ldi r18,0xFC         ;
         out 0x12,r18         ; Включение подтягивающих резисторов Р3
         out 0x17,zero        ; Направление данных порта B Р1.0-Р1.7 -> Ввод
         ldi r18,0xFF
         out 0x18,r18         ; Включение подтягивающих резисторов Р1
         ldi r18,0x70         ;
         out 0x08,r18         ; Регистр упр. и сост. аналового компаратора.
         out 0x2F,zero
         sbi 0x12,0           ; CLK->"1"
         sbi 0x12,1           ; DATA->"1"
;*******************************************************************************
; Проверка индикации при включении - Выводятся восьмерки во всех разрядах.
;
         ldi r18,0x0A
TIT1:    ldi r25,0x88
         rcall PortD
         ldi r25,0x88
         rcall PortD
         ldi r25,0x88
         rcall PortD
         ldi r25,0x88
         rcall PortD
         ldi r25,0x88
         rcall PortD
         rcall z
         dec r18
         brne TIT1
         ldi r18,0xFF
         mov si,r18           ; Записать в SI FF, что бы сразу обновить дисплей
;*******************************************************************************
; Основная программа.
;
MAIN:    ldi r20,0x07
         out 0x33,r20         ; T/C 0 -> Запустить счет внешних импульсов
         rcall Z              ; 0,1 cek
         out 0x33,zero        ; Остановить счет Т/С 0
MAIN1:   rcall CIKL           ; !!ПОСЛЕ ОСТАНОВА СЧЕТЧИКА ПРОВЕРЯЕМ ПЕРЕПОЛНЕНИЕ
         in FM4,0x32          ; мл. Содержимое счетчика
;*******************************************************************************
; Анализ BANDa
;
; Анализируем по выводам порта какой диапазон, Выбираем константу и что с ней
; делать - складывать или вычитать.
         in r20,0x16          ; Считываем диапазон
         cp r20,BAND
         breq NN
         rcall bandcor
         mov r20,r16          ; Cменился диапазон - перезаписываем COR1... COR3
         rcall READEE
         mov COR1,r21         ; перезаписываем COR1
         rcall READEE
         mov COR2,r21         ; перезаписываем COR2
         rcall READEE
         mov COR3,r21         ; перезаписываем COR3
NN:      cpi r16,0x24         ; Band - Частотомер
         breq HD              ; Режим частотомера
         cpi r16,0x00         ; Band 1.8
         breq CORS            ; ВЫЧЕСТЬ
         cpi r16,0x03         ; Band 3.5
         breq CORS            ; ВЫЧЕСТЬ
         cpi r16,0x06         ; Band 7
         breq CORS            ; ВЫЧЕСТЬ
         cpi r16,0x09         ; Band 10
         breq CORS            ; ВЫЧЕСТЬ
; Складываем
CORA:    add FM4,COR3         ; low
         adc FM3,COR2
         adc FM2,COR1         ; higt
         rjmp HD
; Вычитаем
CORS:    mov r23,COR3
         mov r22,COR2
         mov r21,COR1
         sub r23,FM4          ; low
         sbc r22,FM3
         sbc r21,FM2          ; higt
         mov FM4,r23
         mov FM3,r22
         mov FM2,r21
HD:      mov r20,FM4
         cp r20,me14          ; сравнить текущее с предыдущим FM4
         breq HDD             ; если равно то вывести на индикацию
         inc r20              ; добавить один к текущему
         cp r20,me14          ; если равно то вывести на индикацию предыдущее
         breq HDE             ;
         mov me14,FM4         ; Если не +1 то вывести и записать новое значение
         rjmp HDI             ; Вывести на индикацию
HDE:     mov FM4,me14         ;
;*******************************************************************************
; Перевод 16h->10
;
; Исходное число ххххxxxxh FM1,FM2,FM3,FM44
; Делитель r18,r19,r20,r21
; Ответ r25
; Рабочие r15, r17, r22, r23
;
HDD:     sbrs si,6            ; бит - частота обновления неизменного значения 6-1/64
         rjmp KEY             ; если старое значение то не индицируем
HDI:     clr si               ; если не индицировали 64 раза то чистим si и на дисплей
         clr r23              ; Регистр конвертирования
         ldi r18,0x3B         ; :1 000 000 000=3B 9A CA 00
         ldi r19,0x9A
         ldi r20,0xCA
         ldi r21,0x00
         rcall DELEN
         swap r25
         mov r15,r25          ; 1 разряд
         ldi r18,0x05         ; :100 000 000=05 F5 E1 00
         ldi r19,0xF5
         ldi r20,0xE1
         rcall DELEN
         add r25,r15
         mov LCD1_2,r25       ; 1+2 разряды
         ldi r18,0x00         ; :10 000 000=00 98 96 80
         ldi r19,0x98
         ldi r20,0x96
         ldi r21,0x80
         rcall DELEN
         swap r25
         mov r15,r25          ; 3 разряд
         ldi r18,0x00         ; :1 000 000=00 0F 42 40h
         ldi r19,0x0F
         ldi r20,0x42
         ldi r21,0x40
         rcall DELEN
         add r25,r15
         mov LCD3_4,r25       ; 3+4 разряд
         ldi r19,0x01         ; :100 000=00 01 86 A0h
         ldi r20,0x86
         ldi r21,0xA0
         rcall DELEN
         swap r25
         mov r15,r25          ; 5 разряд
         ldi r19,0x00
         ldi r20,0x27         ; :10 000=00 00 27 10h
         ldi r21,0x10
         rcall DELEN
         add r25,r15
         mov LCD5_6,r25       ; 5+6 разряд
         ldi r20,0x03         ; :1 000=00 00 03 E8h
         ldi r21,0xE8
         rcall DELEN
         swap r25
         mov r15,r25          ; 7 разряд
         ldi r20,0x00
         ldi r21,0x64         ; :100=00 00 00 64h
         rcall DELEN
         add r25,r15
         mov LCD7_8,r25       ; 7+8 разряд
         ldi r21,0x0A         ; :10=00 00 00 0Ah
         rcall DELEN
         swap r25
         mov r15,r25          ; 9 разряд
         mov r25,FM4          ; 10 разряд
         rcall CONVA_0
         add r25,r15
         mov LCD9_10,r25      ; 9+10 разряд
;*******************************************************************************
; Вывести на дисплей.
;
D10:     mov r25,LCD1_2
         ldi r25,0x0B         ; Буква 0F для дисплея 0x0B
         rcall PortD
         mov r25,LCD3_4
         rcall PortD
         mov r25,LCD5_6
         rcall PortD
         mov r25,LCD7_8
         rcall PortD
         mov r25,LCD9_10
         rcall PortD
KEY:     clr FM1
         clr FM2
         clr FM3
         clr FM4
         out 0x32,zero        ; Обнулить таймер 0
;*******************************************************************************
; Опрос кнопок коррекции коррекции.
;
         inc si               ; добавить 1 в счетчик индикации
         inc ss26             ; добавить 1 в счетчик клавиш
         sbrs ss26,2          ; бит - частота автоповтора клавиш 2-0,4с; 3-0,8с
         rjmp MAIN
         clr ss26
         sbis 0x10,2
         rjmp mUP             ; Если нажата "Больше" то добавить 1 и записать в ЕЕПРОМ
         sbis 0x10,3
         rjmp mDOWN           ; Если нажата "Меньше" то вычесть 1 и записать в ЕЕПРОМ
         rjmp MAIN            ; Если не нажаты то MAIN

mUP:     cpi r16,0x24
         breq fmUP
         add COR3,ODIN        ; low добавить 1
         adc COR2,zero
         adc COR1,zero        ; higt
         rjmp ENDee
mDOWN:   cpi r16,0x24
         breq fmDOWN
         sub COR3,ODIN        ; low вычесть 1
         sbc COR2,zero
         sbc COR1,zero        ; higt
ENDee:   mov r20,r16
         mov r21,COR1         ; записать в ЕЕПРОМ COR1
         rcall WRITEE
         mov r21,COR2         ; записать в ЕЕПРОМ COR2
         rcall WRITEE
         mov r21,COR3         ; записать в ЕЕПРОМ COR3
         rcall WRITEE
         rjmp MAIN
fmUP:    inc F1
         rjmp ENDfee
fmDOWN:  dec F1
         rjmp ENDfee
ENDfee:  ldi r20,0x30         ; Адрес коррекции кварца в ЕЕПРОме 30h
         mov r21,F1           ; записать в ЕЕПРОМ F1
         rcall WRITEE
         rjmp MAIN
;*******************************************************************************
; П О Д П Р О Г Р А М М Ы
;*******************************************************************************
; Подпрограмма ЗАДЕРЖКА 0.1сек.
;
Z:       ldi r20,0x63         ; Тут 63
SOU:     ldi r21,0xFF         ; Тут FF
SOU1:    rcall CIKL
         rcall CIKL
         rcall CIKL
         rcall CIKL
         dec r21
         brne SOU1            ; Повтор FF раз.
         dec r20
         brne SOU
         mov r19,F1           ; ДЛИТЕЛЬНОСТЬ 100.005mc - 54
SOU4:    ldi r21,0x06         ; Тут 06
SOU3:    rcall CIKL
         dec r21
         brne SOU3            ; Повтор FF раз.
         dec r19
         brne SOU4            ; Повтор FF раз.
         ret

;*******************************************************************************
; Подпрограмма ЗАДЕРЖКА
;
CIKL:    in F3,0x38
         sbrc F3,1            ; Пропуск если бит TOV0 сброшен
         rjmp CIKL1
         nop
         nop                  ; НЕ ИЗМЕНЯТЬ !!!!ЗАДЕРЖКА!!!!!!!!!
         wdr
         nop
         nop
         ret
CIKL1:   add FM3,ODIN         ; Если таймер 0 переполнился то добавить 1
         adc FM2,zero
         adc FM1,zero
         out 0x38,TOV0        ; Сбросить бит TOV0 УСтаНОвиВ ЕГО!!!
         ret
;*******************************************************************************
; Подпрограмма деления
;
DELEN:   ldi r25, -1
SUBii:   inc r25
         sub FM4,r21          ; low
         sbc FM3,r20
         sbc FM2,r19
         sbc FM1,r18          ; higt
         brsh SUBi1           ; Переход если > 0
         add FM4,r21          ; low
         adc FM3,r20
         adc FM2,r19
         adc FM1,r18          ; higt
         tst r23
         breq CONV2           ; Если RAB23=0 то ненадо конвертировать
CONVA_0: tst r25
         brne CONV2
         ori r25,0x0A         ; Заменить 0 на А в мл. тетраде
CONV2:   wdr
         ret
SUBi1:   ldi r23,0xFF
         rjmp SUBii
;*******************************************************************************
;
; Подпрограмма ВЫВОД НА НТ1611
;
PortD:   ldi r17,0x08         ; Записать 8 бит
PB4:     sbi 0x12,0           ; CLK->"1"
         nop
         nop
         nop
         sbi 0x12,1           ; DATA->"1"
         adc r25,r25          ; Старший бит-> перенос
         brcs PB5             ; Если есть перенос -> PB5
         cbi 0x12,1           ; DATA->"0"
PB5:     ldi r21,15           ;
PB6:     wdr
         dec r21
         brne PB6             ; Повтор 15 раз.
         cbi 0x12,0           ; CLK->"0"
         ldi r21,15           ;
PB7:     wdr
         dec r21
         brne PB7             ; Повтор 15 раз.
         dec r17              ; RAB17-1=RAB17
         brne PB4             ; Если RAB17 не равно 0 -> PB4
         nop
         nop
         nop
         sbi 0x12,0           ; CLK->"1"
         ret
;*******************************************************************************
;
; Подпрограмма BAND - CORR.
;
BANDCOR: mov BAND,r20         ; Записать новое значение диапазона.
         cpi r20,0xFF         ; НЕ Нажато ничего - режим частотомера
         breq FREQ
         cpi r20,0xFE         ; Band 1.8
         breq Band1
         cpi r20,0xFD         ; Band 3.5
         breq Band3
         cpi r20,0xFB         ; Band 7
         breq Band7
         cpi r20,0xF7         ; Band 14
         breq Band14
         cpi r20,0xEF         ; Band 21
         breq Band21
         cpi r20,0xDF         ; Band 28
         breq Band28
         cpi r20,0xBF         ; Band 28.5
         breq Band285
         cpi r20,0xFC         ; Band 10
         breq Band10
         cpi r20,0xF3         ; Band 18
         breq Band18
         cpi r20,0xCF         ; Band 24
         breq Band24
         cpi r20,0x3F         ; Band 29.5
         breq Band295
         cpi r20,0x7F         ; Band 29
         breq Band29
         rjmp FREQ
Band1:   clr r16              ; 1.8 МГц
RETT:    ret
Band3:   ldi r16,0x03
         ret
Band7:   ldi r16,0x06
         ret
Band10:  ldi r16,0x09
         ret
Band14:  ldi r16,0x0C
         ret
Band18:  ldi r16,0x0F
         ret
Band21:  ldi r16,0x12
         ret
Band24:  ldi r16,0x15
         ret
Band28:  ldi r16,0x18
         ret
Band285: ldi r16,0x1B
         ret
Band29:  ldi r16,0x1E
         ret
Band295: ldi r16,0x21
         ret
FREQ:    ldi r16,0x24
         ret
;*******************************************************************************
; Подпрограмма WRITE EEPROM.
;
WRITEE:  out 0x1E,r20         ; регистр адреса EEPROM r20
         out 0x1D,r21         ; Записываемые данные из r21 -> EEPROM
         sbi 0x1C,2           ; Установить бит EEMWE разрешения ЗАПИСИ
         sbi 0x1C,1           ; Установить бит EEWE -> ЗАПИСЬ
WRITE1:  sbic 0x1C,1          ; Ожидаем аппаратного сброса EEWE (2,5-4 mc)
         rjmp WRITE1          ; зацикливаем
         inc r20
         ret
;*******************************************************************************
; Подпрограмма READ EEPROM r20 - Адрес ЕЕПРОМа r21 - результат
;
READEE:  out 0x1E,r20         ; адрес EEPROM r20
         sbi 0x1C,0           ; Установка бита 0 в рег.EECR-> разрешение
         sbi 0x1C,0           ; чтения из EEPROM по адресу r20.
         in r21,0x1D          ; Прочитанные данные из EEPROM -> r21
         inc r20
         ret
;###############################################################################
