; FJRX4.ASM ; ; ************************** ; * 2m Fuchsjagd Empfänger * ; ************************** ; ; Code für Fuchsjagd-Empfänger-Steuerung ; ; Unterstützt den 2m-Fuchsjagdempfänger Version 4 (SMD) auf Platine 'fjrx240.brd' ; ; Autor: Nick Roethe, DF1FO, DF1FO at darc.de ; ; 1. 7.04 -.-: Projektstart 2m Peilempfänger mit FJRX Version 0.0 ; 14. 1.10 0.0: FJRX2 Version 4.7 ist Startpunkt für FJRX4 0.0 ; Von ATmega 8 auf ATmega168 umgestellt ; Ansteuerung für ADF 4110 PLL eingebaut, Einstell-Raster 1 kHz ; (Geändert UDFRQ, CONVF, SETPLL, INIPLL, PLL-Treiber) ; 'RX Aus' wird nicht mehr unterstützt ; Diese Version läuft im Versuchsaufbau mit dem ATMega PDIP28 ; 5. 2.10 0.1: Umgestellt auf neue SMD-Platine mit ATMega TQFP32 ; 27. 2.10 0.2: Vorstufenverstärkung in 3 statt 2 Schritten ; 100ms-Event auf 60ms verkürzt (Abschwächer, Sounds schneller) ; Abschwächer-Eichwerte in 5dB-Schritten ablegen (statt 10 dB) ; 12. 3.10 0.3: Flash-Zeiten an 60ms angepasst ; 16. 3.10 0.4: Einstellung PLL-Mux im Abgleichmenü ; 29. 3.10 0.6: Pseudo-km statt dB-Anzeige bei kleiner Abschwächung ; Dämpfungsannahme 30db/10x unter 3 km, darüber +1km/5dB ; Sound SOUOK 100 Bpm statt 50 ; Nach manueller Abschwächer-Verstellung Automatik 120ms unterdrücken ; 11. 5.10 0.7: Fix für 'dB-Anzeige bei AbglAbsw geht nicht mehr' ; 31. 5.10 0.8: Akust. S-Meter hat keine Nachlaufzeit mehr (Testversion) ; 18. 6.10 0.9: EEPROM-Initialisierungs-Werte jetzt Mittelwert Platinen 101+102 ; Akust. S-Meter Nachlaufzeit endgültig ausgebaut ; 31.10.10 1.0: Volle Abschwächung Vorstufe erst ab 65 dB (statt 60) ; 19. 3.11 1.1: Reserve-Pin X bekommt Pull-Up, Batterie-Alarm zeigt Ist-Spannung, ; Abschalt-Automatik für Empfänger mit Einschalt-Selbsthaltung ; .equ VERSHI= '1' .equ VERSLO= '1' ; .equ VALKEY= $A9 ; EEPROM Valid Key auf Adresse EEPCLR ; ; >> AVR-STUDIO << : Ich benutze AVR Studio 4 ; ================ und Assembler Version 2 ; Einstellungen in AVR Studio 4: ; -> Project -> Assembler Options: Assembler Version 2 ; -> Tools -> Options -> Editor -> Tabwidth=8 ; ; >> FUSES << : Im AVR-Programmer: ; =========== - Häkchen nur an SPIEN und EESAVE ; - (Also kein Häkchen bei CKDIV8!) ; - Brown Out Detection auf 4,3 Volt ; - SUT_CKSEL 'Ext. Crystal Osc. 3.0-8.0 MHz', unterste Auswahl ; - BOOTSZ unterste Auswahl (eigentlich egal) ; Richtiges Hex-Pattern X-H-L $F9-D4-FD ; Beim Auslesen kommt L-H-X $FD-D4-F9 zurück ; .device ATmega168 .listmac ; Macro Expansion Listing On ; ; **** I/O Register Definitions ; ; Memory Mapped I/O Register Definitions (&FF-$60), use LDS/STS .equ UDR0 =$C6 .equ UBRR0H =$C5 .equ UBRR0L =$C4 .equ UCSR0C =$C2 .equ UCSR0B =$C1 .equ UCSR0A =$C0 .equ TWAMR =$BD .equ TWCR =$BC .equ TWDR =$BB .equ TWAR =$BA .equ TWSR =$B9 .equ TWBR =$B8 .equ ASSR =$B6 .equ OCR2B =$B4 .equ OCR2A =$B3 .equ TCNT2 =$B2 .equ TCCR2B =$B1 .equ TCCR2A =$B0 .equ OCR1BH =$8B .equ OCR1BL =$8A .equ OCR1AH =$89 .equ OCR1AL =$88 .equ ICR1H =$87 .equ ICR1L =$86 .equ TCNT1H =$85 .equ TCNT1L =$84 .equ TCCR1C =$82 .equ TCCR1B =$81 .equ TCCR1A =$80 .equ DIDR1 =$7F .equ DIDR0 =$7E .equ ADMUX =$7C .equ ADCSRB =$7B .equ ADCSRA =$7A .equ ADCH =$79 .equ ADCL =$78 .equ TIMSK2 =$70 .equ TIMSK1 =$6F .equ TIMSK0 =$6E .equ PCMSK2 =$6D .equ PCMSK1 =$6C .equ PCMSK0 =$6B .equ EICRA =$69 .equ PCICR =$68 .equ OSCCAL =$66 .equ PRR =$64 .equ CLKPR =$61 .equ WDTCSR =$60 ; I/O Register Definitions ($3F-$00), use IN/OUT/SBI/CBI/SBIS/SBIC .equ SREG =$3F .equ SPH =$3E .equ SPL =$3D .equ SPMCSR =$37 .equ MCUCR =$35 .equ MCUSR =$34 .equ SMCR =$33 .equ MONDR =$31 .equ ACSR =$30 .equ SPDR =$2E .equ SPSR =$2D .equ SPCR =$2c .equ GPIOR2 =$2B .equ GPIOR1 =$2A .equ OCR0B =$28 .equ OCR0A =$27 .equ TCNT0 =$26 .equ TCCR0B =$25 .equ TCCR0A =$24 .equ GTCCR =$23 .equ EEARH =$22 .equ EEARL =$21 .equ EEDR =$20 .equ EECR =$1F .equ GPIOR0 =$1E .equ EIMSK =$1D .equ EIFR =$1C .equ PCIFR =$1B .equ TIFR2 =$17 .equ TIFR1 =$16 .equ TIFR0 =$15 .equ PORTD =$0B .equ DDRD =$0A .equ PIND =$09 .equ PORTC =$08 .equ DDRC =$07 .equ PINC =$06 .equ PORTB =$05 .equ DDRB =$04 .equ PINB =$03 ; ; **** 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 = $100 ; First SRAM Location .equ RAMEND = $4FF .equ XRAMEND = $4FF .equ E2END = $1FF .equ FLASHEND = $1FFF ; ; **** Variablen *************************************************** .DSEG .ORG RAMBEG ; Start of RAM address range ($0100) ; VOID: .BYTE 16 ; Unused RAM Area (because of LCDSTR-Limitation) ; ; ++ Eingestellte Parameter, werden im EEPROM gerettet EEPBEG: FRQ1: .BYTE 2 ; Frequenz-Codewort Frequenz 1 ; 0..4200 = 143,9..148,1 bzw. 148,9.., 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 TBD1: .BYTE 1 ; Platzhalter, nicht benutzt TBD2: .BYTE 1 ; Platzhalter, nicht benutzt ; EEP2: ; Grenze zwischen HW-SetUp und Abgleich-Bereich ABSTAB: .BYTE 25 ; Tabelle Abschwächer-Codes 0,5,10,15..120 dB FFINE: .BYTE 1 ; Frequenz Fein 64 -/+ 25 = -25..+25 * 1,25 kHz UBFINE: .BYTE 1 ; Skalierungswert für Ub-Messung 0..255 FBER: .BYTE 1 ; Frequenzbereich 0:144..146, 1:144..148 2:149..153 UBWBIN: .BYTE 1 ; Schwelle Batteriewarnung in 1/10 V (60..80) SPRACH: .BYTE 1 ; Sprachwahl 1=Deutsch, 2=English, 3=Nederlands DISTCF: .BYTE 1 ; Korrekturfaktor Entfernung -5..+5 = -/+25dB AOTIM: .BYTE 1 ; Auto-Off-Zeit, 0 = Aus, 1..7 = 10-70' TBD4: .BYTE 1 ; Platzhalter, nicht benutzt EEPCLR: .BYTE 1 ; $FF wenn EEPROM gelöscht, VALKEY 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..4200 = 143,9.. bzw 149,9.., 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 ACSOVE: .BYTE 1 ; 1 = S-Meter-Wert über ACSM-Schwelle FRQ: .BYTE 5 ; Frequenz-Dezimalstellen 10M,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 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 * 60 ms) FLATIM: .BYTE 1 ; Verbleibende Flashtime für Text-Flash (n * 60 ms) FUDARM: .BYTE 1 ; Scharf-Zeit für Frq+/- mit <<*>> Mode Peilen (* 60 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 PLLMUX: .BYTE 1 ; PLL-Mux-Einstellwert 0..7, Anfangswert = 1 = Lock Detect AOWAIT: .BYTE 1 ; Auto-Off-Timer, zählt ab letzter Bedienung Minuten bis 10*AOTIM AOCYC: .BYTE 1 ; Auto-Off Cycle, steuert Erzeugung des Abschaltpulses an PB4 ; ++ 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 ; 60 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 TIK4U: .BYTE 1 ; Zaehlt alle 400 us bis 50 (20 msec) TIK20M: .BYTE 1 ; Zaehlt jede 20 msec bis 50 (1 sec) TIK60: .BYTE 1 ; Zaehlt jede 20msec bis 3 (60 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) call LCDSTR ; .. ausführen .ENDMACRO ; ; ++++ Flash Text String @0 for @1*60ms .MACRO FLASH ldi ZL,low(2*@0) ; Ausgabe-Kommand-String ldi ZH,high(2*@0) call 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 call BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 ldi XL,@1 ; Lower Limit ldi XH,@2 ; Upper Limit call INCLIM ; Increment R16 within limits in XH,XL ldi XL,LOW(@0) ; Pointer auf BCD-String ldi XH,1 call 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 call BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 ldi XL,@1 ; Lower Limit ldi XH,@2 ; Upper Limit call DECLIM ; Decrement R16 within limits in XH,XL ldi XL,LOW(@0) ; Pointer auf BCD-String ldi XH,1 call 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 JMP START ; 1 Reset JMP START ; 2 INT0 JMP START ; 3 INT1 JMP START ; 4 PCINT0 JMP START ; 5 PCINT1 JMP START ; 6 PCINT2 JMP START ; 7 WDT JMP START ; 8 TIM2 COMPA JMP START ; 9 TIM2 COMPB JMP START ; 10 TIM2 OVF JMP START ; 11 TIM1 CAPT JMP START ; 12 TIM1 COMPA JMP START ; 13 TIM1 COMPB JMP START ; 14 TIM1 OVF JMP START ; 15 TIM0 COMPA JMP START ; 16 TIM0 COMPB JMP TIMINT ; 17 Timer 0 Overflow JMP START ; 18 SPI, STC JMP START ; 19 USART RX JMP START ; 20 USART UDRE JMP START ; 21 USART TX JMP START ; 22 ADC JMP START ; 23 EE READY JMP START ; 24 ANALOG COMP JMP START ; 25 TWI JMP START ; 26 SPM READY ; ; ; ***************************** ; **** 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 ; ldi XH,HIGH(RAMBEG) 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 ; 5 available for future additions ldi R16,$2E out DDRB,R16 ldi R16,$11 out PORTB,R16 ; ; ++++ Initialize Port C Bit 0 as Output Vorstufe Ein/Aus ; 1 as Output PLL Data ; 2 as Input X (Reserve, Pull-Up) ; 3 as Input P0 with Pull-Up ; 4 as Output PLL Clock ; 5 as Output PLL Latch Enable ; 6 as Analog Input UbMess ; 7 as Analog Input S-Meter ldi R16,$33 out DDRC,R16 ldi R16,$0C 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,$07 ; Select Analog Input 7 STS ADMUX,R16 LDI R16,$86 ; Enable ADC, Clock Divider 64 = 78 kHz STS ADCSRA,R16 ; = 180 usec Conversion Time ; ; ++++ Intialize Timer/Counter 0 as 400 us Interrupt (5,12MHz/8/256) ldi R16,$02 ; Set Clock Divider to 8 out TCCR0B,R16 ldi R16,$01 sts TIMSK0,R16 ; Enable Counter 0 Overflow Interrupt ; ; ++++ 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 sts TCCR1A,R16 ldi R16,$09 sts TCCR1B,R16 ldi R16,$0A ; Komparator fuer Counter Reset & Output Toggle sts OCR1AH,R16 ldi R16,0 ; $0A00 = 1 kHz Startwert sts OCR1AL,R16 ; ; ++++ Intialize Timer/Counter 2 as fast PWM (20 kHz) for Uabschw stsi TCCR2A,$83 ; Clock Divider 1, fast PWM, OC2 active stsi TCCR2B,$01 ; ; ++++ Get Steuer-Parameter from EEPROM call GETEEP ; Parameter aus EEPROM holen ; STA02: lds R16,EEPCLR ; Hat EEPROM gültigen Inhalt? cpi R16,VALKEY breq STA021 ; .. sonst Parameter initialisieren call EEPNEW ; STA021: lds R16,LOCKED ; LOCKED darf nur $81 oder $20 sein cpi R16,$81 ; (steht nach Software Upgrade evtl auf anderem Wert) breq STA022 stsi LOCKED,$20 STA022: lds R16,AOTIM ; AOTIM darf nur 0..7 sein andi R16,$F8 breq STA03 stsi AOTIM,0 ; ; ++++ Initialize some Variables STA03: 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,166 ; Erste Batteriespannungsprüfung nach 10s stsi FRQ512,1 ; Vorige Frequenz-Nr für 12<>3, Rückkehr 3 -> 1 stsi PLLMUX,1 ; PLL Multiplexer auf 'Lock Bit' ; sbic PINB,4 ; Wenn Drücker gedrückt rjmp STA031 ; stsi MODE,$20 ; .. dann Abgleichmode ; STA031: call GETFRQ ; Aktuelle Frequenz laden call CONVF ; Frequenz Dezimal ausrechnen call CONVPF ; Leistung Dezimal ausrechnen call CONVBW ; Batterie-Warnung Dezimal ausrechnen call INIPLL ; PLL Initialisieren ; ; ++++ Start Interrupt Handler call CLRTIM ; Fuchstimer auf Startwert sei ; Global Interrupt enable ; ldi R25,100 ; Wait 100 ms call DELXMS ; ; ++++ Initialize LCD and show Start Text call INILCD flash STRPO,15 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 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,45 ; Start Menu Message ; M29: sts MODE,R16 ; Mode speichern ; ; ++++ Switch-Flags holen 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 MAIN30 stsi AOWAIT,0 ; .. Auto Off Timer auf 0 MAIN30: 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,15 rjmp M309 M3X1: sound SOUAA1 flash STRAA1,15 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,13 ; Wenn > 60 dB brcs M301 stsi ABSBIN,12 ; .. dann auf 60 dB rjmp M302 M301: cpi R16,5 ; Wenn > 20dB brcs M3011 stsi ABSBIN,4 ; .. dann auf 20 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 call CONVAB ; .. neuen Abschwächerwert einstellen pop R17 stsi AAWAIT,2 ; Abschwächerautomatik für 120 ms unterdrücken M309: andi R17,$9F ; Flag Bits 5, 6 löschen ; ; ++++ Auto Off Timer handeln lds R18,AOTIM ; Zeitlimit mit Istwert vergleichen tst R18 ; Bei Limit = 0 breq M30A ; .. nix machen lsl R18 ; Zeitlimit mit 10 malnehmen mov R19,R18 ; ..(weil 1..7 für 10-70' steht) lsl R19 lsl R19 add R18,R19 ; lds R19,AOWAIT cp R18,R19 brne M30A stsi AOWAIT,0 ; Wenn Limit erreicht, Istwert auf 0 stsi AOCYC,18 ; .. und Abschaltversuch starten ; ; ++++ Je nach Mode: Drehdrücker handeln M30A: lds R16,MODE cpi R16,3 ; Bei Mode 3 brne M30 call UDABS ; Abschwächer ändern, ACSM an/aus, Kanal rjmp M399 ; fertig ; M30: cpi R16,2 ; Bei Mode 2 brne M31 call 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..$2A 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,$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 call CLRSTW ; .... dann Stopuhr löschen und starten ; M35: cpi R16,5 ; Wenn Mode = 5 brne M36 call 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 call EEPNEW ; .... dann EEPROM initialisieren call SAVCAL ; flash STRSAV,15 ; .... 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/ 150 weiterschalten lds R18,FBER inc R18 cpi R18,3 brne M3251 clr R18 M3251: sts FBER,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 M329 sbrs R17,4 ; .. und Drehdrücker Click rjmp M399 call SAVCAL ; .... Abgleich-Parameter in EEPROM retten flash STRSAV,15 ; .... Anzeige Save to EEPROM sound SOUOK ; .... und Quittungston rjmp M399 ; M329: cpi R16,$29 ; Wenn Mode = 29 brne M32A rcall UDPLL ; .. PLL Multiplexer einstellen rjmp M399 ; M32A: cpi R16,$2A ; Wenn Mode = 2A brne M399 rcall UDAOT ; .. Auto Off Time einstellen rjmp M399 ; ; M399: ; call ADUM ; Messspannung A/D-Wandeln und behandeln ; ; ++++ Alles weitere nur alle 60 ms: ++++++++++++++ MAIN5: lds R16,TICK ; 60 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 60 ms 1,5 kHz und 2,5 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: call 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 Alarmtime-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,12 ; .. und Meldung zeigen ; ; ++++ Batterie checken ; Interrupthandler setzt Timer BATTIM bei Sendestart F1 auf 166 ; Timer wird hier alle 60 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,80 ; Sonst Alarm-Text und -Sound sound SOUBAT ; MAINB6: lds R16,FUDARM ; Wenn FUDARM Flag > 0 dec R16 ; .. jede 60 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 ldi ZH,1 ; .... dann Pointer auf FRQ1X2-Entry bauen lds ZL,FOX+1 ldi R16,LOW(FRQ1X2) add ZL,R16 ld R16,Z ; .... und Entry lesen cp R16,R17 ; .... Wenn aktuelle Frequenz ungleich Soll breq MAINC9 call THISF ; ...... Soll-Frequenz laden MAINC9: ; ++++ Batteriespannung A/D-konvertieren und skalieren MAIN6: ldi R16,6 ; Analog-Channel 6 = 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 call ANACON ldi XH,1 ; Pointer auf Anzeige-Fenster ldi XL,LOW(UBATT) call B3BCD ; Ergebnis in BCD wandeln und ablegen ; call CONVAB ; Abschwächer-Einstellung in Entfernung umrechnen ; call CONVUM ; Messspannung in Bargraph-Anzeige wandeln ; ; ++++ Abschaltimpuls für Auto Off erzeugen MAIN65: lds R16,AOCYC ; Wenn Cycle-Counter > 0 tst R16 breq MAIN69 dec R16 ; .. runterzählen sts AOCYC,R16 cpi R16,17 ; Bei Zählerstand 17 brne MAIN66 sbi DDRB,4 ; .. PIN PB4 aktiv auf Low ziehen cbi PORTB,4 MAIN66: cpi R16,1 ; Bei Zählerstand 1 brne MAIN69 cbi DDRB,4 ; .. PIN PB4 wieder Input mit Pull-Up sbi PORTB,4 MAIN69: ; ; ++++ 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 ; Stopuhr Restart brne M75 show STR04 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,FBER ; Gewählten Abstimmbereich zeigen cpi R18,0 brne M7251 show STR250 rjmp M799 M7251: cpi R18,1 brne M7252 show STR251 rjmp M799 M7252: show STR252 rjmp M799 M726: cpi R16,$26 brne M727 show STR26 M727: cpi R16,$27 brne M728 show STR27 M728: cpi R16,$28 brne M729 show STR28 M729: cpi R16,$29 brne M72A show STR29 M72A: cpi R16,$2A brne M799 show STR2A M799: ; ++++ Falls Frequenz geändert: Synthesizer laden MAIN8: lds R16,FRQCHG ; Change Frequency Flag gesetzt? tst R16 breq MAIN89 call SETPLL ; Ja, Frequenz in PLL laden stsi FRQCHG,0 ; .. und Flag löschen rjmp MAIN89 ; MAIN89: call 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 call SAVCHG ; .. und geänderte Parameter retten ; MAIN99: rjmp MAIN ; ; *************** ; **** Subroutines ************************************************* ; *************** ; ; ################################# ; #### Variablen ändern und anzeigen ############################### ; ################################# ; ; **** Stopuhr löschen und starten CLRSTW: cli sts STOPW,C0 ; Zeit auf 0 setzen sts STOPW+1,C0 sts STOPW+2,C0 sts STOPW+3,C0 sts STOPW+4,C0 sei 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,LOW(NFOX) ; Pointer auf NFox-BCD-String ldi XH,1 call BCD2B ; Wandelt 2B BCD @ X,X+1 nach Bin in R16 mov R18,R16 ldi XL,LOW(FOX) ; Pointer auf Fox-BCD-String ldi XH,1 cli ; Interrupt aus call 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 call INCLIM ; Increment R16 within limits in XH,XL sbrs R17,2 ; Down-Flag call DECLIM ; Decrement R16 within limits in XH,XL ldi XL,LOW(FOX) ; Pointer auf BCD-String ldi XH,1 call 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: call 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 call GETFRQ ; Neue Frequenz holen call 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: call 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: call 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 call 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 ; ; **** PLL-Mux einstellen 0..7 UDPLL: andi R17,$0C ; Up oder Down Flag gesetzt? breq UDPLL9 lds R16,PLLMUX ; Get current value sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 andi R16,$07 ; Limit to 0..7 sts PLLMUX,R16 ; Geänderten Wert speichern rcall INIPLL ; Neuen Mux-Wert in PLL laden UDPLL9: ret ; ; **** Auto-Off-Time einstellen 0..7 UDAOT: andi R17,$0C ; Up oder Down Flag gesetzt? breq UDAOT9 lds R16,AOTIM ; Get current value sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 andi R16,$07 ; Limit to 0..7 sts AOTIM,R16 ; Geänderten Wert speichern UDAOT9: ret ; ; **** Abschwächer-Einstellung, Frequenz-Nr. +/-, ACSM Ein/Aus ; Schalter-Flags in R17 UDABS: mov R16,R17 ; Nur wenn Up oder Down gesetzt andi R16,3 breq UDABS2 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 UDAB20 ldi R16,0 UDAB20: cpi R16,25 brne UDAB21 ldi R16,24 UDAB21: sts ABSBIN,R16 stsi AAWAIT,2 ; Abschwächerautomatik unterdrücken für 120 ms ; UDABS2: 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 ldi ZH,1 ; Pointer auf FRQ1X2-Entry bauen lds ZL,FOX+1 ldi R16,LOW(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 sound SOUPIP ; .. Quittungston ; 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,10 sbrc R17,1 sbiw R24,10 sbrc R17,2 ; +/- 1 kHz adiw R24,1 sbrc R17,3 sbiw R24,1 ; tst R25 ; Wenn Ergebnis negativ brpl UDFRQ2 clr R24 ; .. auf 0 setzen clr R25 rjmp UDFRQ8 ; UDFRQ2: lds R17,FBER ; Max.-Frq. 146 oder 148/153? cpi R17,0 brne UDFRQ4 ; cpi R25,$09 ; Für 146: Wenn Ergebnis > 2200 = $0898 brcc UDFRQ3 cpi R25,$08 brne UDFRQ8 cpi R24,$99 brcs UDFRQ8 UDFRQ3: ldi R24,$98 ldi R25,$08 rjmp UDFRQ8 ; UDFRQ4: cpi R25,$11 ; Für 148/153: Wenn Ergebnis > 4200 = $1068 brcc UDFRQ5 cpi R25,$10 brne UDFRQ8 cpi R24,$69 brcs UDFRQ8 UDFRQ5: ldi R24,$68 ldi R25,$10 rjmp UDFRQ8 ; 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,30 ; 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) ldi YH,1 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) ldi YH,1 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 -> 5B FRQ **** CONVF: lds R24,FRQBIN ; Binäres Frequenzcodewort holen lds R25,FRQBIN+1 ; ldi R16,4 ; 10 MHz Startwert ldi R17,3 ; 1 MHz Startwert für die 143,9 MHz-Frequenzbereiche lds R20,FBER ; Frequenzbereich prüfen sbrc R20,1 ldi R17,8 ; 1 MHz Startwert für den 148,9 MHz Frequenzbereich ldi R18,9 ; 100 kHz Startwert ldi R19,0 ; 10 kHz Startwert ldi R20,0 ; 1 kHz Startwert ; adiw R24,1 CONVF4: sbiw R24,1 ; Binäres Codewort nach Dezimal wandeln breq CONVF6 ; .. und zum Startwert addieren inc R20 cpi R20,10 brne CONVF4 clr R20 inc R19 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 ; CONVF6: sts FRQ+0,R16 ; Dezimale Frequenzanzeige ablegen sts FRQ+1,R17 sts FRQ+2,R18 sts FRQ+3,R19 sts FRQ+4,R20 ; ret ; ; **** PLL-Einstell-Bytes aurechnen und übergeben ****************** ; Die drei Data Bytes in der PLL werden mit folgendem Wert geladen: ; ((Bandanfang - 10700 - 64 + FFINE + FRQBIN) * 4) +1 ; Bandanfang ist 143900 bzw 148900, FFINE ist 64 +/- 25 SETPLL: push R0 push R16 push R17 push R18 push R24 push R25 ; lds R24,FRQBIN ; Frequenzcode holen lds R25,FRQBIN+1 lds R16,FFINE ; und FFINE addieren add R24,R16 adc R25,C0 ; lds R16,FBER ; Frequenzbereich 144.. oder 150.. ? cpi R16,2 breq SETPL2 ; SETPL1: ldi R18,$02 ; Grundwert für 143,9 MHz, MSB ldi R17,$08 ; 143900 - 10700 - 64 ldi R16,$10 ; .. LSB rjmp SETPL3 ; SETPL2: ldi R18,$02 ; Grundwert für 148,9 MHz, MSB ldi R17,$1B ldi R16,$98 ; .. LSB ; SETPL3: add R16,R24 ; Grundwert + (FRQBIN + FFINE) adc R17,R25 adc R18,C0 ; clc ; PLL-Teiler-Wert * 4 + 1 rol R16 rol R17 rol R18 sec rol R16 rol R17 rol R18 ; rcall OUTPLL ; Ergebnis an Synthesizer ; pop R25 pop R24 pop R18 pop R17 pop R16 pop R0 ret ; ; ; ++++ PLL nach Power-On initialisieren INIPLL: ldi R18,$C0 ; Set Initialization Latch ldi R17,$00 ; .. $C000 Min CP Current, $DF80 Max lds R16,PLLMUX ; .. Byte 3 High Nibble PLL-Mux-Einstellung swap R16 ori R16,$83 ; .. Phase Detector Polarity Positive rcall OUTPLL ; ldi R18,$00 ; Set Reference Counter Latch ldi R17,$50 ldi R16,$00 rcall OUTPLL ; rcall SETPLL ; Set N Counter Latch ret ; ; ; ++++ 24 Bit-Wort in R16,R17,R18 (R16 = LSB) an PLL senden ; HW-Interface: Clock = PC4, Latch Enable = PC5, Data = PB5 OUTPLL: ldi R24,24 ; Loop-Counter ; OUTPL0: rol R16 ; Mov next MSb to Carry rol R17 rol R18 brcc OUTPL1 ; Copy Carry bit to PLL Data sbi PORTC,1 rjmp OUTPL2 OUTPL1: cbi PORTC,1 OUTPL2: nop ; sbi PORTC,4 ; Toggle PLL Clock nop cbi PORTC,4 ; dec R24 ; Decrement Loopcount 24 -> 0 brne OUTPL0 ; cbi PORTC,1 ; Clear Data Line sbi PORTC,5 ; Toggle PLL Latch Enable nop cbi PORTC,5 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,LOW(UBFVAL) ; Aktuellen Wert ... ldi XH,1 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,LOW(FFIVAL+1) ; ldi XH,1 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 5 dB-Abschwächereinstellung inc R16 cpi R16,25 ; 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,LOW(ABSVAL) ; ldi XH,1 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: sts ADMUX,R16 ; ADMUX einstellen clr R16 ; Wait a little for I/O to settle AC1: dec R16 brne AC1 ldi R16,$C6 sts ADCSRA,R16 ; Start ADC AC2: lds R16,ADCSRA sbrs R16,4 ; Wait for ADIF rjmp AC2 ldi R16,$96 sts ADCSRA,R16 ; Clear ADIF lds R16,ADCL ; Get Conversion Results lds 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: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,7 ; Analog-Channel 7 = S-Meter 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 stsi ACSOVE,1 ; .... dann Flag setzen rjmp ACSM ADUM9: stsi ACSOVE,0 ; .... sonst löschen ; ; ; ** 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 ; lds R16,TCNT1L ; Wait until Counter High Byte is 0 lds R16,TCNT1H ; .. to avoid noise by counter tst R16 ; .. counting to max (< 5ms @ 200 Hz) brne ACSM7 ; sts OCR1AH,R17 ; Variablen Oscillator laden sts OCR1AL,R18 ; lds R16,ACSMON ; Piepser je nach Flag Ein-/Aus-Schalten lds R17,ACSOVE ; Wenn S-Meter < Schwelle .. tst R17 brne ACSM8 clr R16 ; .. dann Piepser auf jeden Fall ausschalten ACSM8: sts TCCR1A,R16 sbrc R16,6 ; NF Degate entsprechend schalten sbi DDRB,2 sbrs R16,6 cbi DDRB,2 ; ACSM9: ret ; ;**** Soundgenerator (Alle 60 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 sts OCR1AH,R0 ; Variablen Oscillator laden clr R18 sts OCR1AL,R18 dec R0 ; Sonderfall Wert = 1 breq SOUG1 ; .. Piepser bleibt aus ldi R18,$40 ; .. sonst Piepser aktivieren SOUG1: sts 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,1 ; Pointer auf Bargraph ldi XL,LOW(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 bzw. Entfernung umrechnen CONVAB: ; ++ Abschwächercode in Dämpfungsanzeige umrechnen lds R16,ABSBIN ; Abschwächer Code holen (0..24) mov R17,R16 ; .. und mit 5 malnehmen lsl R17 lsl R17 add R16,R17 ; ldi XH,1 ; In BCD wandeln ldi XL,LOW(ABSCHW) rcall B3BCD lds R17,ABSCHW+1 ; Abschwächer-dB-Wert Anzeigen lds R18,ABSCHW+2 ldi R19,$80 ; dB Symbol ; lds R16,ABSCHW ; .. Wenn >= 100 db tst R16 breq CONVA9 lds R17,ABSCHW ; .... 3stellig ohne dB anzeigen lds R18,ABSCHW+1 lds R19,ABSCHW+2 ; CONVA9: lds R20,PFOXBN ; Wenn PFOXBN = 16 cpi R20,16 ; .. dann dB anzeigen brne CUR1 rjmp CUR499 ; ; ++ Abschwächercode in Entfernungsanzeige umrechnen CUR1: lds R16,ABSBIN ; Abschwächer Code holen lds R17,PFOXBN ; Korrekturfaktor Sendeleistung holen sub R16,R17 ldi R17,21 ; 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,35 ; Wenn Ergebnis > 34 brcs CUR3 ldi R16,34 ; .. auf 34 setzen CUR3: ; ; CUR40: cpi R16,10 ; 19..10 km brcc CUR41 ldi R17,1 ldi R18,9 sub R18,R16 ldi R19,'k' rjmp CUR499 ; CUR41: cpi R16,18 ; 9..2 km brcc CUR44 ldi R17,19 sub R17,R16 ldi R18,'k' ldi R19,'m' rjmp CUR499 ; CUR44: cpi R16,18 ; 1,5 km brne CUR45 ldi R17,1 ldi R18,'k' ldi R19,5 CUR45: cpi R16,19 ; 1 km brne CUR46 ldi R17,1 ldi R18,'k' ldi R19,'m' CUR46: cpi R16,20 ; 700 m brne CUR47 ldi R17,7 clr R18 clr R19 CUR47: cpi R16,21 ; 500 m brne CUR48 ldi R17,5 clr R18 clr R19 CUR48: cpi R16,22 ; 300 m brne CUR49 ldi R17,3 clr R18 clr R19 CUR49: cpi R16,23 ; 200 m brne CUR410 ldi R17,2 clr R18 clr R19 CUR410: cpi R16,24 ; 150 m brne CUR411 ldi R17,1 ldi R18,5 clr R19 CUR411: cpi R16,25 ; 100 m brne CUR412 ldi R17,1 clr R18 clr R19 CUR412: cpi R16,26 ; 70 m brne CUR413 ldi R17,7 clr R18 ldi R19,'m' CUR413: cpi R16,27 ; 50 m brne CUR414 ldi R17,5 clr R18 ldi R19,'m' CUR414: cpi R16,28 ; 30 m brne CUR415 ldi R17,3 clr R18 ldi R19,'m' CUR415: cpi R16,29 ; 20 m brne CUR416 ldi R17,2 clr R18 ldi R19,'m' CUR416: cpi R16,30 ; 10 m brne CUR417 ldi R17,1 ldi R18,0 ldi R19,'m' CUR417: cpi R16,31 ; 7 m brne CUR418 clr R17 ldi R18,7 ldi R19,'m' CUR418: cpi R16,32 ; 5 m brne CUR419 clr R17 ldi R18,5 ldi R19,'m' CUR419: cpi R16,33 ; 3 m brne CUR420 clr R17 ldi R18,3 ldi R19,'m' CUR420: cpi R16,34 ; < 3 m brne CUR499 ldi R17,'<' ldi R18,3 ldi R19,'m' ; CUR499: sts DIST+0,R17 ; Entfernungsanzeige speichern sts DIST+1,R18 sts DIST+2,R19 ; ; Abschwächer-Spannung aus Tabelle holen ; lds R16,ABSBIN ; Abschwächer-Code ldi XL,low(ABSTAB) ; ist Pointer in Tabelle ldi XH,high(ABSTAB) add XL,R16 ld R18,X+ ; Analogwert holen com R18 ; Kleiner Wert => Grosse Spannung sts OCR2A,R18 ; Analogwert an PWM übergeben ; ; Bei Abschwächung ab 65 dB Vorstufe ausschalten, ; bei 20-65 dB abgeschwächt einschalten, sonst voll an ; lds R16,ABSBIN ; Abschwächer-Code cpi R16,13 ; >= 65 dB? brcs CUR6 sbi PORTC,0 ; Ja, Vorstufe Aus sbi DDRC,0 rjmp CUR9 CUR6: cpi R16,4 ; >= 20 dB? brcs CUR61 cbi PORTC,0 ; Vorstufe abgeschwächt Ein cbi DDRC,0 rjmp CUR9 CUR61: cbi PORTC,0 ; Sonst Vorstufe voll Ein sbi DDRC,0 ; CUR9: ret ; ; ; ################### ; #### EEPROM Handling ############################################# ; ################### ; ; ++++ Initialize Steuer-Parameter ; Called if EEPROM is empty or by menu item 'EEPROM Reset' ; EEPNEW: stsi FRQ1,$71 ; F1 = 144,525 MHz stsi FRQ1+1,$02 stsi FRQ2,$00 ; F2 = 143,900 MHz stsi FRQ2+1,$00 stsi FRQ3,$98 ; F3 = 146,100 MHz stsi FRQ3+1,$08 stsi FRQ4,$68 ; F4 = 148,100 MHz stsi FRQ4+1,$10 stsi FRQX,1 ; Aktive Frequenz 1 stsi NFOX,0 ; 5 Füchse stsi NFOX+1,5 ; Fuchs-Laufzeit 60,00 s stsi TFOXS,6 stsi TFOXS+1,0 stsi TFOXMS,0 stsi TFOXMS+1,0 stsi PFOXBN,12 ; Sendeleistung 1W stsi NFREQ,4 ; 4 Frequenzen stsi TALARM,1 ; Alarmzeit -10 s stsi TALARM+1,0 stsi ACSMLV,0 ; ACSM Schwelle 0 (keine) stsi LOCKED,$20 ; Kein Lock stsi ABSTAB+0,40 ; Abschwächertabelle 0,5..120 dB stsi ABSTAB+1,75 stsi ABSTAB+2,101 stsi ABSTAB+3,118 stsi ABSTAB+4,87 ; 20 dB (ab hier Vorstufe -15dB) stsi ABSTAB+5,109 stsi ABSTAB+6,124 stsi ABSTAB+7,135 stsi ABSTAB+8,143 stsi ABSTAB+9,149 stsi ABSTAB+10,155 stsi ABSTAB+11,159 stsi ABSTAB+12,164 stsi ABSTAB+13,78 ; 65 dB (ab hier Vorstufe -50dB) stsi ABSTAB+14,104 stsi ABSTAB+15,120 stsi ABSTAB+16,133 stsi ABSTAB+17,141 stsi ABSTAB+18,148 stsi ABSTAB+19,153 stsi ABSTAB+20,158 stsi ABSTAB+21,163 stsi ABSTAB+22,182 stsi ABSTAB+23,202 stsi ABSTAB+24,210 stsi FFINE,64 ; Frequenzkorrektur +00 stsi UBFINE,130 ; Ub-Mess-Korrektur stsi FBER,1 ; 144-148 MHz stsi UBWBIN,70 ; Battterie Alarm-Schwelle 7,0 V stsi SPRACH,1 ; Sprache Deutsch stsi DISTCF,0 ; Entfernungs-Korrektur +/-0 stsi EEPCLR,VALKEY ; EEPROM ist jetzt gültig ret ; ; ++++ Geänderte Parameter von EEPBEG bis EEP2-1 ; ins EEPROM speichern ; SAVCHG: LDS R16,EEPCLR ; Hat EEPROM gültigen Inhalt? CPI R16,VALKEY BRNE SAVCH9 ; .. sonst nichts speichern ; LDI YL,LOW(EEPBEG) ; Pointer auf Variablen LDI YH,1 LDI R20,0 ; Bytecounter und EEPROM Low Adresse OUT EEARH,C0 ; 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 LDI YH,1 LDI R20,EEP2-EEPBEG ; Bytecounter und EEPROM Low Adresse OUT EEARH,C0 ; 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 LDI YH,1 LDI R20,$00 ; Bytecounter und EPROM Low Adresse OUT EEARH,C0 ; 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,1 ; 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 ldi YH,1 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 * 7 * 256 * 3 Cycle / 5 MHz) DELXMS: PUSH R16 PUSH R17 PUSH R25 ; DXMS: CLR R16 LDI R17,7 D1MS: INC R16 ; 3 cycle inner loop BRNE D1MS ; " " " " DEC R17 BRNE D1MS DEC R25 BRNE DXMS POP R25 POP R17 POP R16 RET ; ; ************************************ ; ******* 400 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 ; ; ++ 400 us Service ; TIM500: sei ; Enable next interrupt ; inctim TIK4U,50,TIM501 ; Increment to 20 msec rjmp TIM504 ; TIM501: sbrc R24,0 ; Alle 800 usec rcall DEBNCE ; .. Debounce Drehgeber ; cpi R24,10 ; Alle 10 msec breq TIM502 cpi R24,35 brne TIM503 TIM502: rcall DEBNC2 ; .. Debounce Taster TIM503: 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,166 ; 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 TIK60,3,TIM21 ; Increment 20 msec Timer up to 3 (60 ms) stsi TICK,1 ; At Time 100 set Timing Flag for Main rjmp TIM21 ; TIM99X: rjmp TIM99 ; TIM21: inctim TIK20M,50,TIM99X ; Increment 20 msec Timer up to 50 (1 s) stsi TACK,1 ; At Time 1 s set Timing Flag for Main ; ; ++ 1 sec Service ; 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 (dann ist eh alles egal...) sts STOPW,R24 ; TIM30: inctim TIK1S,60,TIM99 ; Increment 1 sec Timer up to 60 (1 minute) ; ; ++ 1 min Service lds R24,AOWAIT ; Auto Off Timer 1 Minute weiterzählen inc R24 sts AOWAIT,R24 ; ; ++ 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,AOCYC ; Ausser wenn gerade Auto-Off-Versuch: TST R20 BRNE DEB9 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 ********************************************** ; ************************* ; ; ++++ 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 4 " .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 "1..:... " .DB " " .DB 1,FRQ,0,FRQXSY,FRQ+2,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 neu starten STR04: .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 "1..:... " .DW $1010 ; 1,2,3 .DB $7E," ",$E1,"ndern" .DB $7E," change" .DB $7E," wijzig" .DB 1,FRQ,0,FRQXSY,FRQ+2,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 143,9..146,1 STR250: .DW $1010 ; 1,2,3 .DB "FBereich" .DB "F-Range " .DB "F-Bereik" .DB "144-146",$7E .DW 0 ; ; >12345678< Frequenzbereich 143,9..148,1 STR251: .DW $1010 ; 1,2,3 .DB "FBereich" .DB "F-Range " .DB "F-Bereik" .DB "144-148",$7E .DW 0 ; ; >12345678< Frequenzbereich 150..152,5 STR252: .DW $1010 ; 1,2,3 .DB "FBereich" .DB "F-Range " .DB "F-Bereik" .DB "149-153",$7E .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< PLL Mux einstellen STR29: .DB "PLLMux ." .DB "1L 2N 4R" .DB 1,2,3,4,5,6,7,PLLMUX .DB 1,2,3,4,5,6,7,8 ; ; >12345678< Auto Aus-Zeit einstellen STR2A: .DW $1010 ; 1,2,3 .DB "Auto Aus" .DB "Auto Off" .DB "Auto Off" .DB " :0 Min " .DB 1,2,3,4,5,6,7,8 .DB 1,AOTIM,3,4,5,6,7,8 ; ; >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< 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 UBATT,0,3,0,5,6,7,8 ; ; >12345678< Menü neu aufgemacht STRMEN: .DB "1..:... " .DB ".:..:.,." .DB 1,FRQ,0,FRQXSY,FRQ+2,0,0,LOCKED .DB STOPW,1,0,0,UBATT,0,7,0 ; ; >12345678< Kanal geändert STRFRQ: .DB "1..:... " .DB " - . -" .DB 1,FRQ,0,FRQXSY,FRQ+2,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 60ms-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,22,1,17,1,13,1 ; Power-On-Fanfare .DB 10,10,10,1,1,1,1,0 ; SOUABS: .DB 1,1,6,4,1,1,0,0 ; Automatik-Abschwächer SOUAB2: .DB 6,4,6,4,1,1,0,0 ; dto., Sound für Serie ; SOUALA: .DB 3,4,5,6,7,9,10,12,14,17,22,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 ; SOUPIP: .DB 1,10,10,0 ; 120 msec-Piepser ; 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..... *************************************** ; ************************