; FJRX2.ASM ; ; ************************** ; * 2m Fuchsjagd Empfänger * ; ************************** ; ; Code für Fuchsjagd-Empfänger-Steuerung ; ; Unterstützt den 2m-Fuchsjagdempfänger Lvl. 3.3 auf Platine 'fjrx233.brd' ; oder der Langversion 'fjrx234.brd' ; ; Autor: Nick Roethe, DF1FO, DF1FO at darc.de ; ; Created 1.7.2004 as FJRX.ASM ; Änderungen bis Stand 3.3 ab 3.6 gelöscht ; 8.10.07 3.4: Entfernungsschätzung abschaltbar im PFuchs-Menü ; 8.10.07 3.5: Menüs wahlweise Deutsch oder Englisch (für Bryan Ackerly) ; 11.10.07 3.6: EEPROM-Save nur die geänderten Werte, jede volle Sekunde ; 64B für LCD CGRAM als Tabelle im Flash, STSI Makro optimiert, ; div. weitere Flash-Sparmassnahmen (inges. ca 400 Worte) ; Unterstützung für 3 Sprachen, im Einstellmenü wählbar ; 14.10.07 3.7: Frequenz#-Umschaltung im Mode Peilen zittersicher, ; Neue Spezial-Modi 12<>3 (NFREQ=5) und 1x2<>3 (NFREQ=6) ; Einstellmenü startet mit PFuchs ; Neuer Signalton Freq.wechsel, ; Neue Entfernungsanzeige-Korrektur im Abgleichmenü ; EEPROM Init nur aus Abgleichmenü (nicht automatisch) ; EEPROM-Layout geändert (Abgleichdaten neu eingeben!) ; 15.10.07 3.8: Niederländische Menütexte (Danke Pim Niessen und Joe Somers!) ; Altes EEPROM-Format wird automatisch auf neues migriert ; Diverse Kleinst-Änderungen ; 19.10.07 3.9: Abschwächer-Taster öffnet mit 3. Click auf 0 dB ; Diverse Fixes/Cleanup ; 22.10.07 3.A: Low Battery Alarm: Neuer Signalton, 10 sec später (für DL9TE) ; 24.10.07 4.0: Signalton Automatik-Abschwächer geändert ; 29.10.07 4.1: Frequenz-Nr.-Wechsel mit <<*>> statt <*> ; 31.12.07 4.2: Batteriealarm bei Foxoring (NFuchs=1) nur alle 5 min ; Fix: fehlende Initialisierung FRQ512 (Mode 12<>3, gefunden von Didi) ; 12. 5.08 4.3: Unnötiges PLL-Laden im Mode NFreq beseitigt (gefunden von Matthias) ; 31. 7.08 4.4: Abschwächerautomatik macht 10 dB Schritt, wenn S-Meter 6 dB über F.S. ; (übernommen aus FJRX83 0.5) ; 27. 7.09 4.5: Eingabeverriegelung (für Anfänger-Modus) ; 1. 1.10 4.6: Clean-Ups für 4.5 ; .equ VERSHI= '4' .equ VERSLO= '6' ; ; >> FUSES << : EESAVE = 0 ; =========== CKSEL = 1111, SUT = 11 ; BODEN = 0, BODLVL = 0 ; Brown-Out Erkennung @ 4V ; Ergibt Hex-Pattern D13F ; ; >> AVR-STUDIO << : Ich benutze AVR Studio 4 ; ================ und Assembler Version 1 Stand v1.74 oder höher ; Einstellungen in AVR Studio 4: ; -> Project -> Assembler Options: Assembler Version 1 ; Wrap Relative Jumps On ; -> Tools -> Options -> Editor -> Tabwidth=8 ; ; .listmac; Macro Expansion Listing On ; ;----------------------------------------------------------------------- ; .device ATmega8; Specifies Device ; ; **** I/O Register Definitions .equ SREG =$3f .equ SPH =$3e .equ SPL =$3d .equ GIMSK =$3b .equ GICR =$3b ; new name for GIMSK .equ GIFR =$3a .equ TIMSK =$39 .equ TIFR =$38 .equ SPMCR =$37 .equ I2CR =$36 .equ TWCR =$36 .equ MCUCR =$35 .equ MCUSR =$34 ; For compatibility, .equ MCUCSR =$34 ; keep both names until further .equ TCCR0 =$33 .equ TCNT0 =$32 .equ OSCCAL =$31 .equ SFIOR =$30 .equ TCCR1A =$2f .equ TCCR1B =$2e .equ TCNT1H =$2d .equ TCNT1L =$2c .equ OCR1AH =$2b .equ OCR1AL =$2a .equ OCR1BH =$29 .equ OCR1BL =$28 .equ ICR1H =$27 .equ ICR1L =$26 .equ TCCR2 =$25 .equ TCNT2 =$24 .equ OCR2 =$23 .equ ASSR =$22 .equ WDTCR =$21 .equ UBRRH =$20 ; Note! UCSRC equals UBRRH .equ EEARH =$1f .equ EEARL =$1e .equ EEDR =$1d .equ EECR =$1c .equ PORTB =$18 .equ DDRB =$17 .equ PINB =$16 .equ PORTC =$15 .equ DDRC =$14 .equ PINC =$13 .equ PORTD =$12 .equ DDRD =$11 .equ PIND =$10 .equ SPDR =$0f .equ SPSR =$0e .equ SPCR =$0d .equ UDR =$0c .equ UCSRA =$0b .equ UCSRB =$0a .equ UBRRL =$09 .equ ACSR =$08 .equ ADMUX =$07 .equ ADCSR =$06 .equ ADCH =$05 .equ ADCL =$04 .equ I2DR =$03 .equ I2AR =$02 .equ I2SR =$01 .equ I2BR =$00 .equ TWDR =$03 .equ TWAR =$02 .equ TWSR =$01 .equ TWBR =$00 ; ; **** Register Definitions .def C0 =r8 .def C1 =r9 .def XL =r26 .def XH =r27 .def YL =r28 .def YH =r29 .def ZL =r30 .def ZH =r31 ; ; **** Memory Sizes .equ RAMBEG =$60 ; First SRAM Location .equ RAMEND =$45F .equ FLASHEND =$FFF .equ E2END =$1FF ; ; **** Variablen *************************************************** .DSEG .ORG RAMBEG ; Start of RAM address range ($0060) ; ; ++ Eingestellte Parameter, werden im EEPROM gerettet EEPBEG: TBD1: .BYTE 1 ; Platzhalter, nicht benutzt FRQ1: .BYTE 2 ; Frequenz-Codewert Frequenz 1 ; 0..3360 = 143,9..148,1, LSB,MSB FRQ2: .BYTE 2 ; Frequenz-Codewort Frequenz 2 FRQ3: .BYTE 2 ; Frequenz-Codewort Frequenz 3 FRQ4: .BYTE 2 ; Frequenz-Codewort Frequenz 4 FRQX: .BYTE 1 ; Aktive Frequenz 1..4 NFOX: .BYTE 2 ; Zahl der Füchse Z,E 1..10 TFOXS: .BYTE 2 ; Fuchs-Laufzeit Sekunden Z,E 1..99 TFOXMS: .BYTE 2 ; Fuchs-Laufzeit Milli-Sekunden H,Z 0..980 in 20er Schritten PFOXBN: .BYTE 1 ; Sendeleistung Coded 0=1µW, 1=3µW..15=30W, 16=Nur dB-Anzeige NFREQ: .BYTE 1 ; Zahl der Frequ. 1..6, 5: Sondermodus 12<>3, 6: 1x2<>3 TALARM: .BYTE 2 ; EOT Alarm Vorlaufzeit 0..31 sec, 0 = Aus Z,E ACSMLV: .BYTE 1 ; Akustisches S-Meter Schwelle 0..3 Achtel LOCKED: .BYTE 1 ; $81 = Verriegelt = Anfängermode, $20 = Normal FRQ1X2: .BYTE 10 ; Modus 1x2<>3 Frequenz 1 oder 2 für Fuchs 10, 1..9 ; EEP2: ; Grenze zwischen HW-SetUp und Abgleich-Bereich ABSTAB: .BYTE 13 ; Tabelle Abschwächer-Codes 0,10,20..120 dB FFINE: .BYTE 1 ; Frequenz Fein 64 -/+ 25 = -25..+25 * 1,25 kHz UBFINE: .BYTE 1 ; Skalierungswert für Ub-Messung 0..255 FBER68: .BYTE 1 ; Frequenzbereich 0:144..146, 1:144..148 UBWBIN: .BYTE 1 ; Schwelle Batteriewarnung in 1/10 V (60..80) SPRACH: .BYTE 1 ; Sprachwahl 1=Deu, 2=Eng, 3=Ned DISTCF: .BYTE 1 ; Korrekturfaktor Entfernung -5..+5 = -/+25dB EEPCLR: .BYTE 1 ; $FF wenn EEPROM gelöscht, $A9 wenn gültig EEPEND: ; Ende der geretteten Einstellungen ; ; ++ Zustands-Variablen MODE: .BYTE 1 ; Mode (Beschreibung siehe Texte ganz unten) ; 0 = RX aus, 2 = Frequenzeingabe, 3 = Peilen ; 4..x = Hauptmenü ; $10..$1x = Untermenü Einstellungen ; $20..$2x = Untermenü Abgleich FRQBIN: .BYTE 2 ; Aktuelle Frequenz 0..3360 = 143,9..148,1, LSB,MSB FRQCHG: .BYTE 1 ; 1 = Frequenz geändert => PLL neu laden AUTOON: .BYTE 1 ; Abschwächer-Automatik ein = ' ', aus = '*' ACSMON: .BYTE 1 ; Akustisches S-Meter ein = $40, aus = $00 ACSTIM: .BYTE 1 ; Akust.S.-Meter > Schwelle, Nachlaufzeit (*100ms) FRQ: .BYTE 4 ; Frequenz-Dezimalstellen 1M,100k,10k,1k FRQXSY: .BYTE 1 ; Symbol für Frequenz 1..4 (1..4 Punkte) STOPW: .BYTE 5 ; Stopuhr Eh,Zm,Em,Zs,Es STOPWR: .BYTE 1 ; 1 = Stopuhr läuft, 0 = steht TIMER: .BYTE 4 ; Count Down Timer Zs,Es,Hms,Zms zählt in 20 ms Schritten FOX: .BYTE 2 ; Current Fox Z,E 1..10 ABSBIN: .BYTE 1 ; Abschwächer Binaer-Wert 0..24 für 0, 5, 10..120 dB ABSCHW: .BYTE 3 ; Abschwächer Anzeige 0..120 dB in 5 dB Stufen H,Z,E DIST: .BYTE 4 ; Distanz-Anzeige H,Z,E ABSVAL: .BYTE 3 ; Abschwächer Analogwert 0..255 H,Z,E FFIVAL: .BYTE 3 ; FFINE Anzeigewert -/+0..25 VZ,Z,E UBFVAL: .BYTE 3 ; UBat Korrektur UBFINE Anzeigewert 0..255 H,Z,E DCFVAL: .BYTE 2 ; Distanz Korrekturfaktor Anzeigewert VZ,E PFOX: .BYTE 4 ; Sendeleistung Watt Anzeigewert Z,E,h,z AAWAIT: .BYTE 1 ; Wartezeit nach 5dB-Auto-Abschwächung (n * 100 ms) FLATIM: .BYTE 1 ; Verbleibende Flashtime für Text-Flash (n * 100 ms) FUDARM: .BYTE 1 ; Scharf-Zeit für Frq+/- mit <<*>> Mode Peilen (* 100 ms) ; Erste Betätigung setzt auf 5 = 500ms Fenster für zweite SOUPNT: .BYTE 2 ; Pointer auf Soundstring LSB,MSB; Fertig bei MSB = 0 UBWARN: .BYTE 2 ; Batteriewarnungsschwelle V/mV E,h FRQ512: .BYTE 1 ; Vorige Frequenz-Nr für Mode 5, Rückkehr von Freq-Nr 3 ; ++ Analog-Werte UBATT: .BYTE 3 ; Batterie-Spannung in V/mV Z,E,h UMESSA: .BYTE 1 ; Messspannung für akustisches S-Meter UMESSP: .BYTE 4 ; Spitzenwertspeicher Umess, Ältester Wert in *+3 UMESS: .BYTE 8 ; Messspannung Bargraph 8 Stellen ;++ Display-Ansteuerung LCDDAT: .BYTE 16 ; Data to be displayed in LCD ; ++ Kommunikation mit Int.-Handler SWIFLG: .BYTE 1 ; Switch Flags, Bit 0=Up, 1=Down, 2=Up+Pressed, ; 3=Down+Pressed, 4=Drehdrücker Puls ; 5=Schnell-Taster Kurz, 6=Schnell-Taster Lang TICK: .BYTE 1 ; 100 ms Timing Flag TACK: .BYTE 1 ; 1 s Timing Flag ALATIM: .BYTE 1 ; EOT Alarm Flag, 1 = Alarm auslösen BATTIM: .BYTE 1 ; Batterie-Prüf-Zeit-Timer, 1 = prüfen, 0 = fertig FRQTIM: .BYTE 1 ; Frequenzwechselzeit Mode 6 ; ++ Interrupt-Handler DEBP1: .BYTE 1 ; Debounce Counter Drehgeber DEBDD: .BYTE 1 ; Debounce Drücker Drehgeber DEBST: .BYTE 1 ; Debounce Schnell-Taster TIK3U1: .BYTE 1 ; Zaehlt alle 320 us bis 3 (1 msec) TIK3U2: .BYTE 1 ; Zaehlt alle 320 us bis 25 (8 msec) TIK8M: .BYTE 1 ; Zaehlt jede 8 msec bis 5 TIK20M: .BYTE 1 ; Zaehlt jede 20 msec bis 50 (1 sec) TIK100: .BYTE 1 ; Zaehlt jede 20msec bis 5 (100 ms) TIK1S: .BYTE 1 ; Zaehlt jede 1 s bis 60 (1 min) ; ; ********************** ; **** Macro Definitionen ****************************************** ; ********************** ; ; ++++ Store to SRAM Location @0 Immediate Value @1 ; USES R21 ! C0 resp. C1 are registers with Value 0 resp. 1 .MACRO STSI .IF @1==0 sts @0,C0 .ENDIF .IF @1==1 sts @0,C1 .ENDIF .IF @1>1 ldi R21,@1 sts @0,R21 .ENDIF .ENDMACRO ; ; ++++ Show Text String @0 .MACRO SHOW ldi ZL,low(2*@0) ; Ausgabe-Kommand-String ldi ZH,high(2*@0) rcall LCDSTR ; .. ausführen .ENDMACRO ; ; ++++ Flash Text String @0 for @1*100ms .MACRO FLASH ldi ZL,low(2*@0) ; Ausgabe-Kommand-String ldi ZH,high(2*@0) rcall LCDSTR ; .. ausführen ldi ZL,@1 ; Flash Timer aufsetzen sts FLATIM,ZL ; .ENDMACRO ; ; ++++ Started Sound-String @0 .MACRO SOUND ldi ZL,low(2*@0) ; Sound-String sts SOUPNT,ZL ldi ZH,high(2*@0) sts SOUPNT+1,ZH .ENDMACRO ; ; ++++ Increment 2 Digit BCD within Boundaries .MACRO I2BCD push R16 push XL push XH ldi XL,@0 ; Pointer auf BCD-String clr XH rcall BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 ldi XL,@1 ; Lower Limit ldi XH,@2 ; Upper Limit rcall INCLIM ; Increment R16 within limits in XH,XL ldi XL,@0 ; Pointer auf BCD-String clr XH rcall B2BCD ; Wandelt Bin in R16 in 2B BCD @ X, X+1 pop XH pop XL pop R16 .ENDMACRO ; ; ++++ Decrement 2 Digit BCD within Boundaries .MACRO D2BCD push R16 push XL push XH ldi XL,@0 ; Pointer auf BCD-String clr XH rcall BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 ldi XL,@1 ; Lower Limit ldi XH,@2 ; Upper Limit rcall DECLIM ; Decrement R16 within limits in XH,XL ldi XL,@0 ; Pointer auf BCD-String clr XH rcall B2BCD ; Wandelt Bin in R16 in 2B BCD @ X, X+1 pop XH pop XL pop R16 .ENDMACRO ; ; ******************** ; **** Code starts here ******************************************** ; ******************** .CSEG .ORG 0 ; ; ++++ Interrupt Vectors RJMP START ; 0 Reset RJMP START ; 1 Ext Int 0 RJMP START ; 2 Ext Int 1 RJMP START ; 3 Timer Compare 2 RJMP START ; 4 Timer Overflow 2 RJMP START ; 5 Input Capture 1 RJMP START ; 6 Timer Compare 1A RJMP START ; 7 Timer Compare 1B RJMP START ; 8 Timer Overflow 1 RJMP TIMINT ; 9 Timer Overflow 0 RJMP START ; $A SPI RJMP START ; $B USART Receive Complete RJMP START ; $C USART Data Reg. Empty RJMP START ; $D USART Transmit Complete RJMP START ; $E A/D-Converter RJMP START ; $F EEPROM RJMP START ;$10 Analog Comparator RJMP START ;$11 2-wire I/F RJMP START ;$12 SPM complete ; ; ; ; ***************************** ; **** Main Programm starts here ************************************* ; ***************************** ; ; ++++ Initialize Stackpointer to end of internal RAM START: ldi R16,LOW(RAMEND) out SPL,R16 ldi R16,HIGH(RAMEND) out SPH,R16 ; ; ++++ Initialize Constant Registers ; clr C0 ; Constant 0 clr C1 ; Constant 1 inc C1 ; ; ++++ Initialize RAM area ; clr XH ldi XL,LOW(RAMBEG) clr R16 STA01: st X+,R16 cpi XL,LOW(RAMEND+1) brne STA01 cpi XH,HIGH(RAMEND+1) brne STA01 ; ; ++++ Initialize Port B Bit 0 as Input P1 with Pull-Up ; 1 as Sound Output (=OC1A) ; 2 as Sound Degate Output ; 3..5 used by ISP ; 3 also Uregel Output (OC2) ; 4 also Input Drücker with Pull-Up ldi R16,$0E out DDRB,R16 ldi R16,$11 out PORTB,R16 ; ; ++++ Initialize Port C Bit 0 as Vorstufe Ein/Aus Output ; 1,2 as Analog In Ub,Umess ; 3 as Input P0 with Pull-Up ; 4 as I2C SCL Line, Output, OC, Hi ; 5 as I2C SDA Line, BiDi, OC, Hi ldi R16,$01 out DDRC,R16 ldi R16,$08 out PORTC,R16 ; ; ++++ Initialize Port D Bit 0..5 as Output for Display ; Bit 6,7 as Input with Pull-Up for Mode-Schalter ldi R16,$3F out DDRD,R16 ldi R16,$C0 out PORTD,R16 ; ; ++++ Initialize A/D-Converter LDI R16,$01 ; Select Analog Input 1 OUT ADMUX,R16 LDI R16,$86 ; Enable ADC, Clock Divider 64 = 78 kHz OUT ADCSR,R16 ; = 180 usec Conversion Time ; ; ++++ Intialize Timer/Ctr 0 as 320 usec Timing Interrupt (5Mhz/64/25) ldi R16,$03 ; Set Clock Divider to 64 out TCCR0,R16 ldi R16,-25 ; Set Counter to Start-Value out TCNT0,R16 ldi R16,$01 out TIMSK,R16 ; Enable Counter 0 Overflow Interrupt ; ldi R25,50 ; Wait a little rcall DELXMS ; ; ++++ Intialize Timer/Counter 1 as Variable Osc. for Acoustic S-Meter ; -- CTC-Mode on OC1A Pin, f is 5,0 MHz /2 /OCR1AH_L ldi R16,$00 ; $00 = Sound Off, $40 = On out TCCR1A,R16 ldi R16,$09 out TCCR1B,R16 ldi R16,$0A ; Komparator fuer Counter Reset & Output Toggle out OCR1AH,R16 ldi R16,0 ; $0A00 = 1 kHz Startwert out OCR1AL,R16 ; ; ++++ Intialize Timer/Counter 2 as fast PWM (19 kHz) for Uabschw ldi R16,$69 ; Clock Divider 1, fast PWM, OC2 active out TCCR2,R16 ; ; ++++ Get Steuer-Parameter from EEPROM ; Wenn EEPROM altes Format: umformatieren ; Wenn EEPROM ungültig: initialisieren rcall GETEEP ; Parameter aus EEPROM holen ; lds R16,EEPBEG ; Hat EEPROM veraltetes Format? (< Lvl. 3.8) cpi R16,$A8 brne STA02 rcall EEPMIG ; .. EEPROM umorganisieren auf aktuelles Format ; STA02: lds R16,EEPCLR ; Hat EEPROM jetzt gültigen Inhalt? cpi R16,$A9 breq STA021 ; .. sonst Parameter initialisieren rcall EEPNEW ; STA021: lds R16,LOCKED ; LOCKED darf nur $81 oder $20 sein cpi R16,$81 ; (steht nach Software Upgrade evtl auf anderem Wert) breq STA03 stsi LOCKED,$20 ; ; ++++ Initialize some Variables STA03: stsi STOPWR,1 ; Stopuhr läuft nach Power-On an stsi FRQCHG,1 ; Laden der PLL anfordern stsi ABSBIN,2 ; Abschwächer auf 10 dB stsi AUTOON,' ' ; Abschwächer-Automatik Ein stsi AAWAIT,5 ; Abschwächermechanismus verzögert einschalten stsi FRQTIM,1 ; Bei Mode NFREQ=6 richtige Frequenz laden stsi BATTIM,100 ; Erste Batteriespannungsprüfung nach 10s stsi FRQ512,1 ; Vorige Frequenz-Nr für 12<>3, Rückkehr 3 -> 1 ; sbic PINB,4 ; Wenn Drücker gedrückt rjmp STA031 ; stsi MODE,$20 ; .. dann Abgleichmode ; STA031: rcall GETFRQ ; Aktuelle Frequenz laden rcall CONVF ; Frequenz Dezimal ausrechnen rcall CONVPF ; Leistung Dezimal ausrechnen rcall CONVBW ; Batterie-Warnung Dezimal ausrechnen ; ; ++++ Start Interrupt Handler rcall CLRTIM ; Fuchstimer auf Startwert sei ; Global Interrupt enable ; ; ++++ Initialize LCD and show Start Text rcall INILCD flash STRPO,10 ldi R25,100 ; Wait 100 ms rcall DELXMS stsi SWIFLG,0 ; Clear any Drehgeber Flags sound SOUPO ; rjmp MAIN6 ; Start Main Loop with A/D of UBat ; ; ************* ; **** Main Loop *************************************************** ; ************* ; MAIN: ; ++++ Mode Updaten MAIN2: lds R16,MODE ; Mode holen mov R17,R16 ; Alten Mode retten ; sbis PIND,6 ; Wenn Schalter nicht auf Menü (FRQ) rjmp M21 sbis PINC,4 ; .. und RX Power Off ldi R16,0 ; .... dann Mode 0 sbic PINC,4 ; .. und RX Power On ldi R16,3 ; .... dann Mode 3 ; cpi R16,3 ; Wenn Mode = 3 brne M29 cpi R17,3 ; .. und bisheriger Mode <>3 breq M29 stsi FRQTIM,1 ; .... Flag FRQTIM für Mode 1x2<>3 setzen rjmp M29 ; M21: sbic PIND,6 ; Wenn Schalter auf Menü (FRQ) rjmp M29 mov R18,R16 andi R18,$FC ; und Mode < 4 brne M29 cpi R16,2 ; aber nicht 2 breq M29 ldi R16,7 ; .. dann Mode = 7 flash STRMEN,30 ; Start Menu Message ; M29: sts MODE,R16 ; Mode speichern ; ; ++++ Je nach Mode: Drehdrücker + Taster handeln MAIN3: lds R16,MODE ; Mode holen cli lds R17,SWIFLG ; Switch Flags holen clr R18 ; .. und löschen sts SWIFLG,R18 sei cpi R16,3 ; Wenn Mode <> 3 (Peilen) breq MAIN31 tst R17 ; .. und wenn irgendein Flag gesetzt breq MAIN31 clr R18 ; .... dann laufende Flashes abbrechen sts FLATIM,R18 ; ; ++++ Abschwächertaster behandeln ; MAIN31: sbrs R17,6 ; Taster Lang drücken rjmp M300 sbis PINB,4 ; .. und Drehdrücker nicht gedrückt rjmp M3X2 lds R18,LOCKED ; .. und nicht gelockt sbrc R18,0 rjmp M3X19 ; lds R18,AUTOON ; Abschwächer-Automatik toggeln ldi R19,$0A ; .. ' ' <> '*' eor R18,R19 sts AUTOON,R18 cpi R18,' ' ; Passenden Quittungston + Text erzeugen breq M3X1 sound SOUAA0 flash STRAA0,10 rjmp M309 M3X1: sound SOUAA1 flash STRAA1,10 M3X19: rjmp M309 ; M3X2: lds R18,LOCKED ; Abschwächertaster lang drücken und Drehdrücker ldi R19,$20 ; .. dann locked toggeln cpi R18,$20 brne M3X21 ldi R19,$81 M3X21: sts LOCKED,R19 ; .. und speichern sound SOUOK cpi R19,$81 ; Wenn locked brne M3X22 stsi ACSMON,0 ; .. ACSM ausschalten stsi AUTOON,$20 ; .. und Abschwächerautomatik Ein M3X22: stsi DEBDD,60 ; Drücker-Puls unterdrücken rjmp M309 ; M300: sbrs R17,5 ; Kurz drücken rjmp M309 lds R16,ABSBIN ; = Abschwächer öffnen cpi R16,9 ; Wenn > 40 dB brcs M301 stsi ABSBIN,8 ; .. dann auf 40 dB rjmp M302 M301: cpi R16,3 ; Wenn > 10dB brcs M3011 stsi ABSBIN,2 ; .. dann auf 10 dB rjmp M302 M3011: stsi ABSBIN,0 ; Wenn <= 10dB dann auf 0 dB ; M302: lds R18,PFOXBN ; Wenn allerdings PFOX <= 7 (3 mW) cpi R18,7 brcc M303 stsi ABSBIN,0 ; .. dann Abschwächer immer gleich auf 0dB M303: push R17 rcall CONVAB ; .. neuen Abschwächerwert einstellen pop R17 M309: andi R17,$9F ; Flag Bits 5, 6 löschen ; ; Bei Mode 0 (RX Off) sonst nix tun, nur Flags löschen ; lds R16,MODE cpi R16,3 ; Bei Mode 3 brne M30 rcall UDABS ; Abschwächer ändern, ACSM an/aus, Kanal rjmp M399 ; fertig ; M30: cpi R16,2 ; Bei Mode 2 brne M31 rcall UDFRQ ; Frequenz ändern rjmp M399 ; fertig ; M31: mov R18,R16 ; Bei Mode > = 4 andi R18,$FC brne M330 rjmp M399 M330: lds R19,LOCKED ; .. wenn nicht gelocked sbrc R19,0 rjmp M399 ; M331: sbrc R17,0 ; Wenn Up Flag inc R16 ; .. Mode erhöhen sbrc R17,1 ; Wenn Down Flag dec R16 ; .. Mode verringern cpi R16,8 ; Mode Range auf 4..7, $10..$16 ,$20..$28 brne M332 ; beschränken ldi R16,4 M332: cpi R16,3 brne M333 ldi R16,7 M333: cpi R16,$17 brne M334 ldi R16,$10 M334: cpi R16,$0F brne M335 ldi R16,$16 M335: cpi R16,$29 brne M336 ldi R16,$20 M336: cpi R16,$1F brne M337 ldi R16,$28 M337: sts MODE,R16 ; Mode speichern ; M34: cpi R16,4 ; Wenn Mode = 4 brne M35 sbrs R17,4 ; .. und Drückerpuls rjmp M35 lds R18,STOPWR ; .. und Stopuhr steht tst R18 brne M342 rcall CLRSTW ; .... dann Stopuhr löschen und starten rjmp M35 M342: clr R18 ; sts STOPWR,R18 ; .... sonst Stopuhr anhalten rjmp M399 ; M35: cpi R16,5 ; Wenn Mode = 5 brne M36 rcall UDCTMR ; .. dann Timer löschen/ändern rjmp M399 ; M36: cpi R16,6 ; Wenn Mode = 6 (Einstellungen?) brne M37 sbrs R17,4 ; .. und Drehdrücker Click rjmp M37 ldi R16,$10 ; .. dann neuer Mode 10 (PFuchs) sts MODE,R16 rjmp M399 ; M37: cpi R16,7 ; Wenn Mode = 7 (Frequ. ändern?) brne M310 sbrs R17,4 ; .. und Drehdrücker Click rjmp M310 ldi R16,$02 ; .. dann neuer Mode 2 (Vary Frq.) sts MODE,R16 rjmp M399 ; M310: cpi R16,$10 ; Wenn Mode = 10 brne M311 rcall UDPF ; .. dann Leistung Fuchs verändern rjmp M399 ; M311: cpi R16,$11 ; Wenn Mode = 11 brne M312 rcall UDNF ; .. dann N Füchse verändern rjmp M399 ; M312: cpi R16,$12 ; Wenn Mode = 12 brne M313 rcall UDTFS ; .. dann T Fuchs Sekunden verändern rjmp M399 ; M313: cpi R16,$13 ; Wenn Mode = 13 brne M314 rcall UDTFMS ; .. dann T Fuchs ms verändern rjmp M399 ; M314: cpi R16,$14 ; Wenn Mode = 14 brne M315 rcall UDNFRQ ; .. dann Zahl Frequenzen verändern rjmp M399 ; M315: cpi R16,$15 ; Wenn Mode = 15 brne M316 rcall UDTA ; .. dann EOT Alarmzeit verändern rjmp M399 ; M316: cpi R16,$16 ; Wenn Mode = 16 brne M320 rcall UDACSM ; .. ACSM Schwelle verändern rjmp M399 ; M320: cpi R16,$20 ; Wenn Mode = 20 brne M321 rcall UDSPRA ; .. Batterie-Warnungs-Pegel einstellen rjmp M399 ; M321: cpi R16,$21 ; Wenn Mode = 21 brne M322 sbrs R17,4 ; .. und Drehdrücker Click rjmp M322 rcall EEPNEW ; .... dann EEPROM initialisieren rcall SAVCAL ; flash STRSAV,10 ; .... Message anzeigen sound SOUOK ; .... und Quittungston rjmp M399 ; M322: cpi R16,$22 ; Wenn Mode = 22 brne M323 rcall CALUB ; .. dann U Bat kalibrieren rjmp M399 ; M323: cpi R16,$23 ; Wenn Mode = 23 brne M324 rcall CALFFI ; .. dann Frequenz kalibrieren rjmp M399 ; M324: cpi R16,$24 ; Wenn Mode = 24 brne M325 sbrc R17,4 ; .. und Drehdrücker Click rcall CALABS ; .. dann Frequenz/Abschwächer eichen rjmp M399 ; M325: cpi R16,$25 ; Wenn Mode = 25 brne M326 sbrs R17,4 ; .. und Drehdrücker Click rjmp M326 ; .. dann Bereich ..146/..148 toggeln lds R18,FBER68 com R18 andi R18,1 sts FBER68,R18 rjmp M399 ; M326: cpi R16,$26 ; Wenn Mode = 26 brne M327 rcall UDUBW ; .. Batterie-Warnungs-Pegel einstellen rjmp M399 ; M327: cpi R16,$27 ; Wenn Mode = 27 brne M328 rcall UDDCF ; .. Entfernungskorrektur einstellen rjmp M399 ; M328: cpi R16,$28 ; Wenn Mode = 28 brne M399 sbrs R17,4 ; .. und Drehdrücker Click rjmp M399 rcall SAVCAL ; .... Abgleich-Parameter in EEPROM retten flash STRSAV,10 ; .... Anzeige Save to EEPROM sound SOUOK ; .... und Quittungston rjmp M399 ; ; M399: ; rcall ADUM ; Messspannung A/D-Wandeln und behandeln ; ; ++++ Alles weitere nur alle 100 ms: ++++++++++++++ MAIN5: lds R16,TICK ; 100 ms Flag testen tst R16 brne MAIN51 rjmp MAIN MAIN51: stsi TICK,0 ; ; ++++ Wenn Empfänger übersteuert und Automatik Ein: ; Abschwächer 5 dB höher und Tatü (je 100 ms 500 Hz und 1 kHz) MAINA: lds R16,AUTOON ; Automatik eingeschaltet? cpi R16,' ' brne MAINB ; .. sonst nix tun ; lds R16,AAWAIT ; Wartezeit, weil gerade erst abgeschwächt? tst R16 breq MAINA1 dec R16 sts AAWAIT,R16 ; .. dann nur Wartezähler dekrementieren rjmp MAINB ; MAINA1: lds R17,UMESSP ; Messpannung > Schwelle? cpi R17,128 ; 128 ist S-Meter Vollausschlag brcc MAINA2 rjmp MAINB ; MAINA2: lds R16,ABSBIN ; .. ja: Abschwächer hochschalten cpi R16,24 ; .. ausser wenn schon am Anschlag breq MAINB inc R16 sts ABSBIN,R16 cpi R17,210 ; .. falls Messpannung > 2 * Schwelle (Anschlag) brcs MAINA4 cpi R16,24 breq MAINA4 inc R16 ; .... um insgesmt 2 Stufen hochschalten sts ABSBIN,R16 MAINA4: rcall CONVAB ; .. neuen Abschwächerwert einstellen stsi AAWAIT,1 ; .. Wartezeit vor nächster Abschwächung lds R16,FLATIM ; .. Wenn Textanzeige nicht aktive tst R16 brne MAINB lds R16,SOUPNT+1 ; .... dann wenn Soundgenerator nicht busy tst R16 brne MAINA3 sound SOUABS ; ...... Zweiton erzeugen rjmp MAINB MAINA3: sound SOUAB2 ; ...... Sonst Folge-Zweiton erzeugen ; ; ++++ Alarm-Tonfolge erzeugen, wenn Flag gesetzt und Mode = 3 ; und mehr als 1 Fuchs MAINB: lds R17,ALATIM ; Flag holen clr R18 sts ALATIM,R18 ; und löschen tst R17 ; Flag > 0? breq MAINB0 lds R17,MODE ; und Mode = 3 cpi R17,3 brne MAINB0 lds R18,NFOX+1 ; und > 1 Fuchs.. cpi R18,1 breq MAINB0 sound SOUALA ; .. dann Tonsignal flash STRALA,8 ; .. und Meldung zeigen ; ; ++++ ACSM > Schwelle Nachlaufzeit dekrementieren (falls > 0) MAINB0: lds R17,ACSTIM ; ACSM-Timer > 0 tst R17 breq MAINB1 dec R17 ; .. dann dekrementieren sts ACSTIM,R17 ; ; ++++ Batterie checken ; Interrupthandler setzt Timer BATTIM bei Sendestart F1 auf 100 ; Timer wird hier alle 100 ms dekrementiert ; Bei erreichen von 0 (nach 10 s) wird Batteriespannung gepruft MAINB1: lds R17,BATTIM ; Timer BATTIM holen cpi R17,0 ; Wenn = 0 breq MAINB6 ; ..nix tun dec R17 ; Wenn > 0: dekrementieren sts BATTIM,R17 ; ..und ablegen brne MAINB6 ; Wenn jetzt = 0: Batterie prüfen ; lds R16,UBATT ; Batteriespannung 10V-Stelle holen tst R16 ; Wenn > 0: Bat ok brne MAINB6 ; lds R16,UBATT+1 ; Sonst 1V-Stelle holen lds R17,UBWARN cp R16,R17 breq MAINB3 ; Wenn = Alarmschwelle: nächste Stelle brcs MAINB5 ; Wenn < Alarmschwelle: Alarm rjmp MAINB6 ; Wenn > Alarmschwelle: Bat ok ; MAINB3: lds R16,UBATT+2 ; Wenn 1V-Stelle gleich lds R17,UBWARN+1 ; .. 100mV-Stelle holen cp R16,R17 ; Wenn > Alarmschwelle: Bat ok brcc MAINB6 ; MAINB5: flash STRBAT,60 ; Sonst Alarm-Text und -Sound sound SOUBAT ; MAINB6: lds R16,FUDARM ; Wenn FUDARM Flag > 0 dec R16 ; .. jede 100 ms runterzählen brmi MAINB7 sts FUDARM,R16 MAINB7: ; ; ++++ Im Mode 6 Frequenz prüfen wenn Flag FRQTIM gesetzt MAINC: lds R17,FRQTIM ; Flag holen clr R18 sts FRQTIM,R18 ; und löschen tst R17 ; Wenn Flag FRQTIM gesetzt breq MAINC9 lds R17,NFREQ ; .. und NFREQ = 6 (Mode 1x2<>3) cpi R17,6 brne MAINC9 lds R17,FRQX ; .. und aktuelle Frequenz = 1,2 cpi R17,3 brcc MAINC9 clr ZH ; .... dann Pointer auf FRQ1X2-Entry bauen lds ZL,FOX+1 ldi R16,FRQ1X2 add ZL,R16 ld R16,Z ; .... und Entry lesen cp R16,R17 ; .... Wenn aktuelle Frequenz ungleich Soll breq MAINC9 rcall THISF ; ...... Soll-Frequenz laden MAINC9: ; ++++ Batteriespannung A/D-konvertieren und skalieren MAIN6: ldi R16,1 ; Analog-Channel 1 = UBATT lds R19,UBFINE ; Scaling Factor, ist $2xxd swap R19 ; mit xx = UBFINE und d = dont care andi R19,$0F ori R19,$20 lds R18,UBFINE ; Scaling Factor, Low swap R18 rcall ANACON ldi XH,0 ; Pointer auf Anzeige-Fenster ldi XL,UBATT rcall B3BCD ; Ergebnis in BCD wandeln und ablegen ; rcall CONVAB ; Abschwächer-Einstellung in Entfernung umrechnen ; rcall CONVUM ; Messspannung in Bargraph-Anzeige wandeln ; ; ++++ Je nach Mode Display laden lds R17,FLATIM ; Flash-Timer > 0 tst R17 breq MAIN7 dec R17 ; .. dann dekrementieren sts FLATIM,R17 rjmp MAIN8 ; .. und Display nicht ändern ; MAIN7: lds R16,MODE cpi R16,0 brne M72 lds R18,NFOX+1 ; Mode RX Aus: Wenn nur 1 Fuchs.. cpi R18,1 breq M701 show STR000 rjmp M72 M701: show STR001 ; .. Stopuhr statt Timer zeigen M72: cpi R16,2 brne M73 show STR02 M73: cpi R16,3 brne M74 lds R18,NFOX+1 ; Mode Peilen: Wenn nur 1 Fuchs.. cpi R18,1 breq M731 show STR030 rjmp M74 M731: show STR031 ; .. Stopuhr statt Timer zeigen M74: cpi R16,4 brne M75 lds R18,STOPWR tst R18 breq M741 show STR040 rjmp M75 M741: show STR041 M75: cpi R16,5 brne M76 show STR05 M76: cpi R16,6 brne M77 show STR06 M77: cpi R16,7 ; Frequenz ändern anbieten brne M710 lds R18,LOCKED ; .. bei Locked unterdrücken cpi R18,$20 brne M771 show STR07 rjmp M710 M771: show STRMEN M710: cpi R16,$10 brne M711 lds R18,PFOXBN ; Wenn PFOXBN = 16 cpi R18,16 brne M7101 show STR100 ; .. Entfernungsanzeige aus rjmp M711 M7101: show STR10 M711: cpi R16,$11 brne M712 show STR11 M712: cpi R16,$12 brne M713 show STR12 M713: cpi R16,$13 brne M714 show STR13 M714: cpi R16,$14 brne M715 lds R18,NFREQ ; Wenn Sondermodi 5 oder 6 cpi R18,5 brne M7141 show STR145 ; .. Sondertexte zeigen rjmp M715 M7141: cpi R18,6 brne M7142 show STR146 rjmp M715 M7142: show STR14 ; .. sonst Standardtext M715: cpi R16,$15 brne M716 lds R18,TALARM ; Wenn TALARM = 00 tst R18 brne M7151 lds R18,TALARM+1 tst R18 brne M7151 show STR150 ; .. Alarm Aus rjmp M716 M7151: show STR15 M716: cpi R16,$16 brne M720 show STR16 M720: cpi R16,$20 brne M721 show STR20 M721: cpi R16,$21 brne M722 show STR21 M722: cpi R16,$22 brne M723 show STR22 M723: cpi R16,$23 brne M724 show STR23 M724: cpi R16,$24 brne M725 show STR24 M725: cpi R16,$25 brne M726 lds R18,FBER68 ; Gewählten Abstimmbereich zeigen tst R18 brne M7251 show STR250 rjmp M726 M7251: show STR251 M726: cpi R16,$26 brne M727 show STR26 M727: cpi R16,$27 brne M728 show STR27 M728: cpi R16,$28 brne M799 show STR28 M799: ; ++++ Falls RX Power On und Frequenz geändert: Synthesizer laden MAIN8: sbis PINC,4 ; RX Power On Flag rjmp MAIN85 lds R16,FRQCHG ; Change Frequency Flag gesetzt? tst R16 breq MAIN89 rcall SETPLL ; Ja, Frequenz in PLL laden stsi FRQCHG,0 ; .. und Flag löschen rjmp MAIN89 MAIN85: stsi FRQCHG,1 ; RX Off, Change Frq Flag setzen ; MAIN89: rcall SOUGEN ; Soundgenerator ausführen ; ; ++++ Zur vollen Sekunde: geänderte Parameter ins EEPROM MAIN9: lds R16,TACK ; Wenn volle Sekunde cpi R16,0 breq MAIN99 stsi TACK,0 ; .. Flag löschen rcall SAVCHG ; .. und geänderte Parameter retten ; MAIN99: rjmp MAIN ; ; *************** ; **** Subroutines ************************************************* ; *************** ; ; ################################# ; #### Variablen ändern und anzeigen ############################### ; ################################# ; ; **** Stopuhr löschen und starten CLRSTW: sts STOPWR,C0 ; Run-Flag löschen sts STOPW,C0 ; Zeit auf 0 setzen sts STOPW+1,C0 sts STOPW+2,C0 sts STOPW+3,C0 sts STOPW+4,C0 sts STOPWR,C1 ; und Run-Flag setzen ret ; ; **** Timer löschen bei Klick, +/- bei Drück + Dreh UDCTMR: sbrc R17,4 ; Wenn Drückerpuls rcall CLRTIM ; .... dann Timer löschen und starten ; UDCT2: andi R17,$0C ; Switch-Flag Up Oder Down gesetzt? breq UDCT9 ; .. dann derzeitige Fuchs# ändern ; push R16 ldi XL,NFOX ; Pointer auf NFox-BCD-String clr XH rcall BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 mov R18,R16 ldi XL,FOX ; Pointer auf Fox-BCD-String clr XH cli ; Interrupt aus rcall BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 ldi XL,1 ; Lower Limit mov XH,R18 ; Upper Limit sbrs R17,3 ; Up-Flag, dann Fox-Nummer erhoehen rcall INCLIM ; Increment R16 within limits in XH,XL sbrs R17,2 ; Down-Flag rcall DECLIM ; Decrement R16 within limits in XH,XL ldi XL,FOX ; Pointer auf BCD-String clr XH rcall B2BCD ; Wandelt Bin in R16 in 2B BCD @ X, X+1 sei ; Interrupts wieder zulassen pop R16 ; UDCT9: ret ; ; **** Fuchs Timer auf Start-Wert setzen CLRTIM: push R16 cli ; Interrupt unterdrücken lds R16,TFOXS ; Zeit von TFOX nach TIMER kopieren sts TIMER,R16 lds R16,TFOXS+1 sts TIMER+1,R16 lds R16,TFOXS+2 sts TIMER+2,R16 lds R16,TFOXS+3 sts TIMER+3,R16 sei ; Interrupt wieder an stsi FOX,0 ; Fuchszähler auf 1 stsi FOX+1,1 pop R16 ret ; ; **** Zahl der Füchse (1..10) verändern UDNF: sbrs R17,2 ; Up Flag rjmp NF2 i2bcd NFOX,1,10 rjmp NF8 NF2: sbrs R17,3 ; Down Flag rjmp NF9 d2bcd NFOX,1,10 NF8: rcall CLRTIM ; Nach Änderung: Fuchstimer neu starten NF9: ret ; ; **** Zahl der Frequenzen (1..6) verändern UDNFRQ: andi R17,$0C ; Nur wenn Up oder Down gesetzt: breq NFRQ9 lds R16,NFREQ sbrc R17,2 ; Up inc R16 sbrc R17,3 ; Down dec R16 cpi R16,0 ; Limit to 1..6 (Wrap) brne NFRQ2 ldi R16,6 NFRQ2: cpi R16,7 brne NFRQ3 ldi R16,1 NFRQ3: sts NFREQ,R16 stsi FRQX,1 ; Nach Änderung: Frequenz 1 aktivieren stsi FRQ1X2,1 ; Für Modus 6, Fuchs 1-10, Freq 1 stsi FRQ1X2+1,1 stsi FRQ1X2+2,1 stsi FRQ1X2+3,1 stsi FRQ1X2+4,1 stsi FRQ1X2+5,1 stsi FRQ1X2+6,1 stsi FRQ1X2+7,1 stsi FRQ1X2+8,1 stsi FRQ1X2+9,1 rcall GETFRQ ; Neue Frequenz holen rcall CONVF ; .. und in Anzeigewert umrechnen stsi FRQCHG,1 ; Frequency Changed Flag setzen (=PLL laden) NFRQ9: ret ; ; **** Schwelle ACSM (0..3) verändern UDACSM: lds R16,ACSMLV sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 andi R16,$03 ; Limit to 0..3 sts ACSMLV,R16 ret ; ; **** EOT Alarm-Zeit (0..30) verändern UDTA: push R16 ; TA1: sbrs R17,2 ; Up Flag rjmp TA2 i2bcd TALARM,0,30 rjmp TA8 TA2: sbrs R17,3 ; Down Flag rjmp TA8 d2bcd TALARM,0,30 TA8: pop R16 ret ; ; **** Laufzeit Fuchs Sekunden(1..99) verändern UDTFS: sbrs R17,2 ; Up Flag rjmp TFS2 i2bcd TFOXS,1,99 rjmp TFS8 TFS2: sbrs R17,3 ; Down Flag rjmp TFS9 d2bcd TFOXS,1,99 TFS8: rcall CLRTIM ; Nach Änderung: Fuchstimer neu starten TFS9: ret ; ; **** Laufzeit Fuchs ms (0,2..98) verändern UDTFMS: sbrs R17,2 ; Up Flag rjmp TFM2 i2bcd TFOXMS,0,99 i2bcd TFOXMS,0,99 brcs TFM1 rjmp TFM8 TFM1: i2bcd TFOXS,1,99 rjmp TFM8 TFM2: sbrs R17,3 ; Down Flag rjmp TFM9 d2bcd TFOXMS,0,99 brcc TFM3 d2bcd TFOXS,1,99 TFM3: d2bcd TFOXMS,0,99 TFM8: rcall CLRTIM ; Nach Änderung: Fuchstimer neu starten TFM9: ret ; ; **** Leistung der Füchse verändern UDPF: lds R16,PFOXBN sbrs R17,2 ; Up Flag rjmp UDPFA inc R16 rjmp UDPFB UDPFA: sbrs R17,3 ; Down Flag rjmp UDPF9 dec R16 UDPFB: cpi R16,17 ; Limit to 0..16 (nicht wrappen!) brne UDPFC ldi R16,16 UDPFC: cpi R16,-1 brne UDPFD ldi R16,0 UDPFD: sts PFOXBN,R16 rcall CONVPF ; Convert Code to Textform UDPF9: ret ; ; **** Sprache auswählen UDSPRA: lds R16,SPRACH ; Get current language sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 UDSP1: cpi R16,0 ; Limit to 1..3 brne UDSP2 ldi R16,3 UDSP2: cpi R16,4 brne UDSP3 ldi R16,1 UDSP3: sts SPRACH,R16 ; Geänderte Sprache speichern UDSP9: ret ; ; **** Textstring für Fuchsleistung in PFOX stellen CONVPF: push R16 stsi PFOX,0 ; Erst mal alles auf 0 stsi PFOX+1,0 stsi PFOX+2,0 lds R16,PFOXBN ; Binaer Code für Leistung ; stsi PFOX+3,$E4 ; 0..3: 'µ'W cpi R16,4 brcs CPF0 stsi PFOX+3,'m' ; 4..9: 'm'W cpi R16,10 brcs CPF0 stsi PFOX+3,' ' ; 10..16: ' 'W ; CPF0: cpi R16,0 brne CPF1 stsi PFOX+1,1 CPF1: cpi R16,1 brne CPF2 stsi PFOX+1,3 CPF2: cpi R16,2 brne CPF3 stsi PFOX+0,1 CPF3: cpi R16,3 brne CPF4 stsi PFOX+0,3 CPF4: cpi R16,4 brne CPF5 stsi PFOX+2,1 CPF5: cpi R16,5 brne CPF6 stsi PFOX+2,3 CPF6: cpi R16,6 brne CPF7 stsi PFOX+1,1 CPF7: cpi R16,7 brne CPF8 stsi PFOX+1,3 CPF8: cpi R16,8 brne CPF9 stsi PFOX+0,1 CPF9: cpi R16,9 brne CPF10 stsi PFOX+0,3 CPF10: cpi R16,10 brne CPF11 stsi PFOX+2,1 CPF11: cpi R16,11 brne CPF12 stsi PFOX+2,3 CPF12: cpi R16,12 brne CPF13 stsi PFOX+1,1 CPF13: cpi R16,13 brne CPF14 stsi PFOX+1,3 CPF14: cpi R16,14 brne CPF15 stsi PFOX+0,1 CPF15: cpi R16,15 brne CPF99 stsi PFOX+0,3 CPF99: pop R16 ret ; ; **** Enfernungskorrektur (-5..+5) verändern UDDCF: lds R16,DISTCF ; Get current language sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 cpi R16,-6 ; Limit to -5..+5 (nicht wrappen) brne UDDCF2 ldi R16,-5 UDDCF2: cpi R16,6 brne UDDCF3 ldi R16,5 UDDCF3: sts DISTCF,R16 ; Geänderten Faktor speichern ldi R17,'+' ; Für Anzeige: Vorzeichen bestimmen sbrc R16,7 ldi R17,'-' sts DCFVAL,R17 ; .. und ablegen sbrc R16,7 ; Wenn Wert negativ neg R16 ; .. komplementieren sts DCFVAL+1,R16 ; ret ; ; **** Abschwächer-Einstellung, Frequenz-Nr. +/-, ACSM Ein/Aus ; Schalter-Flags in R17 UDABS: lds R16,ABSBIN sbrc R17,0 ; Up Flag inc R16 sbrc R17,1 ; Down Flag dec R16 cpi R16,-1 ; Auf 0..24 begrenzen, nicht wrappen brne UDABS2 ldi R16,0 UDABS2: cpi R16,25 brne UDAB21 ldi R16,24 UDAB21: sts ABSBIN,R16 ; lds R16,SOUPNT+1 ; Frequenzwechsel nur wenn nicht bereits ein tst R16 ; .. F-Wechsel angezeigt wird: brne UDABS4 ; lds R16,FUDARM ; Wenn Arm Flag nicht gesetzt.. tst R16 brne UDABS3 clr R16 ; .. Erste Betätigung handeln sbrc R17,3 ; .. Bei Drücken und Drehen ldi R16,5 ; .... Arm-Flag auf 500 ms setzen sbrc R17,2 ldi R16,5 sts FUDARM,R16 rjmp UDABS4 ; ; Wenn Arm Flag gesetzt (= 2te <*>-Betätigung innert 400 ms) UDABS3: lds R16,NFREQ ; Sonderfall NFREQ = 5 cpi R16,5 brne UDAB31 lds R16,FRQX cpi R16,1 ; .. und Aktuelle Frequenz = 1 brne UDAB30 sbrc R17,3 ; .... Down+Pressed Flag rcall NEXTF ; = Frequenz 2 sbrc R17,2 ; .... Up+Pressed Flag rcall PREVF ; = Frequenz 3 rjmp UDABS4 ; .... fertig für Frequenz = 1 ; UDAB30: cpi R16,3 ; .. und Aktuelle Frequenz = 3 brne UDAB35 lds R16,FRQ512 sbrc R17,3 ; .... Down+Pressed Flag rcall THISF ; = auf vorige Frequenz zurück rjmp UDABS4 ; .... fertig für Frequenz = 3 ; UDAB31: cpi R16,6 ; Sonderfall NFREQ = 6 brne UDAB35 clr ZH ; Pointer auf FRQ1X2-Entry bauen lds ZL,FOX+1 ldi R16,FRQ1X2 add ZL,R16 ld R16,Z ; .. und Entry lesen ; lds R18,FRQX cpi R18,3 ; Wenn derzeitige Frequenz = 3 brne UDAB33 sbrs R17,3 ; .. und Down+Pressed Flag rjmp UDABS4 ; UDAB32: rcall THISF ; .... dann auf FRQ1X2 wechseln rjmp UDABS4 ; UDAB33: sbrs R17,2 ; Fuchs 1x2 und Up+Pressed Flag rjmp UDAB34 ldi R16,3 ; .. dann auf Frequenz 3 wechseln rjmp UDAB32 UDAB34: sbrs R17,3 ; Fuchs 1x2 und Down+Pressed Flag rjmp UDABS4 ldi R18,$03 ; FRQ1x2 toggeln 1<>2 eor R16,R18 st Z,R16 rjmp UDAB32 ; UDAB35: sbrc R17,2 ; .. Up+Pressed Flag Normalfall rcall NEXTF ; = nächste Frequenz sbrc R17,3 ; .. Down+Pressed Flag rcall PREVF ; = vorige Frequenz ; UDABS4: sbrs R17,4 ; Wenn Click Flag gesetzt.. rjmp UDABS9 lds R16,LOCKED ; .. und nicht locked sbrc R16,0 rjmp UDABS9 lds R16,ACSMON ; .. Akustisches S-Meter Ein/Aus toggeln ldi R18,$40 eor R16,R18 sts ACSMON,R16 tst R16 ; Falls neu eingeschaltet .. breq UDABS9 ldi R16,30 ; .. dann Nachlaufzeit auf 3 Sekunden sts ACSTIM,R16 ; UDABS9: ret ; ; **** Frequenz erhöhen/erniedrigen je nach Flags in R17 (=SWIFLG) UDFRQ: sbrs R17,4 ; Bit 4 = Druckpuls gesetzt? rjmp UDFRQ0 rcall NEXTF ; .. dann Frequenz weiterschalten rjmp UDFRQ9 ; .. und fertig UDFRQ0: andi R17,$0F ; Bit 0, 1, 2 or 3 set? brne UDFRQ1 rjmp UDFRQ9 ; UDFRQ1: lds R24,FRQBIN ; Low Byte of Frequency Code lds R25,FRQBIN+1 ; sbrc R17,0 ; +/- 10 kHz adiw R24,8 sbrc R17,1 sbiw R24,8 sbrc R17,2 ; +/- 1,25 kHz adiw R24,1 sbrc R17,3 sbiw R24,1 ; tst R25 ; Wenn Ergebnis negativ brpl UDFRQ2 clr R24 ; .. auf 0 setzen clr R25 ; UDFRQ2: lds R17,FBER68 ; Max.-Frq. 146 oder 148? tst R17 brne UDFRQ4 ; adiw R24,$20 ; Für 146: Wenn Ergebnis > 1760 = 06E0 cpi R25,$07 brcs UDFRQ3 clr R24 ; .. auf 1760 setzen ldi R25,$07 UDFRQ3: sbiw R24,$20 rjmp UDFRQ8 ; UDFRQ4: sbiw R24,$20 ; ; Für 148: Wenn Ergebnis > 3360 = 0D20 brcs UDFRQ5 ; .. Wenn Ergebnis < 20 nix tun cpi R25,$0D brcs UDFRQ5 clr R24 ; .. auf 3360 setzen ldi R25,$0D UDFRQ5: adiw R24,$20 ; UDFRQ8: sts FRQBIN,R24 ; Ergebnis abspeichern als Binärwert sts FRQBIN+1,R25 rcall PUTFRQ ; .. und nach FRQ1..4 kopieren ; rcall CONVF ; Dezimale Frequenzanzeige bereitstellen stsi FRQCHG,1 ; Frequency Changed Flag setzen (=PLL laden) ; UDFRQ9: ret ; ; Switch to next Frequency NEXTF: push R17 rcall PUTFRQ ; Put current frequency FRQBIN -> FRQ1..4 ; lds R16,FRQX ; Derzeitige Frequenz-Nr. lds R17,NFREQ ; und Max. Frequenz-Nr. holen sts FRQ512,R16 ; Für Mode 5 alte Freq.-Nr. merken cpi R17,5 ; Bei NFREQ = 5,6 brcs NEXTF0 ldi R17,3 ; .. auf 3 Frequenzen begrenzen ; NEXTF0: cp R16,R17 ; Frequenz-Nummer weiterschalten brne NEXTF1 ; .. und bei > Maximum nach 1 wrappen ldi R16,1 rjmp NEXTF2 NEXTF1: inc R16 NEXTF2: sts FRQX,R16 ; rcall GETFRQ ; Get new Frequency FRQ 1..4 -> FRQBIN rcall CONVF ; Dezimale Frequenzanzeige bereitstellen stsi FRQCHG,1 ; Frequency Changed Flag setzen (=PLL laden) flash STRFRQ,20 ; Neue Frequenz String flashen ; lds R16,FRQX ; Zu neuem Kanal gehörende Tonfolge ausgeben cpi R16,1 brne NEXTF4 sound SOUF1 ; Neue Frequenz 1 Tonfolge NEXTF4: cpi R16,2 brne NEXTF5 sound SOUF2 ; Neue Frequenz 2 Tonfolge NEXTF5: cpi R16,3 brne NEXTF6 sound SOUF3 ; Neue Frequenz 3 Tonfolge NEXTF6: cpi R16,4 brne NEXTF7 sound SOUF4 ; Neue Frequenz 4 Tonfolge NEXTF7: pop R17 ret ; ; ; Switch to previous Frequency PREVF: push R17 rcall PUTFRQ ; Put current frequency FRQBIN -> FRQ1..4 ; lds R16,FRQX ; Frequenz-Nummer weiterschalten sts FRQ512,R16 ; Für Mode 5 alte Freq.-Nr. merken dec R16 brne PREVF1 lds R16,NFREQ ; .. und bei 1 nach Maximum wrappen cpi R16,5 ; Bei NFREQ = 5,6 brcs PREVF1 ldi R16,3 ; .. auf 3 Frequenzen begrenzen PREVF1: rjmp NEXTF2 ; Weiter wie bei NEXTF ; ; Switch to Frequency # in R16 THISF: push R17 push R16 rcall PUTFRQ ; Put current frequency FRQBIN -> FRQ1..4 pop R16 ; rjmp NEXTF2 ; Put current frequency FRQBIN -> FRQ1..4 PUTFRQ: lds R16,FRQX ; Pointer auf aktive Frequenz bauen dec R16 ldi YL,LOW(FRQ1) clr YH add YL,R16 add YL,R16 ; lds R16,FRQBIN ; Und 2 Byte kopieren st Y+,R16 lds R16,FRQBIN+1 st Y,R16 ; ret ; Get current frequency FRQBIN <- FRQ1..4 GETFRQ: lds R16,FRQX cpi R16,1 ; Frequenzsymbol erzeugen brne GETF2 ldi R17,'.' GETF2: cpi R16,2 brne GETF3 ldi R17,':' GETF3: cpi R16,3 brne GETF4 ldi R17,$86 GETF4: cpi R16,4 brne GETF5 ldi R17,$87 GETF5: sts FRQXSY,R17 ; lds R16,FRQX ; Pointer auf aktive Frequenz bauen dec R16 ldi YL,LOW(FRQ1) clr YH add YL,R16 add YL,R16 ; ld R16,Y+ sts FRQBIN,R16 ; Und 2 Byte kopieren ld R16,Y sts FRQBIN+1,R16 ; ret ; **** Dezimale Frequenzanzeige vorbereiten 2B FRQBIN -> 4B FRQ **** CONVF: lds R24,FRQBIN ; Binäres Frequenzcodewort holen lds R25,FRQBIN+1 ; 3 LSB aus Frequenz separieren für 1 kHz Anzeige clc clr R17 ; Separierte Bits nach R17 ror R25 ror R24 ror R17 ror R25 ror R24 ror R17 ror R25 ror R24 ror R17 clc ; Separierte Bits rechtsbündig machen ror R17 swap R17 sbrc R17,2 ; Wenn Wert >= 4 inc R17 ; 1 dazu wg 1,25 kHz Abstimmschritt sts FRQ+3,R17 ; Unterste Stelle fertig ; Rest ist im Bereich 0..220 ldi R16,3 ; 1MHz Startwert ldi R17,9 ; 100 kHz ldi R18,0 ; 10 kHz ; CONVF4: tst R24 ; Frequenz ist Startwert + Rest * 10 kHz breq CONVF6 CONVF5: dec R24 inc R18 cpi R18,10 brne CONVF4 clr R18 inc R17 cpi R17,10 brne CONVF4 clr R17 inc R16 rjmp CONVF4 ; CONVF6: tst R25 ; Für grosse F ist Übertrag 1 in R25 breq CONVF7 clr R25 ; .. dann nochmal 256 Increments rjmp CONVF5 ; CONVF7: sts FRQ,R16 sts FRQ+1,R17 sts FRQ+2,R18 ; ret ; ; **** PLL-Einstell-Bytes aurechnen und übergeben ****************** SETPLL: push R0 push R16 push R17 push R18 push R24 push R25 ; lds R16,FFINE ; Einstellung für 143,9 MHz, DB0 add R16,R16 ; FFINE * 2 + 1 inc R16 ldi R17,$40 ldi R18,$27 ; .. DB2 lds R24,FRQBIN ; Frequenzcode holen lds R25,FRQBIN+1 clc ; Ein Bit links schieben rol R24 rol R25 add R16,R24 ; und zum Basiswert addieren adc R17,R25 rcall OUTI2C ; Ergebnis an Synthesizer ; pop R25 pop R24 pop R18 pop R17 pop R16 pop R0 ret ; ; **** UB-Anzeige eichen, dazu UBFINE 0.255 einstellen ; CALUB: push R16 push R17 lds R16,UBFINE ; Aktuellen Wert holen andi R17,$0C ; Wenn kein Flag gesetzt breq CALUB3 ; .. Änderungsteil überspringen ; sbrc R17,2 ; Increment? inc R16 sbrc R17,3 ; Decrement? dec R16 ; sts UBFINE,R16 ; Aktuellen Wert speichern ; CALUB3: ldi XL,UBFVAL ; Aktuellen Wert ... clr XH rcall B3BCD ; .. in 3 BCD in ABSVAL wandeln ; pop R17 pop R16 ret ; ; **** Frequenznachstimmung eichen ; CALFFI: push R16 push R17 lds R16,FFINE ; Aktuellen Wert holen andi R17,$0C ; Wenn kein Flag gesetzt breq CALFF3 ; .. Änderungsteil überspringen ; ldi R18,1 sts FRQCHG,R18 ; Change Frq Flag setzen ; sbrc R17,2 ; Increment? inc R16 sbrc R17,3 ; Decrement? dec R16 cpi R16,90 ; Oberes Limit +25 ? brne CALFF1 ldi R16,89 CALFF1: cpi R16,38 ; Unteres Limit -25 ? brne CALFF2 ldi R16,39 ; CALFF2: sts FFINE,R16 ; Aktuellen Wert speichern ; CALFF3: ldi R17,64 ; Anzeigewert ist FFINE - 64 sub R16,R17 ; .. = -25 .. +25 ldi R17,'+' ; Vorzeichen bestimmen sbrc R16,7 ldi R17,'-' sts FFIVAL,R17 ; .. und ablegen sbrc R16,7 ; Wenn Wert negativ neg R16 ; .. komplementieren ldi XL,FFIVAL+1 ; clr XH rcall B2BCD ; .. in 2 BCD in FFIVAL+1,2 wandeln ; CALFF9: pop R17 pop R16 ret ; ; **** Abschwächer eichen ; CALABS: push R16 push R17 ldi YL,low(ABSTAB) ; Tabelle mit Abschwächerwerten ldi YH,high(ABSTAB) ; stsi ABSBIN,0 ; Abschwächer auf 0 dB setzen ; CALAB1: sbic PIND,6 ; Wenn Kippschalter nicht mehr auf Menü (FRQ) rjmp CALAB9 ; .. abbrechen ld R16,Y ; Aktuellen Wert holen lds R17,SWIFLG ; Switch Flags holen clr R18 ; .. und löschen sts SWIFLG,R18 sbrc R17,0 ; Increment? inc R16 sbrc R17,1 ; Decrement? dec R16 st Y,R16 ; Aktuellen Wert speichern ; sbrs R17,4 ; Click? rjmp CALAB2 lds R16,ABSBIN ; Nächste 10 dB-Abschwächereinstellung inc R16 inc R16 cpi R16,26 ; bis maximal 24 breq CALAB9 sts ABSBIN,R16 ld R16,Y+ ; Tabellenpointer inkrementieren rjmp CALAB1 ; CALAB2: rcall CONVAB ; Abschwächer einstellen ld R16,Y ; Aktuellen Analogwert ldi XL,ABSVAL ; clr XH rcall B3BCD ; .. in 3 BCD in ABSVAL wandeln rcall ADUM ; S-Meter-Wert D/A-Wandeln rcall CONVUM ; S-Meter updaten show STRCAL ; Display updaten rjmp CALAB1 ; CALAB9: pop R17 pop R16 ret ; ; ; **** Increment R16 within limits in XL,XH INCLIM: cp R16,XH ; Am oberen limit? breq INCL1 inc R16 ; Nein: inkrementieren clc ; und Carry Flag loeschen rjmp INCL9 INCL1: mov R16,XL ; Ja: auf unteres Limit setzen sec ; Carry Flag setzen INCL9: ret ; ; **** Decrement R16 within limits in XL,XH DECLIM: cp R16,XL ; Am unteren limit? breq DECL1 dec R16 ; Nein: dekrementieren clc ; Und Carry Flag löschen rjmp DECL9 DECL1: mov R16,XH ; Ja: auf oberes Limit setzen sec ; Und Carry Flag setzen DECL9: ret ; ; **** Convert 2B BCD @ X, X+1 nach Bin in R16 BCD2B: push R17 ld R16,X+ ; Get Zehnerstelle lsl R16 ; Multiply by 10 mov R17,R16 lsl R16 lsl R16 add R16,R17 ld R17,X ; Get Einerstelle add R16,R17 ; And add to result dec XL pop R17 ret ; ; **** Convert Bin in R16 to 2B BCD @ X, X+1 B2BCD: push R16 push R17 push R18 in R17,SREG ; Save Statusreg mit Carry Flag push R17 ; clr R17 ; Einerstelle clr R18 ; Zehnerstelle B2B1: tst R16 ; Bis Bin-Wert auf Null ist breq B2B9 dec R16 ; Binwert dekrementieren inc R17 ; und BCD-Wert inkrementieren cpi R17,10 brne B2B1 clr R17 inc R18 rjmp B2B1 B2B9: st X+,R18 ; Ergebnis ablegen st X,R17 dec XL ; pop R17 out SREG,R17 ; Carry-Flag wiederherstellen pop R18 pop R17 pop R16 ret ; ; **** Convert Bin in R16 to 3B BCD @ X, X+1, X+2 B3BCD: push R16 push R17 push R18 push R19 in R17,SREG ; Save Statusreg mit Carry Flag push R17 ; clr R17 ; Einerstelle clr R18 ; Zehnerstelle clr R19 ; Hunderterstelle B3B1: tst R16 ; Bis Bin-Wert auf Null ist breq B3B9 dec R16 ; Binwert dekrementieren inc R17 ; und BCD-Wert inkrementieren cpi R17,10 brne B3B1 clr R17 inc R18 cpi R18,10 brne B3B1 clr R18 inc R19 rjmp B3B1 B3B9: st X+,R19 ; Ergebnis ablegen st X+,R18 st X,R17 subi XL,2 ; pop R17 out SREG,R17 ; Carry-Flag wiederherstellen pop R19 pop R18 pop R17 pop R16 ret ; ; **** Batterie-Warnungs-Level verändern (von 5,8..8,0 V) UDUBW: lds R16,UBWBIN sbrs R17,2 ; Up Flag rjmp UDUBA inc R16 rjmp UDUBB UDUBA: sbrs R17,3 ; Down Flag rjmp UDUB9 dec R16 UDUBB: cpi R16,81 ; Limit to 58..80 brne UDUBC ldi R16,80 UDUBC: cpi R16,57 brne UDUBD ldi R16,58 UDUBD: sts UBWBIN,R16 rcall CONVBW ; Convert Code to Textform UDUB9: ret ; ; **** Batterie-Warnungs-Level Bin nach Dez wandeln CONVBW: lds R16,UBWBIN ; Binärwert holen clr R17 ; Volt-Stelle clr R18 ; Zehntel-Volt-Stelle ; CVBW1: tst R16 ; Loopen bis Binärwert auf 0 gezählt breq CVBW9 dec R16 ; Binärwert dekrementieren inc R18 ; Dezimalwert inkrementieren cpi R18,10 ; Übertrag handeln brne CVBW1 clr R18 inc R17 rjmp CVBW1 ; CVBW9: sts UBWARN,R17 ; Dezimalwert ablegen sts UBWARN+1,R18 ret ; ############################################ ; #### Analog-In, Entfernungs- und Pegelanzeige ######################### ; ############################################ ; ; **** Einen Analogwert Kanal R16 einlesen und in R16 übergeben ; Scaling Factor in R19,R18 ; Benutzt R16 - R22 ANACON: out ADMUX,R16 ; ADMUX einstellen clr R16 ; Wait a little for I/O to settle AC1: dec R16 brne AC1 sbi ADCSR,6 ; Start ADC AC2: sbis ADCSR,4 ; Wait for ADIF rjmp AC2 sbi ADCSR,4 ; Clear ADIF in R16,ADCL ; Get Conversion Results in R17,ADCH rcall MPY16U mov R16,R20 ; 8 bit unsigned result tst R21 ; If Result Overflow.. breq AC3 ldi R16,$FF ; .. Set Result to max AC3: ret ; ;++++ Subroutine for 16x16 Bit Unsigned Multiplication ; ; This subroutine multiplies the two 16-bit register variables ; Mp16uH:mp16uL and mc16uH:mc16uL. ; The result is placed in m16u3:m16u2:m16u1:m16u0. ; ; Number of words :14 + return ; Number of cycles :153 + return ; Low registers used :None ; High registers used :7 R16..R22 ; ;++ Subroutine Register Variables ; .def mc16uL =r16 ;multiplicand low byte .def mc16uH =r17 ;multiplicand high byte .def mp16uL =r18 ;multiplier low byte = result byte 0 (LSB) .def mp16uH =r19 ;multiplier high byte = result byte 1 .def m16u2 =r20 ;result byte 2 .def m16u3 =r21 ;result byte 3 (MSB) .def mcnt16u =r22 ;loop counter ; ;++ Code ; MPY16u: clr m16u3 ;clear 2 highest bytes of result clr m16u2 ldi mcnt16u,16 ;init loop counter lsr mp16uH ror mp16uL ; m16u_1: brcc noad8 ;if bit 0 of multiplier set add m16u2,mc16uL ;add multiplicand Low to byte 2 of res adc m16u3,mc16uH ;add multiplicand high to byte 3 of res noad8: ror m16u3 ;shift right result byte 3 ror m16u2 ;rotate right result byte 2 ror mp16uH ;rotate result byte 1 and multiplier High ror mp16uL ;rotate result byte 0 and multiplier Low dec mcnt16u ;decrement loop counter brne m16u_1 ;if not done, loop more ret ; ; ; **** Messpannung A/D-wandeln und Maximum speichern ; ADUM: ldi R16,2 ; Analog-Channel 2 = UMESS ldi R19,$AB ; Scaling Factor für S-Meter Empfindlichkeit clr R18 ; .. dto., Low Byte rcall ANACON ; A/D-Wandeln, Ergebnis-Bereich 0..255 sts UMESSA,R16 ; Momentanwert speichern für akustische Ausgabe lds R17,UMESSP ; Spitzenwert für Balken-S-Meter bilden cp R16,R17 brcs ADUM8 sts UMESSP,R16 ; ADUM8: lds R17,UMESSP ; Wenn Spitzenwert lds R18,ACSMLV ; .. grösser/gleich ACSM-Schwellwert swap R18 cp R17,R18 brcs ADUM9 ldi R16,30 ; .. dann Nachlaufzeit auf 3 Sekunden sts ACSTIM,R16 ; ADUM9: rcall ACSM ; S-Meter akustisch ausgeben ret ; ; **** Akustisches S-Meter erzeugen ; Eingangswert ist UMESSA 0..255, Bar-S-Meter ab 127 am Anschlag ; Erzeugte Frequenz steigt pro Stufe im Bereich 0..31 um 6/128, ; 32..63 um 4/128, 64..127 um 2/128, 128..255 um 1/128 ; Frequenzen sind: 0 = 100Hz, 32 = 430 Hz, 64 = 1,2 kHz, ; 128 = 3,1 kHz, 150 (Limit) = 3,7 kHz ; ACSM: lds R16,UMESSA ; Messpannung holen cpi R16,150 ; .. und auf 150 begrenzen brcs ACSM0 ldi R16,150 ; ACSM0: ldi R17,$61 ; Untere Eckfrequenz 100 Hz, Hi Byte ldi R18,$A8 ; dto, Lo Byte ; ACSM1: tst R16 ; Wenn Messwert = 0 breq ACSM7 ; .. fertig, ausgeben ; dec R16 ; Sonst Frequenz um 1/128 erhöhen mov R20,R17 ; .. = Teilerfaktor 1/128 verringern mov R21,R18 clr R19 rol R21 ; 1 * links schieben rol R20 ; .. = 7 * rechts rol R19 sub R18,R20 sbc R17,R19 sbrc R16,7 ; Für die unteren 128 Werte rjmp ACSM1 sub R18,R20 ; .. nochmal um 1/128 verringern sbc R17,R19 sbrc R16,6 ; Für die untersten 64 Werte rjmp ACSM1 sub R18,R20 ; .. um nochmal 2/128 verringern sbc R17,R19 sub R18,R20 ; sbc R17,R19 sbrc R16,5 ; Für die alleruntersten 32 Werte rjmp ACSM1 sub R18,R20 ; .. um nochmal 2/128 verringern sbc R17,R19 sub R18,R20 sbc R17,R19 rjmp ACSM1 ; ACSM7: lds R19,SOUPNT+1 ; Ist Sound Pointer <> 0 (Sound aktiv)? tst R19 brne ACSM9 ; .. dann nichts ausgeben ; in R16,TCNT1L ; Wait until Counter High Byte is 0 in R16,TCNT1H ; .. to avoid noise by counter tst R16 ; .. counting to max (< 5ms @ 200 Hz) brne ACSM7 ; out OCR1AH,R17 ; Variablen Oscillator laden out OCR1AL,R18 ; lds R16,ACSMON ; Piepser je nach Flag Ein-/Aus-Schalten lds R17,ACSTIM ; Wenn Nachlaufzeit > 0 .. tst R17 brne ACSM8 clr R16 ; .. dann Piepser auf jeden Fall ausschalten ACSM8: out TCCR1A,R16 sbrc R16,6 ; NF Degate entsprechend schalten sbi DDRB,2 sbrs R16,6 cbi DDRB,2 ; ACSM9: ret ; ;**** Soundgenerator (Alle 100 ms aufrufen) ; Wenn Soundpointer aktiv: Nächstes Element aus Sound-String holen ; und mit Frequenz 10 kHz/Wert piepsen SOUGEN: lds ZL,SOUPNT ; Sound-Pointer holen lds ZH,SOUPNT+1 tst ZH ; Wenn MSB = 0 breq SOUG9 ; .. dann nichts ausgeben ; lpm ; Get one Byte to R0 adiw ZL,1 ; Increment Z out OCR1AH,R0 ; Variablen Oscillator laden clr R18 out OCR1AL,R18 dec R0 ; Sonderfall Wert = 1 breq SOUG1 ; .. Piepser bleibt aus ldi R18,$40 ; .. sonst Piepser aktivieren SOUG1: out TCCR1A,R18 sbi DDRB,2 ; NF Degate aktivieren ; lpm ; Vorschau auf nächstes Byte tst R0 ; Wenn Wert = $0 brne SOUG2 clr ZH ; .. Fertig, SOUPNT MSB auf 0 SOUG2: sts SOUPNT,ZL ; Sound-Pointer retten sts SOUPNT+1,ZH ; SOUG9: ret ; ; **** Messspannung UMESSP in Bargraph UMESS(0..7) wandeln ; Anzeige hat 8*4 = 32 Bars, Angezeigt wird UMESSP/4, also ; nur der Berreich 0..127 (Akustisches S-Meter geht bis 255) CONVUM: lds R17,UMESSP ; Spitzenwert Messspannung in R17 bilden lds R16,UMESSP+1 cp R17,R16 brcc CUM01 mov R17,R16 CUM01: lds R16,UMESSP+2 cp R17,R16 brcc CUM02 mov R17,R16 CUM02: lds R16,UMESSP+3 cp R17,R16 brcc CUM09 mov R17,R16 CUM09: lds R16,UMESSP+2 ; Spitzenwert-Buffer rechts schieben sts UMESSP+3,R16 lds R16,UMESSP+1 sts UMESSP+2,R16 lds R16,UMESSP sts UMESSP+1,R16 stsi UMESSP,0 ; lsr R17 ; 0..127 für Anzeige auf 0..31 skalieren lsr R17 ldi R16,8 ; Stellenzähler ldi XH,0 ; Pointer auf Bargraph ldi XL,UMESS dec R17 ; Um 1 verringern auf -1 .. 30 ; CUM1: ldi R19,$20 ; Blank ist Bargraph-Wert 0 tst R17 ; Wenn Anzeigewert < 0 brmi CUM9 ; .. diese Stelle Blank ; ldi R19,$85 ; Bargraphwert auf 4 voreinstellen cpi R17,$04 ; Wenn Anzeigewert < 4 brcc CUM9 ; mov R19,R17 ; .. Bargraphwert ist 2 LSb von Anzeigewert andi R19,$03 ldi R18,$82 ; .. + $82 add R19,R18 ; CUM9: st X+,R19 ; Bargraphwert speichern ldi R18,4 ; Anzeigewert um 4 verringern sub R17,R18 dec R16 ; Loopcount, 8 Passes brne CUM1 ; lds R16,LOCKED ; Wenn Verriegelt sbrc R16,0 sts UMESS+7,R16 ; .. in Position 7 Schlüssel zeigen ret ; ; **** Abschwächercode in Anzeige Dämpfung/Entfernung umrechnen CONVAB: lds R16,ABSBIN ; Abschwächer Code holen mov R17,R16 ; .. und mit 5 malnehmen lsl R17 lsl R17 add R16,R17 ; ldi XH,0 ; In BCD wandeln für Abschwächeranzeige ldi XL,ABSCHW rcall B3BCD ; ; ++ Entfernungsanzeige lds R16,ABSBIN ; Abschwächer Code holen lds R17,PFOXBN ; Korrekturfaktor Sendeleistung holen sub R16,R17 ldi R17,7 ; Basiskorrekturfaktor, +/-1 verringert/erhöht add R16,R17 ; geschätzte Entfernung um Faktor 1,8 (5 dB) lds R17,DISTCF ; Korrekturfaktor aus Abgleichmenü (-5..+5) addieren add R16,R17 brpl CUR2 ; Wenn Ergebnis negativ ldi R16,0 ; .. auf 0 setzen CUR2: cpi R16,21 ; Wenn Ergebnis > 20 brcs CUR3 ldi R16,20 ; .. auf 20 setzen ; CUR3: lds R17,ABSCHW+1 ; Default: Abschwächer-dB-Wert Anzeigen lds R18,ABSCHW+2 ldi R19,$80 ; dB Symbol ; lds R20,PFOXBN ; Wenn PFOXBN = 16 cpi R20,16 ; .. dann immer dB anzeigen brne CUR44 lds R16,ABSCHW ; .. Wenn >= 100 db tst R16 breq CUR39 lds R17,ABSCHW ; .... 3stellig ohne dB anzeigen lds R18,ABSCHW+1 lds R19,ABSCHW+2 CUR39: clr R16 ; CUR44: cpi R16,4 ; 1,5 km brne CUR45 ldi R17,1 ldi R18,'k' ldi R19,5 CUR45: cpi R16,5 ; 1 km brne CUR46 ldi R17,1 ldi R18,'k' ldi R19,'m' CUR46: cpi R16,6 ; 700 m brne CUR47 ldi R17,7 clr R18 clr R19 CUR47: cpi R16,7 ; 500 m brne CUR48 ldi R17,5 clr R18 clr R19 CUR48: cpi R16,8 ; 300 m brne CUR49 ldi R17,3 clr R18 clr R19 CUR49: cpi R16,9 ; 200 m brne CUR410 ldi R17,2 clr R18 clr R19 CUR410: cpi R16,10 ; 150 m brne CUR411 ldi R17,1 ldi R18,5 clr R19 CUR411: cpi R16,11 ; 100 m brne CUR412 ldi R17,1 clr R18 clr R19 CUR412: cpi R16,12 ; 50 m brne CUR413 ldi R17,5 clr R18 ldi R19,'m' CUR413: cpi R16,13 ; 30 m brne CUR414 ldi R17,3 clr R18 ldi R19,'m' CUR414: cpi R16,14 ; 20 m brne CUR415 ldi R17,2 clr R18 ldi R19,'m' CUR415: cpi R16,15 ; 10 m brne CUR416 ldi R17,1 clr R18 ldi R19,'m' CUR416: cpi R16,16 ; 5 m brne CUR417 clr R17 ldi R18,5 ldi R19,'m' CUR417: cpi R16,17 ; 3 m brne CUR418 clr R17 ldi R18,3 ldi R19,'m' CUR418: cpi R16,18 ; 2 m brne CUR419 clr R17 ldi R18,2 ldi R19,'m' CUR419: cpi R16,19 ; 1 m brne CUR420 clr R17 ldi R18,1 ldi R19,'m' CUR420: cpi R16,20 ; < 1 m brne CUR499 ldi R17,'<' ldi R18,1 ldi R19,'m' ; CUR499: sts DIST+0,R17 ; Entfernungsanzeige speichern sts DIST+1,R18 sts DIST+2,R19 ; ; Abschwächer-Spannung aus Tabelle holen, x5dB-Werte interpolieren ; lds R16,ABSBIN ; Abschwächer-Code mov R17,R16 ; .. brauchen wir noch lsr R16 ; ..geteilt durch 2 ldi XL,low(ABSTAB) ; ist Pointer in Tabelle ldi XH,high(ABSTAB) add XL,R16 ld R18,X+ ; Analogwert holen ; sbrs R17,0 ; Wenn Code ungerade rjmp CUR52 cpi R17,13 ; .. und nicht 65 dB breq CUR51 ld R17,X ; .. nächsten Tabellenwert auch noch holen add R18,R17 ; .. und Mittelwert bilden ror R18 rjmp CUR52 CUR51: lds R18,ABSTAB+2 ; Sonderfall 65dB: Kein gültiger 60dB-Wert lds R17,ABSTAB+3 ; .. stattdessen 30db- und 20 dB-Werte holen sub R17,R18 ; A65 = A70 - (A30-A20)/2 ror R17 lds R18,ABSTAB+7 sub R18,R17 ; CUR52: out OCR2,R18 ; Analogwert an PWM übergeben ; ; Bei Abschwächung ab 65 dB Vorstufe ausschalten, sonst an ; lds R16,ABSBIN ; Abschwächer-Code cpi R16,13 ; >= 65 dB? brcc CUR6 sbi DDRC,0 ; Nein, Vorstufe Ein rjmp CUR9 CUR6: cbi DDRC,0 ; Ja, Vorstufe Aus ; CUR9: ret ; ; ######################### ; #### I2C-Interface Treiber ####################################### ; ######################### ; ; HW-Interface: SDA auf Pin PC5, SCL auf Pin PC4 ; Leitungen werden fuer Low aktiv runtergezogen, fuer High ; freigegeben und gehen ueber externen Pull-Up hoch ; Return-Code fuer alle Ops in R0: 0 = OK, 1 = Missing Ack ; ; ++++ Send Address $C4, Subaddress $00, 3 Databytes in R16, R17, R18 ; and 1 Databyte $00 to I2C (zugeschnitten auf TSA6057) ; OUTI2C: PUSH R16 LDI R16,$C4 ; Chip Address RCALL I2STRT ; Start Sequence RCALL I2SEND ; Send Address LDI R16,$00 ; Byte Subaddress RCALL I2SEND ; Send Subaddress POP R16 ; Get Data Byte 1 PUSH R16 RCALL I2SEND ; Send data Byte 1 MOV R16,R17 RCALL I2SEND ; Send data Byte 2 MOV R16,R18 RCALL I2SEND ; Send data Byte 3 LDI R16,$00 RCALL I2SEND ; Send data Byte 4 = $00 RCALL I2STOP ; Stop Sequence POP R16 RET ; .MACRO SDA_HI CBI DDRC,5 RCALL I2WAIT .ENDMACRO ; .MACRO SDA_LO SBI DDRC,5 RCALL I2WAIT .ENDMACRO ; .MACRO SCL_HI CBI DDRC,4 RCALL I2WAIT .ENDMACRO ; .MACRO SCL_LO SBI DDRC,4 RCALL I2WAIT .ENDMACRO ; ; ---- Wait > 5 usec after any transition - siehe Bus Spec I2WAIT: PUSH R16 LDI R16,7 ; 14 fuer 8 Mhz; 7 fuer 4 MHz Clock I2W1: DEC R16 ; 3 Cycle inner Loop BRNE I2W1 POP R16 RET ; ; ++++ Send Start Sequence on I2C I2STRT: SDA_LO SCL_LO RET ; ; ++++ Send Stop Sequence on I2C I2STOP: SDA_LO SCL_HI SDA_HI RET ; ; ++++ Send Byte in R16 and wait for Ack I2SEND: PUSH R16 PUSH R20 LDI R20,8 ; Loopcounter bis 8 I2SE1: TST R16 ; Get MSb to N-Flag BRPL I2SE2 ; Put MSb on SDA SDA_HI RJMP I2SE3 I2SE2: SDA_LO I2SE3: SCL_HI ; toggle Clock SCL_LO LSL R16 ; Shift next bit to MSb DEC R20 ; Loopcount BRNE I2SE1 ; SDA_HI ; SDA freigeben fuer Ack SCL_HI ; Ack anfordern CLR R0 ; Error Flag loeschen I2SE4: SBIC PINC,5 ; Falls SDA nicht Low .. INC R0 ; .. Error Flag setzen ; SCL_LO ; Ack-Sequenz abschliessen ; POP R20 POP R16 RET ; ; ################### ; #### EEPROM Handling ############################################# ; ################### ; ; ++++ Initialize Steuer-Parameter ; Called if EEPROM is empty or by menu item 'EEPROM Reset' ; EEPNEW: ldi ZL,low(2*INIVAL) ; Pointer auf Ini.-Werte im Flash ldi ZH,high(2*INIVAL) ldi XL,EEPBEG ; Pointer auf EEPROM-Kopie im RAM ldi XH,0 ; EEPN1: lpm ; Copy one Byte from Flash st X+,R0 ; .. to RAM adiw ZL,1 ; Next cpi XL,EEPEND brne EEPN1 ; ret ; ; ++++ Steuer-Parameter von altem Format (<3.7) auf neues umordnen ; EEPMIG: clr XH ; Pointer vorbereiten fürs Verschieben der clr YH ; .. Abgleichdaten um 11 Byte ldi XL,SPRACH-11 ldi YL,SPRACH EEPM1: ld R16,-X ; Verschieben st -Y,R16 ; von SPRACH-1 bis ABSTAB cpi YL,ABSTAB brne EEPM1 ; stsi TBD1,0 ; Initialisiere neue Parameter ldi XL,FRQ1X2 EEPM7: st X+,C1 cpi XL,FRQ1X2+10 brne EEPM7 stsi SPRACH,1 stsi DISTCF,0 stsi EEPCLR,$A9 ; rcall SAVCAL ; Automatisch ins EEPROM retten rcall SAVCHG ret ; ; ++++ Geänderte Parameter von EEPBEG bis EEP2-1 ; ins EEPROM speichern ; SAVCHG: LDS R16,EEPCLR ; Hat EEPROM gültigen Inhalt? CPI R16,$A9 BRNE SAVCH9 ; .. sonst nichts speichern ; LDI YL,LOW(EEPBEG) ; Pointer auf Variablen CLR YH LDI R20,0 ; Bytecounter und EEPROM Low Adresse OUT EEARH,YH ; High Adresse ist 0 SAVCH1: LD R16,Y+ ; 1 Variable holen ; Derzeitigen Wert aus EEPROM holen und vergleichen OUT EEARL,R20 ; EEPROM Entry Adresse laden LDI R17,$01 OUT EECR,R17 ; Set EEPROM Read Cmd SAVCH2: IN R17,EECR ; Wait for EEPROM Read complete ANDI R17,$01 BRNE SAVCH2 IN R17,EEDR ; Daten lesen CP R16,R17 ; .. und vergleichen BREQ SAVCH4 ; Wenn ungleich: ins EEPROM schreiben SAVCH3: IN R17,EECR ; Wait for EEPROM Ready to write ANDI R17,$02 BRNE SAVCH3 OUT EEARL,R20 OUT EEDR,R16 CLI ; Interrupt ausschalten LDI R17,$04 LDI R18,$02 OUT EECR,R17 ; Set EEPROM Master Write Enable OUT EECR,R18 ; Set EEPROM Write SEI ; Interrupt wieder an SAVCH4: INC R20 CPI R20,EEP2-EEPBEG ; Gesamter Bereich geschrieben? BRNE SAVCH1 SAVCH9: RET ; ; ; ++++ Abgleichwerte von EEP2 bis EEPEND-1 ; ins EEPROM speichern ; SAVCAL: LDI YL,LOW(EEP2) ; Pointer auf Variablen CLR YH LDI R20,EEP2-EEPBEG ; Bytecounter und EEPROM Low Adresse OUT EEARH,YH ; High Adresse ist 0 SAVCA1: LD R16,Y+ ; 1 Variable holen SAVCA2: IN R17,EECR ; Wait for EEPROM Ready to write ANDI R17,$02 BRNE SAVCA2 OUT EEARL,R20 OUT EEDR,R16 CLI ; Interrupt ausschalten LDI R17,$04 LDI R18,$02 OUT EECR,R17 ; Set EEPROM Master Write Enable OUT EECR,R18 ; Set EEPROM Write SEI ; Interrupt wieder an INC R20 CPI R20,EEPEND-EEPBEG ; Gesamter Bereich geschrieben? BRNE SAVCA1 RET ; ; ++++ Alle Parameter aus EEPROM holen +++++++++++++++++++++++++++++++ ; GETEEP: LDI YL,low(EEPBEG) ; Pointer auf Variablen CLR YH LDI R20,$00 ; Bytecounter und EPROM Low Adresse OUT EEARH,R20 ; High Adresse ist 0 GET1: OUT EEARL,R20 LDI R17,$01 OUT EECR,R17 ; Set EEPROM Read Cmd GET2: IN R17,EECR ; Wait for EEPROM Read complete ANDI R17,$01 BRNE GET2 IN R16,EEDR ; Daten lesen ST Y+,R16 ; Byte bzw low nibble speichern INC R20 ; Loopcounter CPI R20,EEPEND-EEPBEG ; Alle Bytes gelesen? BRNE GET1 RET ; ; ################### ; #### LCD-Ansteuerung ############################################### ; ################### ; ; **** Subroutine to Copy String to LCD Data Field ******************* ; ; String pointed to by Z ; Variables are inserted according to second 16 Bytes in Data String ; Also handles leading zero suppression ; LCDSTR: PUSH R0 PUSH R16 PUSH R17 PUSH XL PUSH XH PUSH YL PUSH YH ; ;++++ Make Y pointer to LCD Data Field LDI YH,HIGH(LCDDAT) LDI YL,LOW(LCDDAT) ; ;++++ Copy 2 * 8 B Data String LCDST1: LDI R16,2 ; Loopcounter for 2 8B-Strings ; LCDS11: CLR XH ; X is Offset to start of next 8B-String CLR XL ; (used only for multiple language records) LPM ; Get first Byte of line to R0 MOV R17,R0 ; Is it $10 = Multi Language Flag? CPI R17,$10 BRNE LCDS15 ; ADIW ZL,2 ; Read-Pointer skips $1010 LDS R17,SPRACH ; Get selected Language CPI R17,1 ; BRNE LCDS12 LDI XL,16 ; Language 1: Post-Offset 16 LCDS12: CPI R17,2 BRNE LCDS13 ADIW ZL,8 ; Language 2: Pre- and Post-Offset 8 LDI XL,8 LCDS13: CPI R17,3 BRNE LCDS15 ADIW ZL,16 ; Language 3: Pre-Offset 16 ; LCDS15: LDI R17,8 ; Bytecounter 8 to 0 LCDS16: LPM ; Get one Byte to R0 ADIW ZL,1 ; Increment Z ST Y+,R0 ; Store Byte DEC R17 ; Repeat 8 times BRNE LCDS16 ; ADD ZL,XL ; Post-Correct readpointer for multi-language ADC ZH,XH DEC R16 ; Do Two 8-Char Lines BRNE LCDS11 ; LDI YH,HIGH(LCDDAT) LDI YL,LOW(LCDDAT) ; ;++++ Insert Variable String LCDST2: LPM ; Get one Byte to R0 ADIW ZL,1 ; Increment Z MOV R16,R0 ; Use High Register for Immediate OpCodes ; CPI YL,LOW(LCDDAT) ; Wenn erstes Byte BRNE LCDS21 TST R16 ; .. und Inhalt = 0 BRNE LCDS21 RJMP LCDSTA ; dann keine Variablen = Fertig ; LCDS21: CPI R16,0 ; 0 is next Digit BREQ LCDST5 ; LCDST3: MOV R16,R0 ; If not 0: <$10 is NOP ANDI R16,$F0 BREQ LCDST9 ; MOV XL,R0 LDI XH,0 ; LCDST5: LD R16,X+ ; Get Variable CPI R16,10 ; Wenn Im Bereich 0..9 BRCC LCDS51 ; ORI R16,'0' ; Convert 0..9 to ASCII ; LCDS51: CPI R16,'0' ; Handle leading zero BRNE LCDS52 LD R17,Y ; CPI R17,':' BRNE LCDS52 LDI R16,' ' ; Replace leading zero by Space ; LCDS52: CPI R16,$80 ; Codes im Bereich $80-$87 (Sonderzeichen) BRCS LCDST6 CPI R16,$88 BRCC LCDST6 ANDI R16,$07 ; .. nach 0..7 umsetzen ; LCDST6: ST Y,R16 ; Insert character ; LCDST9: INC YL ; Increment Write Pointer CPI YL,LOW(LCDDAT)+16 ; Repeat 16 times BRNE LCDST2 ; LCDSTA: rcall OUTLCD ; Ergebnis anzeigen ; POP YH POP YL POP XH POP XL POP R17 POP R16 POP R0 RET ; ; ; **** LCD-Treiber ********************************************* ; ; Bedient das LCD-Display ueber die standardisierte 4+3-bit Schnittstelle ; ; ++++ Initialize the LCD Display INILCD: push R16 push R25 ; ldi R25,20 ; Wait 20 msec rcall DELXMS ldi R25,$30 ; Initialize LCD rcall LC1CMD ldi R25,5 ; Wait 5 msec rcall DELXMS ldi R25,$30 ; Initialize LCD rcall LC1CMD ldi R25,5 ; Wait 5 msec rcall DELXMS ldi R25,$30 ; Initialize LCD rcall LC1CMD ldi R25,16 ; Wait Another 16 msec rcall DELXMS ldi R25,$20 ; Auf 4 bit Betrieb schalten rcall LC1CMD ldi R25,$28 ; System Set: 2zeilig, 5*7 Matrix,4 bit Betrieb rcall LC2CMD ldi R25,$06 ; Cursor Mode: laeuft nach rechts rcall LC2CMD ldi R25,$0C ; Display on, Cursor Off rcall LC2CMD ldi R25,$80 ; DDRAM-Adress auf 0 rcall LC2CMD ldi R25,$01 ; Clear Display, Cursor Home rcall LC2CMD ldi R25,2 ; Wait 2 msec rcall DELXMS ; ; ++ Load 8 character generator fields from table ; INICG: ldi ZL,low(2*SPECCH) ; Readpointer for CharGen-Table ldi ZH,high(2*SPECCH) ldi R25,$40 ; CGRAM-Adresse auf Anfang rcall LC2CMD clr R16 ; Character-Counter 0 - 63 ; INICG1: lpm ; Get one Byte from Table to R0 mov R25,R0 rcall LC2DAT ; .. and send to LCD adiw ZL,1 ; Increment Z inc R16 ; Increment Bytecounter cpi R16,64 ; If less than 64 brne INICG1 ; .. loop gain ; ; pop R25 pop R16 ret ; ; ++++ Copy 16 Bytes from RAM (LCDDAT) to Display OUTLCD: push R25 ; ldi R25,$80 ;DDRAM-Adress auf 0 rcall LC2CMD ldi YL,LOW(LCDDAT) ;Pointer to Data String clr YH ldi R16,8 ;Loop-Counter, erste Zeile OUTLC1: ld R25,Y+ ;Get one Data Byte rcall LC2DAT ;Write to Display dec R16 ;Decrement Loopcounter brne OUTLC1 ; ldi R25,$A8 ;DDRAM-Adress auf 40 = Anfang 2te Zeile rcall LC2CMD ldi R16,8 ;Loop-Counter, zweite Zeile OUTLC2: ld R25,Y+ ;Get one Data Byte rcall LC2DAT ;Write to Display dec R16 ;Decrement Loopcounter brne OUTLC2 ; pop R25 ret ; ; ++ Write Data in R25 (High Nibble) to LCD ( 1 Data Shot) ; LC1DAT: push R25 ; Entry for Data Mode swap R25 andi R25,$0F ; ori R25,$10 rjmp LC1CM0 ; LC1CMD: push R25 ; Entry for Command Mode swap R25 andi R25,$0F ; LC1CM0: ori R25,$C0 ; Pull-Ups fuer Taster out PORTD,R25 ; Post Data nop nop nop nop nop sbi PORTD,5 ; Toggle Enable Bit nop nop nop nop nop cbi PORTD,5 ; ldi R25,70 ; Wait 40 usec = 200 cycles LC1CM1: dec R25 brne LC1CM1 ; pop R25 ret ; ; ++ Write Data in R25 as Command to LCD (2 Nibble Shots) LC2CMD: push R25 ; rcall LC1CMD ; Send high nibble swap R25 rcall LC1CMD ; and low nibble ; pop R25 ret ; ; ++ Write Data in R25 as Data to LCD (2 Nibble Shots) LC2DAT: push R25 ; rcall LC1DAT ; Send high nibble swap R25 rcall LC1DAT ; and low nibble ; pop R25 ret ; ; ##################### ;##### Delay-Subroutines #################################### ; ##################### ; ; ++++ Delay x ms, x in R25 (x * 5 * 256 * 3 Cycle / 4 MHz) DELXMS: PUSH R16 PUSH R17 PUSH R25 ; DXMS: CLR R16 LDI R17,5 D1MS: INC R16 ; 3 cycle inner loop BRNE D1MS ; " " " " DEC R17 BRNE D1MS DEC R25 BRNE DXMS POP R25 POP R17 POP R16 RET ; ; ************************************ ; ******* 320 usec Timer Interrupt Handler ********************************** ; ************************************ ; ; ++++ Increment Timer @0 up to @1 ; If @1 reached: @0 = 0 else: goto @2 .MACRO INCTIM lds R24,@0 ; Timer holen inc R24 ; und inkrementieren sts @0,R24 cpi R24,@1 ; Wenn Endwert erreicht brne @2 clr R24 ; auf 0 setzen sts @0,R24 .ENDMACRO ; TIMINT: PUSH R16 PUSH R21 PUSH R22 PUSH R23 ; Get some work registers PUSH R24 PUSH XL PUSH XH IN R24,SREG ; Save Statusreg PUSH R24 ; ; ++ 320 us Service ; TIM500: ldi R22,-25 ; Set Counter to Startvalue (Divide by 64*25) out TCNT0,R22 ; inctim TIK3U1,3,TIM501 ; Increment to 1 ms ; sei ; Enable next interrupt rcall DEBNCE ; Debounce Drehgeber ; TIM501: sei inctim TIK3U2,25,TIM599 ; Increment to 8 msec rcall DEBNC2 ; Debounce Taster ; inctim TIK8M,5,TIM502 ; Increment to 40 msec rjmp TIM504 TIM502: cpi R24,2 ; 20 msec-Evemt on 8 msec-Counter = 0 or 2 breq TIM504 TIM599: rjmp TIM99 ; ; ++ 20 ms Service ; TIM504: d2bcd TIMER+2,0,99 ; Decrement Timer ms in R22,SREG ; Save the Carry Flag d2bcd TIMER+2,0,99 sbrs R22,0 ; Skip if Carry set (after first Decrement) rjmp TIM101 TIM10: d2bcd TIMER,0,99 ; Decrement Timer s ; TIM101: lds R24,TIMER+3 ; Wenn Timer 00:00 erreicht hat tst R24 brne TIM102 lds R24,TIMER+2 tst R24 brne TIM102 lds R24,TIMER+1 tst R24 brne TIM103 lds R24,TIMER tst R24 brne TIM103 rjmp TIM104 TIM102: rjmp TIM20 TIM103: rjmp TIM18 ; TIM104: lds R24,TFOXS ; .. Timer auf Startwert setzen sts TIMER,R24 lds R24,TFOXS+1 sts TIMER+1,R24 lds R24,TFOXS+2 sts TIMER+2,R24 lds R24,TFOXS+3 sts TIMER+3,R24 stsi FRQTIM,1 ; lds R24,FOX ; Wenn derzeitiger Fuchs <> Maxwert lds R23,NFOX cp R23,R24 brne TIM11 lds R24,FOX+1 lds R23,NFOX+1 cpi R23,1 ; Wenn Maxwert = 1 brne TIM105 ldi R23,5 ; .. auf 5 setzen = Bat-Alarm nur alle 5 min bei Foxoring TIM105: cp R23,R24 breq TIM12 TIM11: i2bcd FOX,1,16 ; Fuchs hochzaehlen rjmp TIM20 TIM12: stsi FOX,0 ; Sonst Fuchs auf 1 setzen stsi FOX+1,1 stsi BATTIM,100 ; Check Battery Timer auf 10 sec setzen ; TIM18: lds R22,TALARM ; Get Alarm-Time lds R23,TALARM+1 add R22,R23 ; Wenn Zeit = 0 breq TIM20 ; .. nix tun lds R22,TIMER+1 ; Sonst Timer mit Alarm vergleichen cp R22,R23 brne TIM20 lds R23,TALARM lds R22,TIMER cp R22,R23 brne TIM20 stsi ALATIM,1 ; Bei Match: Flag für Main setzen ; TIM20: inctim TIK100,5,TIM21 ; Increment 20 msec Timer up to 5 (100 ms) stsi TICK,1 ; At Time 100 set Timing Flag for Main ; TIM21: inctim TIK20M,50,TIM99 ; Increment 20 msec Timer up to 50 (1 s) stsi TACK,1 ; At Time 1 s set Timing Flag for Main ; ; ++ 1 sec Service ; lds R24,STOPWR ; Falls Stopwatch an tst R24 breq TIM30 i2bcd STOPW+3,0,59 ; Uhr hochzählen Sekunden brcc TIM30 ; i2bcd STOPW+1,0,59 ; Minuten brcc TIM30 lds R24,STOPW ; Stunde inc R24 andi R24,$07 ; Bei 8 h wrappen sts STOPW,R24 ; TIM30: inctim TIK1S,60,TIM99 ; Increment 1 sec Timer ; ; ++ 1 min Service ; Derzeit nichts... ; ; ++ Conclusion of Interrupt Service ; TIM99: CLI ; No interrupts during conclusion POP R24 ; Restore Status Reg OUT SREG,R24 POP XH POP XL POP R24 POP R23 POP R22 POP R21 POP R16 RETI ; Interrupt-Handling beendet ; ; ++++ Debounce Drehgeber und Taster ; ; Result in Flag SWIFLG ; This is a Subroutine called by the interrupt handler once per ms ; SWIFLG ist: Bit 0=Up, 1=Down, 2=Up + Pressed, 3=Down + Pressed, ; 4=Drehdrücker Puls ; 5=Taster Kurz, 6=Taster Lang ; $00 = none ; SWIFLG wird von Main auf none gesetzt. ; ; ++ Debounce Drehgeber Up/Down (alle 1 ms) ; DEBNCE: PUSH R20 ; Used as Temp Register ; LDS R20,DEBP1 ; Debounce-Counter SBIC PINC,3 RJMP DEB1 CPI R20,0 ; An unterem Limit? BREQ DEB3 ; Do nothing DEC R20 ; Counter runterzaehlen STS DEBP1,R20 CPI R20,0 ; Jetzt auf Null? BRNE DEB3 SBIC PINB,0 RJMP DEBINC RJMP DEBDEC ; DEB1: CPI R20,2 ; An oberem Limit (5.5 ms)? BREQ DEB3 INC R20 STS DEBP1,R20 CPI R20,2 ; Jetzt am oberen Limit? BRNE DEB3 SBIC PINB,0 RJMP DEBDEC RJMP DEBINC ; DEBINC: LDI R20,$1 RJMP DEB2 ; DEBDEC: LDI R20,$2 ; DEB2: SBIS PINB,4 ; Wenn Drehgeber gedrückt LSL R20 ; Flags 2 Stellen links schieben SBIS PINB,4 LSL R20 STS SWIFLG,R20 ; Flags speichern LDI R20,60 ; Click-Flag verhindern bei Drück+Dreh STS DEBDD,R20 ; ; ++ Debounce Drehdrücker (alle 1 ms) ; DEB3: LDS R20,DEBDD ; Timer holen SBIS PINB,4 ; Wenn nicht gedrückt RJMP DEB31 CPI R20,50 ; .. und Timer war genau am Limit BRNE DEB30 LDI R20,$10 ; .... dann Drücker-Flag setzen STS SWIFLG,R20 ; ; DEB30: CLR R20 ; Timer auf 0 setzen RJMP DEB39 ; DEB31: CPI R20,50 ; Gedrückt: Counter schon am Limit? BRCC DEB9 ; .. dann nix tun INC R20 ; .. sonst Counter hochzaehlen DEB39: STS DEBDD,R20 ; .. und retten ; DEB9: POP R20 RET ; ; **** Debounce Taster (alle 8 ms) ; DEBNC2: PUSH R20 ; Used as Temp Register ; DEB4: LDS R20,DEBST ; Timer holen SBIC PIND,7 ; Wenn Bit (SU) nicht auf 0 rjmp DEB41 ; .. dann Taster offen ; ; Lang drücken handeln CPI R20,125 ; Counter schon am Limit (1 sec)? BREQ DEB8 ; dann nix tun INC R20 ; Counter hochzaehlen STS DEBST,R20 ; und retten CPI R20,125 ; Jetzt am Limit? BRNE DEB8 LDS R20,SWIFLG ; Dann Flag setzen ORI R20,$40 ; STS SWIFLG,R20 ; rjmp DEB8 ; ; Kurz drücken handeln DEB41: cpi R20,10 ; War Taster 80 - 1000 ms gedrückt? brcs DEB42 cpi R20,125 breq DEB42 LDS R20,SWIFLG ; Dann Flag setzen ORI R20,$20 STS SWIFLG,R20 DEB42: clr R20 sts DEBST,R20 ; DEB8: POP R20 RET ; ; ************************* ; **** Initialisation Tables ********************************************** ; ************************* ; ; ++++ EEPROM Reset/Initial Values ; ; Tbd1, F1 144.525, F2 143.9, F3 146.1, F4 144.1, F1 aktiv INIVAL: .DB 0,$F4,$01,$00,$00,$E0,$06,$A0,$00,1 ; Füchse 05, Sendedauer 60.00s, Leistung 12 (1W), Zahl Freq. 3 ; Alarmzeit -10s, ACSM-Schwelle 0 (keine), Locked .DB 0,5,6,0,0,0,12,3,1,0,0,$20 ; Für Modus 1x2<>3: Fuchs 10,1-9, jeweils Frequenz 1 .DB 1,1,1,1,1,1,1,1,1,1 ; Abschwächertabelle 0..70 dB .DB 53,72,89,104,138,159,166,132 ; dto. 80..120 dB, Freq-Korrektur (+02) .DB 157,164,173,189,229,66 ; Ub-Mess-Korrektur, Freq.Ber. -146, Bat Alarm 7,0V, ; Sprache 1 = Deutsch, Entf.-Korr +/-0, EEPROM valid .DB 117,0,70,1,0,$A9 ; ; ++++ Special Characters 0..7, to be loaded into LCD-Display ; SPECCH: .DB $06,$05,$05,$0E,$15,$15,$0E,$00 ; 0: compressed dB-Symbol .DB $0E,$11,$0E,$04,$04,$07,$06,$07 ; 1: Schlüssel .DB $10,$10,$10,$10,$10,$10,$10,$10 ; 2: | (S-Meter) .DB $18,$18,$18,$18,$18,$18,$18,$18 ; 3: || .DB $18,$1A,$1A,$1A,$1A,$1A,$1A,$18 ; 4: ||| .DB $18,$1B,$1B,$1B,$1B,$1B,$1B,$18 ; 5: |||| .DB $0C,$0C,$00,$0C,$0C,$00,$0C,$0C ; 6: ... (F3-Symbol) .DB $00,$1B,$1B,$00,$1B,$1B,$00,$00 ; 7: :: (F4-Symbol) ; ; ******************* ; **** Display Strings ********************************************* ; ******************* ; ; Die ersten 16 Bytes sind der Festtext-Teil der Anzeige ; ":" in Variablenposition = 0 als Space zeigen (Leading Zero Suppress) ; 0 in Zeichenposition = Komprimiertes dB Zeichen ; 1 " = Schlüssel-Symbol ; 2 " = Block 1 Linie breit (S-Meter) ; 3 " = Block 2 Linien breit ; 4 " = Block 3 Linien breit ; 6 " = 3 Punkte (Frequenz) ; 7 " = 4 Punkte ; $E1 = ä, $EF = ö, $F5 = ü, $E2 = ß, kein Ä, Ö, Ü! ; $7E = ->, $7F = <- ; ; Die zweiten 16 Bytes sind jeweils Pointer auf die Variablen ; 1..8 = Leer ; Variablenname = Variable (Adresse <= $FF!) ; 0 = Nächste Stelle der aktuellen Variable ; Variablenwerte 0..9 werden in ASCII '0'..'9' umgesetzt ; " $80..87 werden in Sonderzeichen 0..7 (siehe oben) umgesetzt ; ; Für Texte ohne Variablen genügen 18 Byte: ; Erste 16 Byte wie oben, danach 0,0 ; ; Der Festtext-Teil (die ersten 2*8 Bytes) kann sprachabhängig ; definiert werden. Dafür ist pro 8 Bytes (eine Zeile) die Syntax ; .DW $1010 .DB 'Deut Txt' .DB 'Engl Txt' .DB 'Spr3 Txt' ; ; >12345678< Power On STRPO: .DB " FJRX 2 " .DB " V. ",VERSHI,".",VERSLO," " .DW 0 ; ; >12345678< RX Off STR000: .DW $1010 ; 1,2,3 .DB "RX Aus ." .DB "RX Off ." .DB "RX Uit ." .DB "F:. :.s" .DB 1,2,3,4,5,6,7,LOCKED .DB 1,FOX,0,4,5,TIMER,0,8 ; ; >12345678< RX Off STR001: .DW $1010 ; 1,2,3 .DB "RX Aus ." .DB "RX Off ." .DB "RX Uit ." .DB ".:..:.. " .DB 1,2,3,4,5,6,7,LOCKED .DB STOPW,2,0,0,5,0,0,8 ; ; >12345678< Frequenz ändern + S-Meter anzeigen STR02: .DB "14.:... " .DB " " .DB 1,2,FRQ,FRQXSY,FRQ+1,0,0,8 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Timer, Entfernung + S-Meter anzeigen STR030: .DB ". :. :.." .DB " " .DB FOX+1,FRQXSY,TIMER,0,AUTOON,DIST,0,0 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Stopuhr, Entfernung + S-Meter anzeigen STR031: .DB ". .. :.." .DB " " .DB STOPW,FRQXSY,STOPW+1,0,AUTOON,DIST,0,0 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Stopuhr stoppen STR040: .DW $1010 ; 1,2,3 .DB "Uhr Stop" .DB "Clk Stop" .DB "Klk Stop" .DB ".:..:.. " .DB 1,2,3,4,5,6,7,8 .DB STOPW,2,0,0,5,0,0,8 ; ; >12345678< Stopuhr neu starten STR041: .DW $1010 ; 1,2,3 .DB "UhrStart" .DB "ClkStart" .DB "KlkStart" .DB ".:..:.. " .DB 1,2,3,4,5,6,7,8 .DB STOPW,2,0,0,5,0,0,8 ; ; >12345678< Timer neu starten STR05: .DB "TmrStart" .DB "F:. :.s" .DB 1,2,3,4,5,6,7,8 .DB 1,FOX,0,4,5,TIMER,0,8 ; ; >12345678< Set-Up-Menu aufrufen STR06: .DW $1010 ; 1,2,3 .DB "Einstell" .DB "Setup- " .DB "Setup- " .DW $1010 ; 1,2,3 .DB $7E," -men",$F5 .DB $7E," menu" .DB $7E," -menu" .DW 0 ; ; >12345678< Frequenz ändern anbieten STR07: .DB "14.:... " .DW $1010 ; 1,2,3 .DB $7E," ",$E1,"ndern" .DB $7E," change" .DB $7E," wijzig" .DB 1,2,FRQ,FRQXSY,FRQ+1,0,0,8 .DB 1,2,3,4,5,6,7,8 ; ; >12345678< Sendeleistung Füchse einstellen STR10: .DW $1010 ; 1,2,3 .DB "P Fu :.." .DB "PFox :.." .DB "PVos :.." .DB ":.,. .W " .DB 1,2,3,4,5,DIST,0,0 .DB PFOX,0,3,0,5,0,7,8 ; ; >12345678< Sendeleistung Füchse auf 'Nur dB Anzeige' STR100: .DW $1010 ; 1,2,3 .DB "P Fuchs " .DB "P Fox " .DB "P Vos " .DW $1010 ; 1,2,3 .DB "nur dB " .DB "dB only " .DB "alleen ",0 .DW 0 ; ; >12345678< Zahl Füchse einstellen STR11: .DW $1010 ; 1,2,3 .DB "N F",$F5,"chse" .DB "N Foxes " .DB "N Vossen" .DB " :. " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,NFOX,0,6,7,8 ; ; >12345678< Zeit Füchse Sekunden einstellen STR12: .DW $1010 ; 1,2,3 .DB "T Fuchs " .DB "T Fox " .DB "T Vos " .DB ">:.<,..s" .DB 1,2,3,4,5,6,7,8 .DB 1,TFOXS,0,4,5,0,0,8 ; ; >12345678< Zeit Füchse ms einstellen STR13: .DW $1010 ; 1,2,3 .DB "T Fuchs " .DB "T Fox " .DB "T Vos " .DB ":.,>..12345678< Zahl Frequenzen einstellen STR14: .DB " N Freq." .DB " : " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,NFREQ,5,6,7,8 ; ; >12345678< Sondermodus 12<>3 STR145: .DB " N Freq." .DB " 12<>3 " .DW 0 ; ; >1234567< Sondermodus 1x2<>3 STR146: .DB " N Freq." .DB "1x2<>3 " .DW 0 ; ; >12345678< EOT Alarmzeit einstellen STR15: .DB "T Alarm " .DB "- :.s " .DB 1,2,3,4,5,6,7,8 .DB 1,2,TALARM,0,5,6,7,8 ; ; >12345678< EOT Alarmzeit Aus STR150: .DB "T Alarm " .DW $1010 ; 1,2,3 .DB " Aus " .DB " Off " .DB " Uit " .DW 0 ; ; >12345678< Akustisches S-Meter Schwelle einstellen STR16: .DW $1010 ; 1,2,3 .DB "Akust.SM" .DB "AcoustSM" .DB "AkoestSM" .DW $1010 ; 1,2,3 .DB $F5,"ber ./8" .DB "over ./8" .DB "over ./8" .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,4,5,ACSMLV,7,8 ; ; >12345678< STR20: .DW $1010 ; 1,2,3 .DB "Sprache " .DB "Language" .DB "Taal " .DW $1010 ; 1,2,3 .DB "Deutsch " .DB "English " .DB "Nederlds" .DW 0 ; ; >12345678< STR21: .DB " EEPROM " .DB $7E," Reset " .DW 0 ; ; >12345678< UBat kalibrieren STR22: .DW $1010 ; 1,2,3 .DB "Abg UBat" .DB "Cal VBat" .DB "Kal VBat" .DB "...:.,.V" .DB 1,2,3,4,5,6,7,8 .DB UBFVAL,0,0,UBATT,0,6,0,8 ; ; >12345678< Frequenz kalibrieren STR23: .DW $1010 ; 1,2,3 .DB "AbgF ..." .DB "CalF ..." .DB "KalF ..." .DB "........" .DB 1,2,3,4,5,FFIVAL,0,0 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Abschwächer kalibrieren STR24: .DW $1010 ; 1,2,3 .DB "Abg Absw" .DB "Cal Att." .DB "KalVerzw" .DB $7E," Start " .DW 0 ; ; >12345678< Frequenzbereich ..146 STR250: .DW $1010 ; 1,2,3 .DB "FBereich" .DB "F-Range " .DB "F-Bereik" .DB "144-146",$7E .DW 0 ; ; >12345678< Frequenzbereich ..148 STR251: .DW $1010 ; 1,2,3 .DB "FBereich" .DB "F-Range " .DB "F-Bereik" .DB "144-148",$7F .DW 0 ; ; >12345678< Batterie-Warnschwelle einstellen STR26: .DB "BatAlarm" .DB "< .,. V " .DB 1,2,3,4,5,6,7,8 .DB 1,2,UBWARN,4,0,6,7,8 ; ; >12345678< Entfernungs-Korrektur STR27: .DW $1010 ; 1,2,3 .DB "Abg Entf" .DB "Cal Dist" .DB "Kal Afst" .DB " .. " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,DCFVAL,0,6,7,8 ; ; >12345678< Abgleich sichern STR28: .DW $1010 ; 1,2,3 .DB "Abgleich" .DB "Save Cal" .DB "OpslagKa" .DW $1010 ; 1,2,3 .DB $7E,"Sichern" .DB $7E," Values" .DB "libratie" .DW 0 ; ; >12345678< Ein Wert Abschwächer kalibrieren STRCAL: .DB ":.. :..",0 .DB " " .DB ABSVAL,0,0,4,ABSCHW,0,0,8 .DB UMESS,0,0,0,0,0,0,0 ; ; ** Die folgenden Strings sind Flash-Meldungen ; ; >12345678< Geänderte Daten in EEPROM schreiben STRSAV: .DB ">>EEPROM" .DB " " .DW 0 ; ; >12345678< EEPROM Umorganisation STRMIG: .DB " EEPROM " .DB " Reorg. " .DW 0 ; ; >12345678< Batteriespannung niedrig STRBAT: .DW $1010 ; 1,2,3 .DB "Batterie" .DB "Battery " .DB "Batterij" .DB " < .,. V" .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,UBWARN,5,0,7,8 ; ; >12345678< Menü neu aufgemacht STRMEN: .DB "14..... " .DB ".:..:.,." .DB 1,2,FRQ,FRQXSY,FRQ+1,0,0,LOCKED .DB STOPW,1,0,0,UBATT,0,7,0 ; ; >12345678< Kanal geändert STRFRQ: .DB "14..... " .DB " - . -" .DB 1,2,FRQ,FRQXSY,FRQ+1,0,0,8 .DB 1,2,3,4,5,FRQX,7,8 ; ; >12345678< Abschwächer-Automatik aus STRAA0: .DW $1010 ; 1,2,3 .DB "Automa- " .DB "Auto-Att" .DB "Verzwak." .DW $1010 ; 1,2,3 .DB "tik AUS" .DB " OFF " .DB "Auto UIT" .DW 0 ; ; >12345678< Abschwächerautomatik ein STRAA1: .DW $1010 ; 1,2,3 .DB "Automa- " .DB "Auto-Att" .DB "Verzwak." .DW $1010 ; 1,2,3 .DB "tik EIN" .DB " ON " .DB "Auto AAN" .DW 0 ; ; >12345678< Sendezeit-Ende Alarm STRALA: .DW $1010 ; 1,2,3 .DB " Noch " .DB " Only " .DB " Nog " .DB " :. sec " .DB 1,2,3,4,5,6,7,8 .DB 1,TALARM,0,4,5,6,7,8 ; ; ***************** ; **** Sound Strings ********************************************* ; ***************** ; ; Diese Strings enthalten Tonwertfolgen, die im 100ms-Raster ; abgespielt werden. Frequenz ist 10 kHz / Wert: ; 3 = 3,3 kHz, 10 = 1 kHz, 100 = 100 Hz ; Sonderfälle: 1 = kein Ton, 0 = End of String ; SOUPO: .DB 1,1,10,1,8,8,1,10 ; Power-On-Fanfare .DB 1,13,13,13,1,1,1,1,1,0 ; SOUABS: .DB 1,1,20,10,1,1,0,0 ; Automatik-Abschwächer SOUAB2: .DB 20,10,20,10,1,1,0,0 ; dto., Sound für Serie ; SOUALA: .DB 3,4,6,9,12,18,24,0 ; 'Ende - x sec'-Alarm ; SOUBAT: .DB 1,8,11,15,20,26,8,11 ; Low Battery Alarm .DB 15,20,26,8,11,15,20,26 ; .DB 1,0 ; SOUAA1: .DB 1,24,24,18,18,12,12,9,9,1,0,0 ; Automatik-Abschwächer Ein SOUAA0: .DB 1,9,9,12,12,18,18,24,24,1,0,0 ; Automatik-Abschwächer Aus ; SOUF1: .DB 1,24,18,12,9,6,1,1,10,1,1,0 ; Frequenz 1 SOUF2: .DB 1,24,18,12,9,6,1,1,10,1,10,1,1,0 ; F 2 SOUF3: .DB 1,24,18,12,9,6,1,1,10,1,10,1,10,1,1,0 ; F 3 SOUF4: .DB 1,24,18,12,9,6,1,1,10,1,10,1,10,1,10,1,1,0 ; F 4 ; SOUOK: .DB 1,1,15,1,15,15,15,1,15,1,1,0 ; Ok ; ; ; ************************ ;******** This is the End..... *************************************** ; ************************