; FJRX82.ASM ; ; *************************** ; * 80m Fuchsjagd Empfänger * ; *************************** ; ; Code für 80m Fuchsjagd-Empfänger-Steuerung ; ; Unterstützt den 80m-Fuchsjagdempfänger Version 2 ; ; Autor: Nick Roethe, DF1FO, DF1FO at darc.de ; ; Dieser Codestand basiert auf der 2m-Fuchsjagd-Empfänger-Steuerung ; FJRX2 3.0. Die Hardware-Treiber stammen aus FJRX81 0.5 . ; ; Start des Codemerge 23.11.2006 ; Version 0.0: Code-Import von FJRX2, Bedienoberfläche angepasst ; 0.1: Frequenzeinstellung ok ; 0.2: Entfernungsanzeige fast ok ; 24.11.06 0.3: Full Function ; 26.11.06 0.4: Entfernungs-Korrektur im Abgleichmenü ; 27. 4.07 0.5: Feinverstimmung +/-100Hz durch Drehen in Modus Peilen (OE6GC) ; 15. 5.07 0.6: Foxoring-Erweiterungen: PFuchs 1µW bis 30W ; Bei NFuchs=1 Stopuhr statt Timer zeigen, Alarm aus ; 13. 6.07 0.7: Akustisches S-Meter eingebaut ; 20. 6.07 0.8: Akustisches S-Meter setzt erst ab 50% S-Meter ein ; 21. 6.07 0.9: Dämpfungsannahme für Entfernung 20dB/10x < 100m, 40 dB > 100m ; Einstellmenü startet mit PFuchs ; 23. 6.07 1.0: Dämpfungsannahme > 100 m wieder 30 db/10x ; 28. 6.07 1.1: Kennlinie ACSM steiler im Bereich S-Meter 50%-100% ; 5. 7.07 1.2: ACSM unabhängig von HF-Regler ; 18. 7.07 1.3: Quarzfrequenz ATMega von 16 MHz auf 10,24 MHz verringert ; 19. 7.07 1.4: Save to EEPROM: immer zur vollen Sekunde, nur die Änderungen ; Haltezeit Balken-S-Meter halbiert ; 1.5: Version obsolet (Anzeige V/R im Display - überflüssig) ; 1.6: Version obsolet (Vorversion zu 1.7 für DM) ; 17. 8.07 1.7: Feinabstimmung in Mode Peilen im Abgleichmenü abwählbar (GRANE) ; Menüpunkt Abschwächer-Tabelle lesen im Abgleichmenü ; ; 31.12.07 1.8: Funktionen/Änderungen aus FJRX2 4.1 (vs. 3.3) übernommen: ; * EEPROM Init nur aus Abgleichmenü (nicht automatisch) ; * Diverse Flash-Sparmassnahmen, insb. STSI Makro optimiert, ; 64B für LCD CGRAM als Tabelle im Flash ; * Frequenz#-Umschaltung Mode Peilen zittersicher ; * Entfernungsschätzung abschaltbar im PFuchs-Menü ; * Einstellbereich DISTCF -5..+5 (statt 0..9) ; * Neue Signaltöne Power-On, Frequenzwechsel, Low Battery ; * Low Battery Alarm 10 sec später (für DL9TE) ; * Quittungston nach jeder Eingabe 'Abgleich Abschwächer' ; - Nicht übernommen: o Unterstützung für 3 Sprachen ; o Spezial-Modi 12<>3 und 1x2<>3 ; 30. 1.08 1.9: S-Meter-Empfindlichkeit 6 dB höher = weniger NF-Verzerrungen ; Dynamikbereich ASM vergrössert auf 10 dB (S-Meter 0,5..1,5) ; Fix für 'EEPCLR wird nicht initialisiert' ; 1. 3.08 2.0: EEPROM-Erst-Initialisierung erfolgt automatisch ; 8. 3.08 2.1: 3. Variante: EEPROM-Erst-Initialisierung nur aus Abgleich-Menü ; 18. 7.08 2.2: Fix für falsche '<5m'-Anzeige bei kleinen dB-Werten ; 22. 9.08 2.3: Fix für 'nur dB'-Anzeige (die funktionierte bisher nicht) ; 15.12.08 2.4: Fix für falsche '<5m'-Anzeige bei Abschwächer-Linksanschlag (Tnx PA1FOX) ; .equ VERSHI= '2' .equ VERSLO= '4' ; .equ VALKEY= $A8 ; EEPROM Valid Key auf Adresse EEPCLR ; ; **** Specify Device .device ATmega8; ; >> FUSES << : EESAVE = 0 ; =========== CKSEL = 1111, SUT = 11 ; Externer Quarz ; 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 ; ;-------------------------------------------------------- ; ; **** 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 ; ; **** Constant-Register Definitions .def C0 =r8 ; Constant 0 .def C1 =r9 ; Constant 1 ; **** Index-Register Definitions .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 ; ; **** S-Meter Scaling Factor .equ SMSCAL =$C0 ;S-Meter-Scaling-Factor (Higher = more sensitivity) ; ; **** Variablen *************************************************** .DSEG .ORG RAMBEG ; Start of RAM address range ($0060) ; ; ++ Eingestellte Parameter, werden im EEPROM gerettet EEPCLR: .BYTE 1 ; $FF wenn EEPROM gelöscht, VALKEY wenn gültig, sonst ungültig/alt ; EEP0: ; Beginn des Frequenz-Bereichs FRQ1: .BYTE 2 ; Frequenz-Codewert 100 Hz-Schritte Frequenz 1 ; 0..3200 = 3,49..3,81, 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 ; EEP1: ; Grenze zwischen Frequenz- und HW-SetUp-Bereich 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..98 in 2er 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..4 TALARM: .BYTE 2 ; EOT Alarm Vorlaufzeit 0..31 sec, 0 = Aus Z,E ; EEP2: ; Grenze zwischen HW-SetUp und Abgleich-Bereich LEVTAB: .BYTE 12 ; Tabelle Level-Werte 0,10,20..110 dB FFINE: .BYTE 1 ; Frequenz Fein 128 -/+ 99 = -9,9..+9,9 kHz UBFINE: .BYTE 1 ; Skalierungswert für Ub-Messung 0..255 UBWBIN: .BYTE 1 ; Schwelle Batteriewarnung in 1/10 V (60..80) DISTCF: .BYTE 1 ; Anpassung Entfernungsschätzung 0..10 (Anz. -5..+5) FRQBER: .BYTE 1 ; Frequenzbereich 0 = 3,49-3,66, 1 = 3,49-3,81 FINTUN: .BYTE 1 ; Feinabstimmung im Modus Peilen 0 = Aus, 1 = Ein 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..3200 = 3490.0 .. 3810.0, LSB,MSB 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..16 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 FFIVAL: .BYTE 3 ; FFINE Anzeigewert -/+0..99 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 FLATIM: .BYTE 1 ; Verbleibende Flashtime für Text-Flash (n * 100 ms) FLASTR: .BYTE 2 ; Pointer auf aktuellen Flash String H,L SOUPNT: .BYTE 2 ; Pointer auf Soundstring LSB,MSB; Fertig bei MSB = 0 UBWARN: .BYTE 2 ; Batteriewarnungsschwelle V/mV E,h LEVDZ: .BYTE 3 ; Messpannung Abschwächerlevel Dez H,Z,E LEVEL: .BYTE 1 ; Level 0..11 = 0 .. 110 dB für Cal/Read Absw Level LEVRDZ: .BYTE 2 ; Level 0..11 Dez. Z,E für Read Absw Level ACSMON: .BYTE 1 ; Akustisches S-Meter ein = 1, aus = 0 ACSMTH: .BYTE 1 ; Akustisches S-Meter > Schwelle = 1, < = 0 ; ++ 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 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 FSOLLH: .BYTE 1 ; Sollfrequenz High Byte (Soll ist $2HHLL) FSOLLL: .BYTE 1 ; Sollfrequenz Low Byte FISTH: .BYTE 1 ; Istfrequenz High Byte (Ist ist $2HHLL) FISTL: .BYTE 1 ; Istfrequenz Low Byte ; ++ Interrupt-Handler DEBP1: .BYTE 1 ; Debounce Counter Drehgeber DEBDD: .BYTE 1 ; Debounce Drücker Drehgeber TIK1M: .BYTE 1 ; Zaehlt jede 1 ms bis 20 (20 msec) 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) TIK150: .BYTE 1 ; Zaehlt jede 1 msec bis 50 (für TUNE) TUNLEN: .BYTE 1 ; Abstimmpulslänge in ms (für TUNE) ; ; ********************** ; **** 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 rcall OUTLCD ; .. und Ergebnis anzeigen .ENDMACRO ; ; ++++ Flash Text String @0 for @1*100ms .MACRO FLASH ldi ZL,low(2*@0) ; Ausgabe-Kommand-String ldi ZH,high(2*@0) sts FLASTR,ZH sts FLASTR+1,ZL rcall LCDSTR ; .. ausführen rcall OUTLCD ; .. und Ergebnis anzeigen ldi ZL,@1 ; Flash Timer aufsetzen sts FLATIM,ZL ; .ENDMACRO ; ; ++++ Start F-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 ; ; ; ++++ Initialisiere Steuer-Parameter ; Called if EEPROM is empty or by menu item 'EEPROM Reset' EEPNEW: stsi FRQ1,$84 ; Frequenz 1 3,580 stsi FRQ1+1,$03 stsi FRQ2,$A4 ; Frequenz 2 3,660 stsi FRQ2+1,$06 stsi FRQ3,$00 ; Frequenz 3 3,490 stsi FRQ3+1,$00 stsi FRQ4,$00 ; Frequenz 4 stsi FRQ4+1,$00 stsi FRQX,1 ; Frequenz 1 aktiv stsi NFOX,0 ; Zahl Füchse = 5 stsi NFOX+1,5 stsi TFOXS,6 ; Zeit Füchse = 60 sec stsi TFOXS+1,0 stsi TFOXMS,0 stsi TFOXMS+1,0 stsi PFOXBN,12 ; Sendeleistung 1 Watt stsi NFREQ,3 ; 3 Frequenzen stsi TALARM,1 ; Alarmzeit 10s stsi TALARM+1,0 stsi LEVTAB+0,40 ; Leveltabelle laden stsi LEVTAB+1,54 ; 0..110 dB in 10 dB Schritten stsi LEVTAB+2,61 stsi LEVTAB+3,68 stsi LEVTAB+4,71 stsi LEVTAB+5,75 stsi LEVTAB+6,92 stsi LEVTAB+7,97 stsi LEVTAB+8,103 stsi LEVTAB+9,123 stsi LEVTAB+10,123 stsi LEVTAB+11,123 stsi FFINE,128-88 ; Feinverstimmung - 88 * 100 Hz (für 460kHz Filter) stsi UBFINE,117 ; Batterieanzeigekorrektur Mittelwert stsi UBWBIN,70 ; Batteriewarnschwelle 7 Volt stsi DISTCF,5 ; Entfernungsanzeige-Korrektur, Mittelwert stsi FRQBER,0 ; Frequenzbereich 3,49 - 3,66 stsi FINTUN,1 ; Feinabstimmung in Modus Peil Ein ; ret ; ; ***************************** ; **** 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 P0 with Pull-Up ; 1 as Input P1 with Pull-Up ; 2 as Output Uabst in HZ ; 3 as Output Sound in HZ ; 4 as Input Drücker with Pull-Up ; 5 as Input (Unused) ; PB3..PB5 also SPI-I/F ldi R16,$00 out DDRB,R16 ldi R16,$13 out PORTB,R16 ; ; ++++ Initialize Port C Bit 0..2 as Analog In URicht, URegel, Ub ; 3 as Input (Unused) ; 4 as Output Mute in HZ ; 5 as Display E Output ldi R16,$20 out DDRC,R16 ldi R16,$00 out PORTC,R16 ; ; ++++ Initialize Port D Bit 0..4 as Output for Display ; 5 as Counter Input Timer 1 ; 6 as Input (Unused) ; 7 as Input w P-Up for Menu-Switch ldi R16,$1F out DDRD,R16 ldi R16,$80 out PORTD,R16 ; ; ++++ Initialize A/D-Converter LDI R16,$00 ; Select Analog Input 0 OUT ADMUX,R16 LDI R16,$86 ; Enable ADC, Clock Divider 64 = 125 kHz OUT ADCSR,R16 ; = 250 usec Conversion Time ; ; ++++ Intialize Timer/Counter 0 as 1 ms Interrupt (10,24MHz/64/160) ldi R16,$03 ; Set Clock Divider to 64 out TCCR0,R16 ldi R16,256-160 ; Set Counter to Startvalue out TCNT0,R16 ldi R16,$01 out TIMSK,R16 ; Enable Counter 0 Overflow Interrupt ; ; ++++ Intialize Timer/Counter 1 as Frequency Counter ldi R16,$00 ; Count Rising Edges on T1 Input out TCCR1A,R16 ldi R16,$07 out TCCR1B,R16 ; ; ++++ Intialize Timer/Counter 2 as Frequency Generator for Sounds ldi R16,$1D ; Clock Divider 128, CTC, Toggle on Compare out TCCR2,R16 ; ; ; ++++ Get Steuer-Parameter from EEPROM ; Wenn EEPROM ungültig: initialisieren rcall GETEEP ; Parameter aus EEPROM holen ; lds R16,EEPCLR ; Hat EEPROM gültigen Inhalt? cpi R16,VALKEY breq STA03 ; .. sonst Parameter initialisieren rcall EEPNEW ; .. aber nicht ins EEPROM kopieren! ; ; ++++ Initialize some Variables STA03: stsi STOPWR,1 ; Stopuhr läuft nach Power-On an stsi BATTIM,100 ; Erste Batteriespannungsprüfung nach 10s ; 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 lds R16,EEPCLR ; Wenn EEPROM Valid cpi R16,VALKEY brne STA04 sound SOUPO ; Power-On-Fanfare rjmp STA09 STA04: sound SOUHI ; Sonst 'Hi' ; STA09: rjmp MAIN6 ; Start Main Loop with A/D of UBat ; ; ************* ; **** Main Loop *************************************************** ; ************* ; MAIN: ; ++++ Mode Updaten MAIN2: lds R16,MODE ; Mode holen ; sbis PIND,7 ; Wenn Schalter nicht auf Menü (=Peilen) rjmp M21 ldi R16,3 ; .... dann Mode 3 rjmp M29 ; M21: sbic PIND,7 ; Wenn Schalter auf Menü 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 tst R17 ; Wenn irgendein Flag gesetzt breq MAIN31 clr R18 ; .. dann laufende Flashes abbrechen sts FLATIM,R18 ; ; Bei Mode 0 (RX Off) sonst nix tun, nur Flags löschen ; MAIN31: lds R16,MODE cpi R16,3 ; Bei Mode 3 brne M30 ; lds R18,SOUPNT+1 ; Wenn kein Sound aktiv tst R18 ; .. und Drehen+Drücken: Frequenz weiterschalten brne MA311 ; .. (Verhindert Mehrfachschalten) sbrc R17,2 ; Up+Pressed Flag rcall NEXTF ; = nächste Frequenz sbrc R17,3 ; Down+Pressed Flag rcall PREVF ; = vorige Frequenz ; MA311: sbrs R17,4 ; Wenn Click Flag gesetzt.. rjmp M300 lds R16,ACSMON ; .. Akustisches S-Meter Ein/Aus toggeln ldi R18,1 eor R16,R18 sts ACSMON,R16 ; M300: lds R18,FINTUN ; Wenn Feinabstimmung im Mode Peilen gewünscht tst R18 breq M301 andi R17,$03 ; und Drehen ohne Drücken breq M301 lsl R17 ; Flags in Position für lsl R17 rcall UDFRQ ; +/- 100 Hz Abstimmung flash STR02,10 ; Frequenz String flashen ; M301: 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 M331 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..$15 ,$20..$2A brne M332 ; beschränken ldi R16,4 M332: cpi R16,3 brne M333 ldi R16,7 M333: cpi R16,$16 brne M334 ldi R16,$10 M334: cpi R16,$0F brne M335 ldi R16,$15 M335: cpi R16,$2B brne M336 ldi R16,$20 M336: cpi R16,$1F brne M337 ldi R16,$2A 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,$13 ; .. dann neuer Mode 13 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 UDNF ; .. dann N Füchse verändern rjmp M399 ; M311: cpi R16,$11 ; Wenn Mode = 11 brne M312 rcall UDTFS ; .. dann T Fuchs Sekunden verändern rjmp M399 ; M312: cpi R16,$12 ; Wenn Mode = 12 brne M313 rcall UDTFMS ; .. dann T Fuchs ms verändern rjmp M399 ; M313: cpi R16,$13 ; Wenn Mode = 13 brne M314 rcall UDPF ; .. dann Leistung Fuchs 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 M320 rcall UDTA ; .. dann EOT Alarmzeit verändern rjmp M399 ; M320: cpi R16,$20 ; Wenn Mode = 20 brne M321 ; .. nix tun ; M321: cpi R16,$21 ; Wenn Mode = 21 brne M322 sbrs R17,4 ; .. und Drehdrücker Click rjmp M322 rcall EEPNEW ; .... dann EEPROM initialisieren 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 CALLEV ; .. dann Abschwächer-Levels eichen rjmp M399 ; M325: cpi R16,$25 ; Wenn Mode = 25 brne M326 rcall READLV ; .. dann Abschwächer-Levels anzeigen 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 CALDIS ; .. dann Distanz kalibrieren rjmp M399 ; M328: cpi R16,$28 ; Wenn Mode = 28 brne M329 sbrs R17,4 ; .. und Drehdrücker Click rjmp M399 lds R18,FRQBER ; .. Frequenzbereich toggeln ldi R19,1 eor R18,R19 and R18,R19 sts FRQBER,R18 rjmp M399 ; M329: cpi R16,$29 ; Wenn Mode = 29 brne M32A sbrs R17,4 ; .. und Drehdrücker Click rjmp M399 lds R18,FINTUN ; .. Feinabstimmung in Mode Tune toggeln ldi R19,1 eor R18,R19 and R18,R19 sts FINTUN,R18 rjmp M399 ; M32A: cpi R16,$2A ; Wenn Mode = 2A brne M399 sbrs R17,4 ; .. und Drehdrücker Click rjmp M399 stsi EEPCLR,VALKEY ; .... EEPROM valid key setzen 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: clr R16 sts TICK,R16 ; ; ++++ 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 MAINB1 lds R17,MODE ; und Mode = 3 cpi R17,3 brne MAINB1 lds R18,NFOX+1 ; und > 1 Fuchs.. cpi R18,1 breq MAINB1 sound SOUALA ; .. dann Tonsignal flash STRALA,8 ; .. und Meldung zeigen ; ; ++++ 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,50 ; Sonst Alarm-Text und -Sound sound SOUBAT MAINB6: ; ; ++++ Batteriespannung A/D-konvertieren und skalieren MAIN6: ldi R16,2 ; Analog-Channel 2 = 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 ; ; ++++ Entfernungsanzeige und S-Meter-Balken erzeugen ; rcall ADDIST ; 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 lds ZH,FLASTR ; .. Flash-String auffrischen lds ZL,FLASTR+1 rcall LCDSTR rcall OUTLCD ; .. und Ergebnis anzeigen rjmp MAIN8 ; 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 brne M710 show STR07 M710: cpi R16,$10 brne M711 show STR10 M711: cpi R16,$11 brne M712 show STR11 M712: cpi R16,$12 brne M713 show STR12 M713: cpi R16,$13 brne M714 lds R18,PFOXBN ; Wenn PFOXBN = 16 cpi R18,16 brne M7131 show STR130 ; .. Entfernungsanzeige aus rjmp M714 M7131: show STR13 M714: cpi R16,$14 brne M715 show STR14 M715: cpi R16,$15 brne M720 show STR15 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 show STR25 M726: cpi R16,$26 brne M727 show STR26 M727: cpi R16,$27 brne M728 show STR27 M728: cpi R16,$28 brne M729 lds R18,FRQBER tst R18 brne M7281 show STR280 rjmp M729 M7281: show STR281 M729: cpi R16,$29 brne M72A lds R18,FINTUN tst R18 brne M7291 show STR290 rjmp M72A M7291: show STR291 M72A: cpi R16,$2A brne M799 show STR2A M799: ; ++++ Sollfrequenz für Regelung bereitstellen MAIN8: rcall SETFRQ ; ++++ Soundgenerator ausführen rcall SOUGEN ; ; ++++ 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: push R16 ldi R16,0 sts STOPWR,R16 ; Run-Flag löschen sts STOPW,R16 ; Zeit auf 0 setzen sts STOPW+1,R16 sts STOPW+2,R16 sts STOPW+3,R16 sts STOPW+4,R16 ldi R16,1 ; und Run-Flag setzen sts STOPWR,R16 pop R16 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..4) verändern UDNFRQ: lds R16,NFREQ dec R16 ; 1..4 -> 0..3 sbrs R17,2 ; Up Flag rjmp NFRQ2 inc R16 rjmp NFRQ8 NFRQ2: sbrs R17,3 ; Down Flag rjmp NFRQ9 dec R16 NFRQ8: andi R16,$03 ; Limit to 0..3 inc R16 sts NFREQ,R16 stsi FRQX,1 ; Nach Änderung: Frequenz 1 aktivieren rcall GETFRQ ; Neue Frequenz holen rcall CONVF ; .. und in Anzeigewert umrechnen NFRQ9: ret ; ; **** EOT Alarm-Zeit (0..30) verändern UDTA: push R16 lds R16,TALARM ; Wenn Alarmzeit = 'Au' cpi R16,'A' brne TA1 stsi TALARM,0 ; .. durch 00 ersetzen stsi TALARM+1,0 ; TA1: sbrs R17,2 ; Up Flag rjmp TA2 i2bcd TALARM,0,30 rjmp TA3 TA2: sbrs R17,3 ; Down Flag rjmp TA8 d2bcd TALARM,0,30 TA3: ; TA8: lds R16,TALARM ; Wenn Alarmzeit = 00 tst R16 brne TA9 lds R16,TALARM+1 tst R16 brne TA9 stsi TALARM,'A' ; .. durch 'Au' ersetzen stsi TALARM+1,'u' ; TA9: 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..15 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 ; ; **** Textstring für Fuchsleistung in PFOX stellen CONVPF: push R16 clr R16 ; Erst mal alles auf 0 sts PFOX,R16 sts PFOX+1,R16 sts PFOX+2,R16 stsi PFOX+3,'m' ; lds R16,PFOXBN ; Binaer Code für Leistung CPF0: cpi R16,0 brne CPF1 stsi PFOX+1,1 stsi PFOX+3,$E4 ; 'µ' CPF1: cpi R16,1 brne CPF2 stsi PFOX+1,3 stsi PFOX+3,$E4 ; 'µ' CPF2: cpi R16,2 brne CPF3 stsi PFOX+0,1 stsi PFOX+3,$E4 ; 'µ' CPF3: cpi R16,3 brne CPF4 stsi PFOX+0,3 stsi PFOX+3,$E4 ; 'µ' 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 stsi PFOX+3,' ' CPF11: cpi R16,11 brne CPF12 stsi PFOX+2,3 stsi PFOX+3,' ' CPF12: cpi R16,12 brne CPF13 stsi PFOX+1,1 stsi PFOX+3,' ' CPF13: cpi R16,13 brne CPF14 stsi PFOX+1,3 stsi PFOX+3,' ' CPF14: cpi R16,14 brne CPF15 stsi PFOX+0,1 stsi PFOX+3,' ' CPF15: cpi R16,15 brne CPF99 stsi PFOX+0,3 stsi PFOX+3,' ' CPF99: pop R16 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 ; +/- 1 kHz adiw R24,10 sbrc R17,1 sbiw R24,10 sbrc R17,2 ; +/- 100 Hz adiw R24,1 sbrc R17,3 sbiw R24,1 ; UDFRQ2: tst R25 ; Wenn Ergebnis negativ brpl UDFRQ3 clr R24 ; .. auf 0 setzen clr R25 ; UDFRQ3: lds R18,FRQBER ; Wenn Frequenzbereich bis 3,66 MHz tst R18 brne UDFRQ4 cpi R25,$06 ; und wenn Ergebnis > 1700 = $06A4 brne UDFRQ8 cpi R24,$A4 brcs UDFRQ8 ldi R24,$A4 ; .. auf 1700 setzen rjmp UDFRQ8 ; ; ; Wenn Frequenzbereich bis 3,81 MHz UDFRQ4: cpi R25,$0C ; und wenn Ergebnis > 3200 = $0C80 brne UDFRQ8 cpi R24,$80 brcs UDFRQ8 ldi R24,$80 ; .. auf 3200 setzen ; 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 ; UDFRQ9: ret ; ; ; Switch to next Frequency NEXTF: push R17 rcall PUTFRQ ; Put current frequency FRQBIN -> FRQ1..4 ; lds R16,FRQX ; Frequenz-Nummer weiterschalten lds R17,NFREQ ; .. und bei > Maximum nach 1 wrappen cp R16,R17 brne NEXTF1 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 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 dec R16 brne PREVF1 lds R16,NFREQ ; .. und bei 1 nach Maximum wrappen PREVF1: rjmp NEXTF2 ; Weiter wie bei NEXTF ; ; 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 LSB lds R25,FRQBIN+1 ; dto MSB ; Codewort ist im Bereich 0 .. 1700 ldi R16,4 ; 100 kHz Startwert ldi R17,9 ; 10 kHz ldi R18,0 ; 1 kHz ldi R19,0 ; 100 Hz adiw R24,1 ; Codewort inkrementieren ; ; Anzeige = Startwert 3490,0 + Codewort * 100 Hz CONVF4: sbiw R24,1 ; Codewort dekrementieren breq CONVF5 ; Wenn noch nicht 0 inc R19 ; .. Anzeige dezimal inkrementieren cpi R19,10 brne CONVF4 clr R19 inc R18 cpi R18,10 brne CONVF4 clr R18 inc R17 cpi R17,10 brne CONVF4 clr R17 inc R16 rjmp CONVF4 ; CONVF5: sts FRQ,R16 sts FRQ+1,R17 sts FRQ+2,R18 sts FRQ+3,R19 ; ret ; ; **** Zähler-Sollwert ausrechnen und übergeben ****************** SETFRQ: push R16 push R17 push R24 push R25 ; ldi R16,$0E ; Hex von 34900 - 4550 - 128, LSB ldi R17,$76 ; dto MSB ; lds R24,FFINE ; Frequenzabgleichwert 128 +/- 99 dazu clr R25 add R16,R24 adc R17,R25 ; lds R24,FRQBIN ; Frequenz-Codewort dazu (100 Hz Schritte) lds R25,FRQBIN+1 add R16,R24 adc R17,R25 ; mov R24,R16 ; * 5 wg. 20 Hz Counter-Auflösung mov R25,R17 clc rol R24 rol R25 clc rol R24 rol R25 add R16,R24 adc R17,R25 ; sts FSOLLL,R16 ; Als Sollwert ablegen sts FSOLLH,R17 ; pop R25 pop R24 pop R17 pop R16 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 UBFVAL wandeln ; pop R17 pop R16 ret ; ; **** Frequenznachstimmung eichen ; Bereich ist +/- 9,9kHz, Abgelegt in FFINE als 128 +/-..99 CALFFI: push R16 push R17 lds R16,FFINE ; Aktuellen Wert holen andi R17,$0C ; Wenn kein Flag gesetzt breq CALFF3 ; .. Änderungsteil überspringen ; sbrc R17,2 ; Increment? inc R16 sbrc R17,3 ; Decrement? dec R16 cpi R16,228 ; Oberes Limit +99 ? brne CALFF1 ldi R16,227 CALFF1: cpi R16,28 ; Unteres Limit -99 ? brne CALFF2 ldi R16,29 ; CALFF2: sts FFINE,R16 ; Aktuellen Wert speichern ; CALFF3: ldi R17,128 ; Anzeigewert ist FFINE - 128 sub R16,R17 ; .. = -99 .. +99 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 ; ; ; **** Entfernungsschätzung eichen ; Bereich Korrekturfaktor ist 0..9 CALDIS: push R16 push R17 lds R16,DISTCF ; Aktuellen Wert holen sbrc R17,2 ; Increment? inc R16 sbrc R17,3 ; Decrement? dec R16 cpi R16,11 ; Oberes Limit 10 ? brne CALDI1 ldi R16,10 CALDI1: cpi R16,-1 ; Unteres Limit 0 ? brne CALDI2 ldi R16,0 ; CALDI2: sts DISTCF,R16 ; Aktuellen Wert speichern ; ldi R17,5 ; 0..10 in -5..+5 umwandeln sub R16,R17 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 ; ; CALDI9: pop R17 pop R16 ret ; ; ; **** Abschwächer-Level eichen in 10 dB Schritten 0 .. 110 dB ; CALLEV: ldi R16,60 ; 1000 Hz rcall PIEPS ; .. Quittungston ldi YL,low(LEVTAB) ; Tabelle mit Abschwächerlevelwerten ldi YH,high(LEVTAB) stsi LEVEL,0 ; Pointer in Tabelle ; CALLE1: sbic PIND,7 ; Setup Mode verlassen? rjmp CALLE9 ; .. dann abbrechen ; ldi R16,1 ; Analog-Channel 0 = URegel ldi R19,$FF ; Scaling Factor clr R18 ; .. dto., Low Byte rcall ANACON ; A/D-Wandeln, Ergebnis-Bereich 0..255 mov R1,R16 ; Für später retten ; ldi XH,0 ; Pointer auf Anzeige-Fenster ldi XL,LEVDZ rcall B3BCD ; Ergebnis in BCD wandeln und ablegen ; lds R16,LEVEL ; Pegelstufe für Anzeige ldi XH,0 ; Pointer auf Anzeige-Fenster ldi XL,DIST rcall B3BCD ; Ergebnis in BCD wandeln und ablegen ; ldi R16,0 ; Analog-Channel 0 = UMESS ldi R19,SMSCAL ; Scaling Factor für S-Meter Empfindlichkeit clr R18 ; .. dto., Low Byte rcall ANACON ; A/D-Wandeln, Ergebnis-Bereich 0..255 sts UMESSP,R16 rcall CONVUM ; S-Meter updaten ; show STRLEV ; Display updaten ldi R25,200 ; Wait 200 msec for readable Display rcall DELXMS ; lds R17,SWIFLG ; Switch Flags holen clr R18 ; .. und löschen sts SWIFLG,R18 sbrs R17,4 ; Click? rjmp CALLE1 ; Nein: Loop ; st Y+,R1 ; Ja: Messwert in Tabelle ablegen ; ldi R16,120 ; 500 Hz rcall PIEPS ; .. Quittungston erzeugen lds R16,LEVEL ; Nächste 10 dB-Stufe inc R16 cpi R16,12 ; bis maximal 11 breq CALLE9 sts LEVEL,R16 rjmp CALLE1 ; CALLE9: stsi LEVEL,0 ; LEVEL auf 0 setzen für nachfolgendes READLV sound SOUOK ; Abschluss-Quittungston ret ; ; Erzeugen von Quittungs-Pieps ohne Verwendung des SOUND-Mechanismus ; Tonhöhe in R16 ; Für CALLEV erforderlich, weil Main-Loop nicht läuft PIEPS: out OCR2,R16 ; Variablen Oscillator laden sbi DDRC,4 ; Mute einschalten sbi DDRB,3 ; Sound einschalten ldi R25,100 ; Tonlänge 100 msec rcall DELXMS cbi DDRB,3 ; Sound ausschalten cbi DDRC,4 ; Mute ausschalten ret ; ; **** Abschwächer-Level lesen in 10 dB Schritten 0 .. 110 dB ; READLV: lds R16,LEVEL ; Pegelstufe für Anzeige holen und updaten sbrc R17,2 ; Increment? inc R16 sbrc R17,3 ; Decrement? dec R16 cpi R16,$FF ; Auf 0 .. 11 begrenzen brne READL1 clr R16 READL1: cpi R16,12 brne READL2 ldi R16,11 READL2: sts LEVEL,R16 ; ldi XH,0 ; Pointer auf Anzeige-Fenster ldi XL,LEVRDZ rcall B2BCD ; Pegelstufe in BCD wandeln und ablegen ; ldi XL,low(LEVTAB) ; Tabelle mit Abschwächerlevelwerten ldi XH,high(LEVTAB) clr R18 ; Adresse zu Eintrag @Pegel ausrechnen lds R16,LEVEL add XL,R16 adc XH,R18 ; ld R16,X ; Tabellenwert lesen ldi XH,0 ; Pointer auf Anzeige-Fenster ldi XL,LEVDZ rcall B3BCD ; Ergebnis in BCD wandeln und ablegen ; 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 ; Scale result 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:mp16uH:mp16uL. ; ; 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,0 ; Analog-Channel 0 = UMESS ldi R19,SMSCAL ; 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: rcall ACSM ; S-Meter akustisch ausgeben ret ; ; **** Akustisches S-Meter erzeugen ; Eingangswert ist UMESSA 0..255, Bar-S-Meter ab 127 am Anschlag ; Ton wird nur ausgegeben, wenn das akustische S-Meter eingeschaltet ist ; und das S-Meter mehr als 50% anzeigt. ; ACSM: lds R16,UMESSA ; Messpannung holen ldi R17,64 ; .. und um 64 verringern sub R16,R17 sbrc R16,7 ; Wenn >= 128 ldi R16,$7F ; auf 127 begrenzen asr R16 ; Auf 0..63 halbieren ; ldi R17,$FF ; Untere Eckfrequenz 250 Hz ; ACSM1: cpi R16,0 ; Wenn Messwert = 0 breq ACSM7 ; .. fertig, ausgeben ; dec R16 ; Messwert = Loopcounter dec R17 ; Frequenz 1 Stufe erhöhen cpi R16,32 ; Wenn Restwert kleiner 32 brcc ACSM1 ldi R19,2 ; .. Frequenz 2 weitere Stufen verringern sub R17,R19 cpi R16,16 ; Wenn Restwert kleiner 16 brcc ACSM1 ldi R19,7 ; .. Frequenz 7 weitere Stufen verringern sub R17,R19 rjmp ACSM1 ; ACSM7: lds R19,SOUPNT+1 ; Ist Sound Pointer <> 0 (Sound aktiv)? tst R19 brne ACSM9 ; .. dann nichts ausgeben ; ACSM71: in R16,TCNT2 ; Wait until Counter <16 andi R16,$F0 ; .. to avoid noise by counter tst R16 ; .. counting to max (< 5ms @ 200 Hz) brne ACSM71 ; out OCR2,R17 ; Variablen Oscillator laden ; lds R16,ACSMTH ; ACSM-Schwellwertschalter handeln lds R17,UMESSA ; Wenn Messpannung < 64 cpi R17,64 brcc ACSM72 clr R16 ; .. Schwellwertschalter aus ACSM72: cpi R17,70 ; Wenn Messpannung > 70 brcs ACSM73 ldi R16,1 ; .. Schwellwertschalter ein ACSM73: sts ACSMTH,R16 ; Abspeichern ; lds R16,ACSMON ; Wenn ACSMON auf 0 tst R16 breq ACSM80 lds R16,ACSMTH ; .. oder Messwert < S-Meter Mitte tst R16 brne ACSM81 ; ACSM80: cbi DDRB,3 ; dann Sound ausschalten cbi DDRC,4 ; .. und Mute ausschalten rjmp ACSM9 ; ACSM81: sbi DDRC,4 ; Sonst Mute einschalten cpi R17,$F0 ; und wenn S-Meter > 1/32 brcc ACSM82 sbi DDRB,3 ; .. Sound einschalten rjmp ACSM9 ACSM82: cbi DDRB,3 ; .. sonst Sound ausschalten ; 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 ; .. schon fertig ; SOUG1: lpm ; Get one Byte to R0 adiw ZL,1 ; Increment Z out OCR2,R0 ; Variablen Oscillator laden dec R0 ; Sonderfall Wert = 1 breq SOUG10 ; .. Piepser bleibt aus sbi DDRB,3 ; .. sonst Piepser aktivieren rjmp SOUG11 SOUG10: cbi DDRB,3 SOUG11: sbi DDRC,4 ; 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 Bereich 0..127 CONVUM: lds R17,UMESSP ; Spitzenwert Messspannung in R17 bilden lds R16,UMESSP+1 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 ; ret ; ; ; **** Regelspannung messen und in Dämpfung/Entfernung umrechnen ; ADDIST: ldi R16,1 ; Analog-Channel 0 = URegel ldi R19,$FF ; Scaling Factor clr R18 ; .. dto., Low Byte rcall ANACON ; A/D-Wandeln, Ergebnis-Bereich 0..255 ; ; ** Zugehörige Pegelstufe aus Tabelle lesen ; mov R17,R16 ; Analogwert um 2 verringern, aber nicht unter 0 tst R17 breq DISB31 dec R17 breq DISB31 dec R17 DISB31: ldi XH,0 ; Pointer auf Tabelle ldi XL,LEVTAB clr R16 ; Pegelwert 0..21 (5 dB-Stufen) ; DISB32: ld R18,X+ ; Wert aus Tabelle holen cp R17,R18 ; Anzeigewert grösser Tabellenwert? brcs DISB33 ; .. dann nächsten Eintrag inc R16 ; Pegelwert erhöhen cpi R16,21 ; .. bis max 21 breq DISB33 ld R19,X ; 5 dB-Zwischenwert berechnen add R18,R19 lsr R18 cp R17,R18 ; Anzeigewert grösser Zwischenwert? brcs DISB33 ; .. dann nächsten Eintrag inc R16 ; Pegelwert erhöhen rjmp DISB32 ; ; DISB33: sts ABSBIN,R16 ; ; ** Abschwächercode in dB wandeln ; 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 dB-Anzeige ldi XL,ABSCHW rcall B3BCD ; ; ** Abschwächercode in Entfernung wandeln ; lds R16,ABSBIN ; Abschwächer Code holen lds R17,PFOXBN ; Korrekturfaktor Sendeleistung dazu sub R16,R17 lds R17,DISTCF ; Korrekturfaktor aus Abgleichmenü dazu add R16,R17 ldi R17,8 ; Basis-Offset dazu add R16,R17 ; ; DIS3: 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 CUR40 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: ldi R16,-1 ; CUR40: sbrc R16,7 ; Wenn Code Negativ ist rjmp CUR499 ; .. dB anzeigen ; cpi R16,0 ; 5 km brne CUR41 ldi R17,5 ldi R18,'k' ldi R19,'m' CUR41: cpi R16,1 ; 4 km brne CUR42 ldi R17,4 ldi R18,'k' ldi R19,'m' CUR42: cpi R16,2 ; 3 km brne CUR43 ldi R17,3 ldi R18,'k' ldi R19,'m' CUR43: cpi R16,3 ; 2 km brne CUR44 ldi R17,2 ldi R18,'k' ldi R19,'m' 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 ; < 5 m brcs CUR499 ldi R17,'<' ldi R18,5 ldi R19,'m' ; CUR499: sts DIST+0,R17 ; Entfernungsanzeige bereitstellen sts DIST+1,R18 sts DIST+2,R19 ; DIS9: ret ; ; ################### ; #### EEPROM Handling ############################################# ; ################### ; ; ++++ Geänderte Parameter von EEPCLR bis EEP2-1 ; ins EEPROM speichern ; SAVCHG: LDI YL,LOW(EEPCLR) ; Pointer auf Variablen CLR YH LDI R20,EEPCLR-EEPCLR ; 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-EEPCLR ; Gesamter Bereich geschrieben? BRNE SAVCH1 RET ; ; ++++ Abgleichwerte von EEP2 bis EEPEND-1 ; ins EEPROM speichern ; SAVCAL: LDI YL,LOW(EEP2) ; Pointer auf Variablen CLR YH LDI R20,EEP2-EEPCLR ; 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-EEPCLR ; Gesamter Bereich geschrieben? BRNE SAVCA1 RET ; ; ++++ Alle Parameter aus EEPROM holen +++++++++++++++++++++++++++++++ ; GETEEP: LDI YL,Low(EEPCLR) ; 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-EEPCLR ; 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 Data String LCDST1: LPM ; Get one Byte to R0 ADIW ZL,1 ; Increment Z ST Y+,R0 ; Store Byte CPI YL,LOW(LCDDAT)+16 ; Repeat 16 times BRNE LCDST1 ; 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: 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 R16 push R25 push YL push YH ; 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 YH pop YL pop R25 pop R16 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 nop nop sbi PORTC,5 ; Toggle Enable Bit nop nop nop nop nop nop nop cbi PORTC,5 ; ldi R25,213 ; Wait 40 usec = 640 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,21 D1MS: INC R16 ; 3 cycle inner loop BRNE D1MS ; " " " " DEC R17 BRNE D1MS DEC R25 BRNE DXMS POP R25 POP R17 POP R16 RET ; ; ++++ Delay x secs, X in R25 DELXS: PUSH R16 PUSH R25 MOV R16,R25 LDI R25,250 ; 250 ms Basis Delay ; DXS: RCALL DELXMS RCALL DELXMS RCALL DELXMS RCALL DELXMS DEC R16 BRNE DXS ; POP R25 POP R16 RET ; ; ********************************** ; ******* 1 msec 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 R22 PUSH R23 ; Get some work registers PUSH R24 PUSH XL PUSH XH IN R24,SREG ; Save Statusreg PUSH R24 ; ; ++ 1 ms Service ; TIM500: ldi R22,256-160 ; Set Counter to Startvalue (Divide by 64*160) out TCNT0,R22 ; sei ; Enable next interrupt rcall TUNE ; Tune VCO to target Frequency rcall DEBNCE ; Debounce Drehgeber ; TIM501: sei inctim TIK1M,20,TIM599 ; Increment to 20 msec rjmp 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 ; lds R24,FOX ; Aktuelle Fuchs Nr. lds R23,NFOX ; Zahl der Füchse cp R23,R24 ; Wenn derzeitiger Fuchs <> Maxwert 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 'in 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 R16 RETI ; Interrupt-Handling beendet ; ; ; ++++ Tune VCO to Target Frequency ; ; Zaehlt für jeweils 50 msec die VCO Frequenz und erzeugt ; einen der Abweichung proportionalen Abstimmimpuls ; This Subroutine is called by the interrupt handler once per ms ; TUNE: PUSH R22 PUSH R23 ; Get some work registers PUSH R24 PUSH R25 ; lds R24,TIK150 ; Increment 1 msec Timer to 50 ms inc R24 sts TIK150,R24 cpi R24,50 ; up to 50 breq TUN50M lds R23,TUNLEN ; Wenn Zeit = Tuning Puls Länge cp R23,R24 brne TUN500 cbi DDRB,2 ; .. Tuning-Ausgang auf High Z cbi PORTB,2 TUN500: rjmp TUN599 ; ; ++ 50 ms Service TUN50M: clr R24 sts TIK150,R24 ; clr R24 in R22,TCNT1L ; Frequenzzähler auslesen in R23,TCNT1H ; out TCNT1H,R24 ; .. und wieder auf 0 setzen out TCNT1L,R24 sts FISTH,R23 ; Ist-Frequenz ablegen für Diagnose sts FISTL,R22 ; TUN501: lds R24,FSOLLL ; Sollfrequenz holen lds R25,FSOLLH sub R24,R22 ; Soll - Ist berechnen sbc R25,R23 ; mov R23,R25 ; Vorzeichen der Differenz abtrennen andi R23,$80 ; .. und in R23 halten breq TUN502 ; Wenn Negativ: com R24 ; .. 2er Komplement bilden com R25 adiw R24,1 TUN502: cpi R25,11 ; Auf 12*256 begrenzen brcs TUN503 ldi R25,11 ldi R24,$FF TUN503: clc ; 2 Stellen links rotieren rol R24 ; Ergibt 0..47 in MSB rol R25 rol R24 rol R25 ror R24 ; .. und 0..63 in LSB ror R24 tst R25 ; Wenn MSB <> 0 breq TUN504 clr R24 ; Dann LSB auf 0 ; TUN504: sts TUNLEN,R25 ; Puls-Länge in ms ablegen tst R24 ; Wenn Abweichung <> 0 brne TUN505 tst R25 brne TUN505 rjmp TUN599 ; TUN505: sbrc R23,7 ; Wenn Vorzeichen - cbi PORTB,2 ; .. Regelausgang auf 0 sbrs R23,7 ; Sonst sbi PORTB,2 ; .. auf 1 sbi DDRB,2 ; Ausgang enabeln ; tst R24 ; Wenn LSB <> 0 => Kurzpuls < 1 msec breq TUN599 ; TUN506: ldi R25,40 ; Inner Loop ist 3 cyc * 40 = 15 usec TUN507: dec R25 brne TUN507 ; Sie wird 1..63 * durchlaufen dec R24 brne TUN506 ; cbi DDRB,2 ; Tuning-Ausgang wieder auf High Z cbi PORTB,2 ; TUN599: POP R25 POP R24 POP R23 POP R22 ret ; ; ; ++++ 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 ; $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 PINB,0 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,1 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,1 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 ; ; ************************* ; **** Initialisation Tables ********************************************** ; ************************* ; ; ++++ 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 $02,$05,$00,$00,$00,$05,$02,$00 ; 1: Up + Down Arrow .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 Variablenposition = Komprimiertes dB Zeichen ; 1 " = Pfeile Up + Down ; 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 ; ; >12345678< Power On STRPO: .DB " FJRX82 " .DB " V. ",VERSHI,".",VERSLO," " .DW 0 ; ; >12345678< RX Off STR000: .DB " RX Aus " .DB "F:. :.s" .DB 1,2,3,4,5,6,7,8 .DB 1,FOX,0,4,5,TIMER,0,8 ; ; >12345678< RX Off STR001: .DB " RX Aus " .DB ".:..:.. " .DB 1,2,3,4,5,6,7,8 .DB STOPW,2,0,0,5,0,0,8 ; ; >12345678< Frequenz ändern + S-Meter anzeigen STR02: .DB "3...:. ",1 .DB " " .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,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,5,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,5,DIST,0,0 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Stopuhr stoppen STR040: .DB "Uhr 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: .DB "UhrStart" .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: .DB "Einstell" .DB $7E," -men",$F5 .DW 0 ; ; >12345678< Frequenz ändern anbieten STR07: .DB "3...:. " .DB $7E," ",$E1,"ndern" .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB 1,2,3,4,5,6,7,8 ; ; >12345678< Zahl Füchse einstellen STR10: .DB "N F",$F5,"chse" .DB " :. ",1," " .DB 1,2,3,4,5,6,7,8 .DB 1,2,NFOX,0,5,6,7,8 ; ; >12345678< Zeit Füchse Sekunden einstellen STR11: .DB "T Fuchs",1 .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 STR12: .DB "T Fuchs",1 .DB ":.,>..12345678< Sendeleistung Füchse einstellen STR13: .DB "P Fu :.." .DB ":.,. .W",1 .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' STR130: .DB "P Fuchs " .DB "nur dB ",1 .DW 0 ; ; >12345678< Zahl Frequenzen einstellen STR14: .DB "N Frequ " .DB " : ",1," " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,NFREQ,5,6,7,8 ; ; >12345678< EOT Alarmzeit einstellen STR15: .DB "T Alarm " .DB "- :.s ",1," " .DB 1,2,3,4,5,6,7,8 .DB 1,2,TALARM,0,5,6,7,8 ; ; >12345678< STR20: .DB "Abgleich" .DB "Aus=Raus" .DW 0 ; ; >12345678< STR21: .DB " EEPROM " .DB $7E," Reset " .DW 0 ; ; >12345678< UBat kalibrieren STR22: .DB "Abg UBat" .DB "...:.,.V" .DB 1,2,3,4,5,6,7,8 .DB UBFVAL,0,0,UBATT,0,6,0,8 ; ; >12345678< Frequenz kalibrieren STR23: .DB "AbgF ..." .DB " " .DB 1,2,3,4,5,FFIVAL,0,0 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Abschwächer kalibrieren STR24: .DB "Abg Absw" .DB $7E," Start " .DW 0 ; ; >12345678< Abschwächerwerte lesen STR25: .DB "LeseAbsw" .DB ":.0",0," :.." .DB 1,2,3,4,5,6,7,8 .DB LEVRDZ,0,3,4,5,LEVDZ,0,0 .DW 0 ; ; >12345678< Batterie-Warnschwelle einstellen STR26: .DB "BatWarng" .DB "< .,. V",1 .DB 1,2,3,4,5,6,7,8 .DB 1,2,UBWARN,4,0,6,7,8 ; ; >12345678< Entfernung kalibrieren STR27: .DB "AbgDis.." .DB "..:..:.." .DB 1,2,3,4,5,6,DCFVAL,0 .DB UMESS+2,0,3,0,0,DIST,0,0 ; ; >12345678< Frequenzbereich STR280: .DB "FBereich" .DB "3,5-3,65" .DW 0 ; ; >12345678< STR281: .DB "FBereich" .DB "3,5-3,8 " .DW 0 ; ; >12345678< Feinabstimmung Modus Peilen STR290: .DB "Feinabst" .DB "Peil Aus" .DW 0 ; ; >12345678< STR291: .DB "Feinabst" .DB "Peil Ein" .DW 0 ; ; >12345678< STR2A: .DB "Abgleich" .DB $7E,"Sichern" .DW 0 ; ; >12345678< Level (Distanz) kalibrieren STRLEV: .DB ":.0",0," :.." .DB " " .DB DIST+1,0,3,4,5,LEVDZ,0,0 .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< Batteriespannung niedrig STRBAT: .DB "Batterie" .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 "3...:. " .DB ".:..:.,." .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB STOPW,1,0,0,UBATT,0,7,0 ; ; >12345678< Kanal geändert STRFRQ: .DB "3...:. " .DB " - . -" .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB 1,2,3,4,5,FRQX,7,8 ; ; >12345678< Sendezeit-Ende Alarm STRALA: .DB " Noch " .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 62,5 kHz / Wert: ; 31 = 2 kHz, 62 = 1 kHz, 255 = 250 Hz ; Sonderfälle: 1 = kein Ton, 0 = End of String ; SOUPO: .DB 1,1,60,1,48,48,1,60 ; Power-On-Fanfare .DB 1,78,78,78,1,1,1,1,1,0 ; SOUHI: .DB 1,62,1,62,1,62,1,62,1,1 .DB 1,62,1,62,1,0 SOUALA: .DB 18,27,37,55,75,110,150,0 ; 'Ende - x sec'-Alarm ; SOUBAT: .DB 1,48,66,90,120,150,48,66 ; Low Battery Alarm .DB 90,120,150,48,66,90,120,150 .DB 1,0 ; SOUF1: .DB 1,150,110,75,55,33,1,1,60,1,1,0 ; Frequenz 1 SOUF2: .DB 1,150,110,75,55,33,1,1,60,1,60,1,1,0 ; F 2 SOUF3: .DB 1,150,110,75,55,33,1,1,60,1,60,1,60,1,1,0 ; F 3 SOUF4: .DB 1,150,110,75,55,33,1,1,60,1,60,1,60,1,60,1,1,0 ; F 4 ; SOUOK: .DB 1,1,96,1,96,96,96,1,96,1,1,0 ; Ok ; SOUPIP: .DB 96,1,0,0 ; Piep ; ; ; ************************ ;******** This is the End..... *************************************** ; ************************