; FJRX85.ASM ; ; ******************************* ; * 80m SMD Fuchsjagd Empfänger * ; ******************************* ; ; Unterstützt den 80m-Fuchsjagdempfänger Version 5 (SMD, 2* SA612) ; ; Autor: Nick Roethe, DF1FO, DF1FO at darc.de ; ; Dieser Codestand basiert auf der Version_4-80m-Fuchsjagd-Empfänger-Steuerung FJRX84 1.9 ; ; This source can be assembled for two different targets, select here: .equ TARGET= 0 ; 0 for STEC11B01 Rotary Encoder, 1 for alternate Encoder ; ; Versionsverlauf: ; 15. 4.12 0.0: Code-Import von FJRX84 V1.9 ; 19. 4.12 0.1: Abschwächertabelle in 5dB-Schritten, Vorstufe aus ab 65 dB ; 26. 4.12 0.2: Prozessortakt von 10,24 auf 5,12 MHz reduziert ; 15. 5.12 0.3: Abschwächer in 512 Stufen (statt 256) ; 1. 8.12 0.4: Initialisierungswerte korrigiert, Auto-Off Puls auf 3 s verlängert ; SAVCHG gefixt, schreibt nur noch echte Änderungen ; 3.10.12 0.5: Nahfeld-Indikator-Ton, Abschwächer bei Foxoring direkt auf 0dB ; 7.10.12 0.6: 6 Speicher für Einstellungen, EEPROM-Layout umgekrempelt, ; Editor für Start-/Speichernamen im Abgleichmenü ; Stopuhr nur noch Reset+Start, EEPROM-Reset automatisch wenn ungültig ; Nahwarnton in 7 Entfernungsstufen (300m - 20m) wählbar ; 12.10.12 0.7: Eigener Menüpunkt Nahwarnton, nur noch 2 Sprachen (Deu-Eng) ; Diverse kleine Fixes und Clean-Ups ; 28.10.12 0.8: Nahwarnton mit Abschwächerfortschaltung synchronisiert ; Diverse Fixes, VALKEY auf $6A geändert, Quittungstöne für Drehgeber ; 5.11.12 0.9: Clean-Ups in CLOSUP + Sprachauswahl, #s wie FJRX4V1.3 ; 17.12.12 1.0: Keine Quittungstöne für +/- Frequenz ; Bei ungültigem EEPROM VALKEY Retry nach 100 msec ; Bei immer noch ungültigem EEPROM Mode = 0 = |A^=Reset| ; Abschwächerbereich auf 0..110db (statt 120 dB) beschränkt ; 18.12.12 1.1: Besonderer Startton IMI bei ungültigem EEPROM ; Diverse Clean-Ups ; 11. 1.13 1.2: Batterie-Alarm nur alle 10 Minuten, auch bei Sprint ; Tuning Puls Länge bei Kurzpuls > 8 verdoppelt ; 23. 1.13 1.3: Anfänger-Modus 'Locked' eingebaut (aus FJRX24 1.3 übernommen) ; Frequenzbereich 3,5-3,8 ausgebaut ; 11. 2.13 1.4: Clean-Up zum Locked Modus; V/R-Lupen-Ton max. 2,5 kHz statt 600 Hz ; 1. 4.13 1.5: Fix für 'Nahton bei großer Entfernung' ; 28. 7.13 1.6: Obergrenze Abstimmbereich 3,710 statt 3,660 MHz (für R2 Champs 2013) ; 26. 9.16 1.7: Änderungen für Maximum-Modus (Akust SM, VR-Lupe Menü) ; Fuchsleistungseinstellung bis 30nW, DELXMS korrigiert (3 ms > 1 ms) ; Störimpulsfilter (Statisch, Weidezaun) durch 8ms-Mittelung UMESS4 ; Bessere Schaltknacksunterdrückung V/R-Taster/Schalter ; 18.10.16 1.8: Support for alternate rotary encoder (assembly switch TARGET) ; Attenuator On/Off (Push A long) extended 1sec to 2 sec ; No Finetuning +/- 100 Hz when Locked ; Special Modes 12**V3, 1x2**V3: V changed to A to support Maximum RX ; 22.12.16 1.9: Fix for R21 conflict Interrupt Handler <> Main (found by Oleg, thanks!) ; 14. 9.17 2.0: Stores up to 12 Frequencies per Memory (China style) ; Several small clean-ups and changes to initial settings ; EEPROM Layout changed - settings lost when upgrading 1.9 -> 2.0 ; Fix for Auto Att. not suppressed in Mode 'ACSM Off' + F/B pressed ; 7. 6.18 2.1 Fix for Stack corruption in 'THISF', resulting in unsolicited 'Total Reset' ; .equ VERSHI= '2' .equ VERSLO= '1' ; .equ VALKEY= $5A ; EEPROM Valid Key auf Adresse EEPCLR ; Invalid (old) keys: $59, $69, $6A .equ VALK19= $6A ; Valid key for older Versions up to 1.9 ; ; **** Specify Device .device ATmega168; ; ; >> 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 3-8MHZ, 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 ; .listmac; Macro Expansion Listing On ; ;-------------------------------------------------------- ; ; **** I/O Register Definitions ; MEMORY MAPPED I/O REGISTER DEFINITIONS (&FF-$60) .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) .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 ; ; **** 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 = $100 ; First SRAM Location .equ RAMEND = $4FF ; RAM size 1024 Byte .equ E2END = $1FF ; EEPROM size 512 Byte ; EEPROM-Belegung ; Abgleichbereich, 72 B, ab 000, danach 64B frei ; 6 Einstell-Speicher, je 60B, ab 136, danach 16B frei .equ FLASHEND = $1FFF ; Flash size 8kB = 4 k Instructionen ; ; **** S-Meter Scaling Factor .equ SMSCAL =$C0 ;S-Meter-Scaling-Factor (Higher = more sensitivity) ; ; **** Variablen *************************************************** .DSEG .ORG RAMBEG ; Start of RAM address range ($0110) ; ; ++ Eingestellte Parameter, werden im EEPROM gerettet ; Abgleichbereich EEPCLR: .BYTE 1 ; (EEP $000) $FF wenn leer, VALKEY wenn gültig ABSTAB: .BYTE 50 ; Tabelle 9-bit Level-Werte 0,5,10..120 dB ; Je 2 Byte Hi,Lo: Hi = 0..255, Lo = $00 oder $80 ; Genutzt wird erzeit nur der Bereich 0..110 dB RXNAM: .BYTE 8 ; Empfänger-Name, wird bei Einschalten angezeigt 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 (58..80) DISTCF: .BYTE 1 ; Anpassung Entfernungsschätzung 0..10 (Anz. -5..+5) SPAREF: .BYTE 1 ; Reserve (ehemals Frequenzbereich) SPRACH: .BYTE 1 ; Sprachwahl 1=Deutsch, 0=English AOTIM: .BYTE 1 ; Auto-Off-Zeit, 0 = Aus, 1..7 = 10-70' SPARE: .BYTE 5 ; Reserve ; Ende Abgleich-Bereich MEMNUM: .BYTE 1 ; Aktueller Speicher 0..5, im EEPROM für verriegelt + $80 ; EEPM: ; Beginn Einstell-Bereich, 60B (EEPROM 136 + MEMNUM * 60) MEMNAM: .BYTE 8 ; Name des aktuellen Speichers FRQ1: .BYTE 24 ; Frequenz-Codewert 100 Hz-Schritte Frequenz 1..12 ; 0..3200 = 3,49..3,81, LSB,MSB NFREQ: .BYTE 1 ; Zahl der Frequ. 1..14, 13: Sondermodus 12**v3, 14: 1x2**v3 FRQX: .BYTE 1 ; Aktive Frequenz 1..12 FRQ1X2: .BYTE 10 ; Modus 1x2**v3 Frequenz 1 oder 2 für Fuchs 10, 1..9 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 TALARM: .BYTE 2 ; EOT Alarm Vorlaufzeit 0..31 sec, 0 = Aus Z,E PFOXBN: .BYTE 1 ; Sendeleistung Coded -3=30nW, -2=0,1 µW..15=30W, 16=Nur dB Anzeige ASMMOD: .BYTE 1 ; Akustisches S-Meter 0=Aus, 1= V/R-Lupe, 2 = Maximum Peilen NAHTON: .BYTE 1 ; Schwelle Nahwarnungs-Ton, 0=Aus, 1=300m..7=20m SPAREM: .BYTE 5 ; Reserve ; Ende Einstell-Bereich ; ; ++ Zustands-Variablen MODE: .BYTE 1 ; Mode: 0 = EEPROM ungültig, 2 = Frequenz ändern, 3 = Peilen ; $04..$0x = 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, darüber + STOPW: .BYTE 5 ; Stopuhr Eh,Zm,Em,Zs,Es STOPWR: .BYTE 1 ; 1 = Stopuhr läuft, 0 = steht TIMER: .BYTE 4 ; Count Down Timer Zs,Es,Hms,Zms zählt in 20 ms Schritten FOX: .BYTE 2 ; Current Fox Z,E 1..10 ABSBIN: .BYTE 1 ; Abschwächer Binaer-Wert 0..22 für 0, 5, 10..110 dB ABSSET: .BYTE 2 ; 2 Abschwächer-Analogwerte, werden im Wechsel ausgegeben ABSCHW: .BYTE 3 ; Abschwächer Anzeige 0..120 dB in 5 dB Stufen H,Z,E ABSVAL: .BYTE 3 ; Abschwächer Analogwert 0..255 H,Z,E DIST: .BYTE 4 ; Distanz-Anzeige H,Z,E DISTBN: .BYTE 1 ; Distanz Codewert 0=9 km, 12=300m,15=100m,17=30m, 19=10m NFREQV: .BYTE 2 ; N Frequency Decimal Z,E 01..14 FRQXV: .BYTE 2 ; Current Frequency Number Decimal 01..12 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 KLKLK: .BYTE 1 ; Doppel Klick Erkennung, nach 1. Klick für 800 ms > 0 AAWAIT: .BYTE 1 ; Wartezeit nach 5dB-Auto-Abschwächung oder V/R (n * 60 ms) VRWAIT: .BYTE 1 ; V/R-Taster Wartezeit, > 0 = ist/war gedrückt (n * 60 ms) VRPREV: .BYTE 1 ; V/R-Taster vorheriger Status, 1 = gedrückt FLATIM: .BYTE 1 ; Verbleibende Flashtime für Text-Flash (n * 60 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 FRQ512: .BYTE 1 ; Vorige Frequenz-Nr für Mode 5, Rückkehr von Freq-Nr 3 AUTOON: .BYTE 1 ; Abschwächer-Automatik ein = ' ', aus = '*' ACSMTH: .BYTE 1 ; Akustisches S-Meter > Schwelle = 1, < = 0 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 NAHTIM: .BYTE 1 ; Timer für NahTon, inkrementiert alle 60 msec EDTCNT: .BYTE 1 ; Namens-Editor-Cycle-Zähler 0= Aus, 1..6= MEMNAM 0..5, 7=RXNAM EDTPOS: .BYTE 1 ; Namens-Editor-Cursor 0..7 EDTCHR: .BYTE 1 ; Namens-Editor, aktuelles Zeichen EDTADR: .BYTE 1 ; Pointer auf erstes Zeichen des Editstrings, Low Byte, High Byte = 1 EDTNUM: .BYTE 1 ; Namens-Editor, MEMNUM vor Start Editor zum wiederherstellen LOCKED: .BYTE 1 ; $81 = Verriegelt = Anfängermode, $20 = Normal ; ++ Analog-Werte UBATT: .BYTE 3 ; Batterie-Spannung in V/mV Z,E,h UMESSA: .BYTE 4 ; Messspannung für akustisches S-Meter, letzte 4 Werte, 2 ms Abstand UMESS4: .BYTE 1 ; Mittelwert der letzten 4 UMESSA Werte UMESSP: .BYTE 4 ; Spitzenwertspeicher Umess für S-Meter, Ältester Wert in *+3 UMESSR: .BYTE 10 ; Spitzenwertspeicher Umess als Referenz für ASM bei V/R UMREF: .BYTE 1 ; Spitzenwert aus UMESSR, begrenzt auf 64..127 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-Flag, 1 = prüfen FRQTIM: .BYTE 1 ; Frequenzwechselzeit Mode 14 VRMUTE: .BYTE 1 ; V/R-Taster-Knacken Mute-Timer, dekrementiert jede 1 ms 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 DEBST: .BYTE 1 ; Debounce Schnell-Taster TIK43: .BYTE 1 ; Zaehlt jede 400 us bis 3 (1,2 msec) TIK425: .BYTE 1 ; Zaehlt jede 400 us bis 25 (10 msec) TIK450: .BYTE 1 ; Zaehlt jede 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) TIK300: .BYTE 1 ; Zaehlt jede 60ms bis 5 (300 ms, für Batterie-A/D-Wandlung) TIK1S: .BYTE 1 ; Zaehlt jede 1 s bis 60 (1 min) TIKMIN: .BYTE 1 ; Zaehlt jede Minute bis 10 Minten TIK100: .BYTE 1 ; Zaehlt jede 400 us bis 250 = 100 ms (für TUNE) TUNLEN: .BYTE 1 ; Abstimmpulslänge in ms (für TUNE) SWICNT: .BYTE 1 ; For Alternate Rotary Encoder ; ; ********************** ; **** 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 call OUTLCD ; .. und Ergebnis anzeigen .ENDMACRO ; ; ++++ Flash Text String @0 for @1*60ms .MACRO FLASH ldi ZL,low(2*@0) ; Ausgabe-Kommand-String ldi ZH,high(2*@0) sts FLASTR,ZH sts FLASTR+1,ZL call LCDSTR ; .. ausführen call 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 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,LOW(@0) ; Pointer auf BCD-String ldi XH,1 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 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 ************************************* ; ***************************** ; ; ++++ Cold Start Entry START: clr R16 STADEL: inc R16 ; Wait 1000 Cycles nop brne STADEL clr R5 ; EEPROM Reset Flag löschen rjmp STA00 ; ; ++++ Total Reset Entry STARTR: clr R5 ; EEPROM Reset Flag setzen inc R5 ; ; ++++ Initialize Stackpointer to end of internal RAM STA00: 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) STA01: st X+,C0 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 Dreh-Drücker with Pull-Up ; 5 as Input Abschwächertaster with Pull-Up ; PB3..PB5 also SPI-I/F ldi R16,$00 out DDRB,R16 ldi R16,$33 out PORTB,R16 ; ; ++++ Initialize Port C Bit 0..2 as Analog In URicht, Uv/r, Ub ; 3 as Output Unused Y1 ; 4 as Output Mute in HZ ; 5 as Output Display E ; 6 as Analog In Unused, tied to Gnd ; 7 as Analog In Unused Y2 ldi R16,$28 out DDRC,R16 ldi R16,$00 out PORTC,R16 ; ; ++++ Initialize Port D Bit 0..4 as Output for Display ; 5 as Input Counter/Timer 1 ; 6 as Output PWM Attenuator ; 7 as Input w P-Up Menu-Switch ldi R16,$5F out DDRD,R16 ldi R16,$80 out PORTD,R16 ; ; ++++ Initialize A/D-Converter LDI R16,$00 ; Select Analog Input 0 STS ADMUX,R16 LDI R16,$86 ; Enable ADC, Clock Divider 64 = 125 kHz STS ADCSRA,R16 ; = 250 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,$83 ; Set Comparator A as PWM for Attenuator out TCCR0A,R16 ldi R16,255 ; Start value for PWM out OCR0A,R16 ldi R16,$01 sts TIMSK0,R16 ; Enable Counter 0 Overflow Interrupt ; ; ++++ Intialize Timer/Counter 1 as Frequency Counter ldi R16,$00 ; Count Rising Edges on T1 Input sts TCCR1A,R16 ldi R16,$07 sts TCCR1B,R16 ; ; ++++ Intialize Timer/Counter 2 as Frequency Generator for Sounds stsi TCCR2A,$42 ; Clock Divider 256, CTC, Toggle on Compare stsi TCCR2B,$06 ; => Sound = 10 kHz / Compare Value ; Changed to 40 kHz for F/B-Zoom ; ; ++++ Hole Ableichwerte + Einstellungen aus EEPROM ; Wenn 'Total Reset' Flag gesetzt: vorher initialisieren tst R5 ; Bei 'Total Reset' Start (R5 > 0) breq STA021 call INIABG ; .. Abgleichwerte initialisieren call INIMEM ; .. 6 Speicher im EEPROM initialisieren ; STA021: call GETCAL ; Abgleichwerte aus EEPROM holen call GETMEM ; Aktuelle Einstellwerte holen lds R16,EEPCLR ; Bei ungültigem VALKEY .. cpi R16,VALKEY breq STA022 ; ldi R25,100 ; .. 100 ms warten und dann 2. Versuch call DELXMS call GETCAL ; Abgleichwerte aus EEPROM holen call GETMEM ; Aktuelle Einstellwerte holen lds R16,EEPCLR ; Bei immer noch ungültigem VALKEY .. cpi R16,VALKEY breq STA022 ; cpi R16,VALK19 ; Ist im EEPROM der VALKEY der Version 1.9? breq STA02A ; ; Nein stsi MODE,0 ; .. Mode auf 0 = Ungüliges EEPROM stsi UBWBIN,40 ; .. Batteriewarnung aus stsi NAHTON,0 ; .. Nahton aus stsi ABSBIN,22 ; .. Abschwächer zu rjmp STA023 ; ; ++ Upgrade 1.9 -> 2.0, Initialize Memories and Valid Key STA02A: call INIMEM ; .. dann die Memories initialisieren ldi R16,VALKEY sts EEPCLR,R16 call SAVCAL flash STRSAV,10 ; .... Anzeige Save to EEPROM sound SOUOK ; .... und Quittungston ; ; ++++ Initialize some Variables STA022: stsi MODE,3 ; Anfangs-Mode = Peilen sbic PINB,4 ; Wenn Drücker gedrückt rjmp STA023 ; stsi MODE,$20 ; .. dann Abgleichmode ; STA023: stsi STOPWR,1 ; Stopuhr läuft nach Power-On an stsi AUTOON,' ' ; Abschwächer-Automatik Ein call CONVBW ; Batterie-Warnungslevel bereitstellen ; ; ++++ Start Interrupt Handler STA03: rcall CLRTIM ; Fuchstimer auf Startwert sei ; Global Interrupt enable ; ; ++++ Initialize LCD and show Start Text call INILCD ldi R25,100 ; Wait 100 ms call DELXMS stsi SWIFLG,0 ; Clear any Drehgeber Flags stsi SWICNT,0 ; tst R5 ; Wenn normal Start (nicht Total Reset) brne STA04 flash STRPO,20 ; .. normaler Starttext rjmp STA05 STA04: flash STRTRE,40 ; .. sonst Total Reset Anzeigen ; STA05: lds R16,MODE ; Wenn EEPROM gültig (Mode > 0) tst R16 breq STA06 sound SOUPO ; .. normale Power-On-Fanfare rjmp STA09 STA06: sound SOUINV ; .. sonst IMI-Fanfare ; STA09: rjmp MAIN6 ; Start Main Loop with A/D of UBat ; ; ************* ; **** Main Loop *************************************************** ; ************* ; MAIN: ; ++++ Mode Updaten MAIN2: lds R16,MODE ; Mode holen mov R21,R16 ; Alten Mode retten ; tst R16 ; Wenn Mode = 0 = EEPROM Ungültig breq MAIN3 ; .. Mode nicht ändern ; sbis PIND,7 ; Wenn Schalter nicht auf Menü (=Peilen) rjmp M21 ldi R16,3 ; .... dann Mode 3 ; cpi R16,3 ; Wenn Mode = 3 brne M29 cpi R21,3 ; .. und bisheriger Mode <>3 breq M29 stsi FRQTIM,1 ; .... Flag FRQTIM für Mode 1x2**v3 setzen flash STRBAK,15 ; .... aktuellen Speichernamen flashen 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 lds R20,FLATIM ; .. Falls kein Flash aktiv tst R20 brne M29 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 MA30 sts FLATIM,C0 ; .. dann laufende Flashes abbrechen stsi AOWAIT,0 ; .. und Auto Off Timer auf 0 ; ; ++ Quittungston bei Betätigung, ausser bei Peilen oder Frequenz ändern MA30: lds R18,MODE ; Wenn Mode >= 4 (nicht Peilen, Frequenz ändern) cpi R18,04 brcs MAIN30 mov R18,R17 ; .. und U/D oder U/D-Pressed Flag andi R18,$0F breq MA31 sound SOUPIP ; .... Hoher Ton MA31: mov R18,R17 ; .. und Click Flag andi R18,$10 breq MAIN30 sound SOUPAP ; .... Mittlerer Ton ; ; ++++ Abschwächertaster behandeln ; MAIN30: tst R16 ; Wenn Modus = 0 = EEPROM leer brne M3005 sbrs R17,6 ; .. und lang drücken rjmp M399 rjmp STARTR ; .... Kaltstart mit Total Reset ; M3005: sbrs R17,6 ; Modus > 0 und Lang drücken rjmp M3007 ; sbis PINB,4 ; .. und Drehdrücker nicht gedrückt rjmp M3X2 lds R18,LOCKED ; .. und nicht gelockt sbrc R18,0 rjmp M309 ; ; lds R18,AUTOON ; Abschwächer-Automatik toggeln ldi R19,$0A ; .. ' ' <> '*' eor R18,R19 sts AUTOON,R18 cpi R18,' ' ; Passenden Quittungston + Text erzeugen breq M3006 sound SOUAA0 flash STRAA0,15 rjmp M309 M3006: sound SOUAA1 flash STRAA1,15 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 call SAVNUM ; .. auch im EEPROM sound SOUOK rjmp M309 ; M3007: sbrs R17,5 ; Kurz drücken rjmp M309 lds R16,ABSBIN ; = Abschwächer öffnen ; lds R18,PFOXBN ; Wenn PFOX <= 6 (1mW, also Foxoring) cpi R18,6 brpl M3009 stsi ABSBIN,0 ; .. dann Abschwächer auf 0 dB rjmp M303 ; Wenn PFox > 3 mW: M3009: cpi R16,11 ; Wenn < 300m @ 1W brcs M301 stsi ABSBIN,10 ; .. dann auf 300m (50 dB) rjmp M303 M301: cpi R16,6 ; Wenn 1,5km..300m @ 1W brcs M302 stsi ABSBIN,5 ; .. dann auf 2km (25 dB) rjmp M303 M302: stsi ABSBIN,0 ; .. sonst auf 0 dB ; M303: push R17 call CONVAB ; Neuen Abschwächerwert einstellen pop R17 M309: andi R17,$9F ; Switch Flag Bits 5, 6 löschen ; ; ++++ Auto Off Timer handeln lds R18,AOTIM ; Zeitlimit mit Istwert vergleichen andi R18,$07 ; 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,50 ; .. und Abschaltversuch starten ; ; ; ++++ Je nach Mode: Drehdrücker handeln M30A: lds R16,MODE cpi R16,3 ; Bei Mode 3 breq M3011 rjmp M3020 ; M3011: sbrs R17,4 ; Wenn Klick Flag gesetzt.. rjmp M3012 ; andi R17,$10 lds R18,KLKLK ; Ist dies der 2te Klick in 300 ms? tst R18 breq M30111 rcall NEXTF ; .. dann Frequenz weiterschalten clr R18 ; .. und Klicktimer löschen rjmp M30112 M30111: ldi R18,8 ; .. Sonst Klicktimer auf 800 ms setzen M30112: sts KLKLK,R18 clr R17 ; M3012: lds R18,ABSBIN ; Drehen ohne Drücken: Abschwächer stellen sbrc R17,0 ; Up Flag inc R18 ; sbrc R17,1 ; Down Flag dec R18 ; cpi R18,-1 ; Limit to 0..22 brne M3013 ldi R18,0 M3013: cpi R18,23 brne M3014 ldi R18,22 M3014: sts ABSBIN,R18 ; sbrs R17,0 ; Wenn Up Flag rjmp M3015 call UMR50P ; .. ACSM-Referenzwert-Buffer halbieren stsi AAWAIT,3 ; .. und Abschwächerautomatik kurz unterdrücken ; M3015: andi R17,$0C ; Drehen mit Drücken: breq M3019 rcall NF5T12 ; 5..12 Frequenzen? breq M30151 rcall NEXTF ; .. Frequenznummer +/- ; M30151: lds R20,LOCKED ; <= 4 Frequenzen cpi R20,$81 ; .. wenn Locked: nix tun breq M3019 rcall UDFRQ ; .. sonst Frequenz +/- 100 Hz flash STR02,10 ; M3019: sts EDTCNT,C0 ; Clean-Up wenn Namens-Edit per Schalter abgebrochen rjmp M399 ; fertig ; M3020: cpi R16,2 ; Bei Mode 2 brne M3021 rcall UDFRQ ; Frequenz ändern rjmp M399 ; fertig ; M3021: 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: lds R20,EDTCNT ; Wenn Namens-Editor aktiv tst R20 brne M34 ; .. Modus nicht ändern sbrc R17,0 ; Wenn Up Flag inc R16 ; .. Mode erhöhen sbrc R17,1 ; Wenn Down Flag dec R16 ; .. Mode verringern cpi R16,9 ; Mode Range auf 4..8, $10..$17 ,$20..$29 brne M332 ; beschränken ldi R16,4 M332: cpi R16,3 brne M333 ldi R16,8 M333: cpi R16,$18 brne M334 ldi R16,$10 M334: cpi R16,$0F brne M335 ldi R16,$17 M335: cpi R16,$2A brne M336 ldi R16,$20 M336: cpi R16,$1F brne M337 ldi R16,$29 M337: sts MODE,R16 ; Mode speichern ; M34: cpi R16,4 ; Wenn Mode = 4 brne M35 sbrs R17,4 ; .. und Drückerpuls rjmp M35 rcall CLRSTW ; .... dann Stopuhr löschen und starten 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 stsi MODE,$13 ; .. dann neuer Mode 13 rjmp M399 ; M37: cpi R16,7 ; Wenn Mode = 7 (Frequ. ändern?) brne M38 sbrs R17,4 ; .. und Drehdrücker Click rjmp M371 stsi MODE,$02 ; .. dann neuer Mode 2 (Vary Frq.) rjmp M399 ; M371: andi R17,$0C ; .. und drehen mit Drücken breq M38 rcall UDFRQ ; .... Frequenz +/- 100 Hz flash STR02,10 stsi SOUPNT+1,0 ; .... kein Quittungston rjmp M399 ; M38: cpi R16,8 ; Wenn Mode = 8 brne M310 rcall UDMEM ; .. dann Memory umschalten 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 M316 rcall UDTA ; .. dann EOT Alarmzeit verändern rjmp M399 ; M316: cpi R16,$16 ; Wenn Mode = 16 brne M317 rcall UDASM ; .. dann Flag V/R-Lupe Ein-Aus rjmp M399 ; M317: cpi R16,$17 ; Wenn Mode = 17 brne M320 rcall UDNATO ; .. dann Nahwarnton Entfernungsschwelle einstellen rjmp M399 ; M320: cpi R16,$20 ; Wenn Mode = 20 brne M321 rcall UDSPRA ; .. Sprache einstellen rjmp M399 ; M321: cpi R16,$21 ; Wenn Mode = 21 brne M322 sbrs R17,4 ; .. und Drehdrücker Click rjmp M322 rjmp STARTR ; .. dann Kaltstart ; 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 Abschwächer-Levels eichen rjmp M399 ; M325: cpi R16,$25 ; Wenn Mode = 25 brne M326 rcall UDUBW ; .. Batterie-Warnungs-Pegel einstellen rjmp M399 ; M326: cpi R16,$26 ; Wenn Mode = 26 brne M327 rcall CALDIS ; .. dann Distanz kalibrieren rjmp M399 ; M327: cpi R16,$27 ; Wenn Mode = 27 brne M328 rcall UDAOT ; .. Auto Off Time 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,10 ; .... Anzeige Save to EEPROM sound SOUOK ; .... und Quittungston rjmp M399 ; M329: cpi R16,$29 ; Wenn Mode = 29 brne M399 lds R20,EDTCNT ; .. und Edit aktiv tst R20 brne M32A1 ; .... Edit ausführen sbrs R17,4 ; .. kein Edit aber Drehdrücker Click rjmp M399 M32A1: call UDEDIT rjmp M399 ; M399: ; call ADUM ; Messspannung A/D-Wandeln und behandeln ; ; Gedrückten V/R-Taster erkennen und Timer setzen MAIN4: ldi R16,1 ; Analogkanal 1 = V/R-Taster Flag wandeln ldi R19,$10 call ANACON andi R16,$FC ; Wenn Ergebnis > 3 (300 mV): Taster gedrückt breq MAIN40 stsi VRWAIT,3 ; Dann Automatik 180 ms unterdrücken ; MAIN40: lds R17,VRPREV ; Hat sich Schalterzustand gegen letzten Pass geändert? tst R16 ; Aktuellen Zustand auf 0/1 normieren breq MAIN41 ldi R16,1 MAIN41: sts VRPREV,R16 ; .. und als neuen alten speichern cp R16,R17 ; Wenn neu <> alt breq MAIN49 stsi VRMUTE,100 ; .. Mute Timer auf 100 ms setzen MAIN49: ; ; ; ++++ Alles weitere nur alle 60 ms: ++++++++++++++++++++++++++++++++++ MAIN5: lds R16,TICK ; 60 ms Flag testen tst R16 brne MAIN51 rjmp MAIN MAIN51: clr R16 sts TICK,R16 ; ; V/R-Taster Timer dekrementieren auf 0 lds R16,VRWAIT tst R16 breq MAIN55 dec R16 MAIN55: sts VRWAIT,R16 ; ; Doppel Klick Timer dekrementieren auf 0 lds R16,KLKLK tst R16 breq MAIN56 dec R16 MAIN56: sts KLKLK,R16 ; ; ++++ Wenn Empfänger übersteuert und Automatik Ein ; und (Abschwächertaster nicht gedrückt oder Maximum-Modus): ; Wenn S-Meter am Anschlag: Abschwächer 10 dB höher, sonst 5 dB höher ; Tatü (je 60 ms 2 kHz und 3 kHz) ; MAINA: lds R16,AAWAIT ; Wartezeit, weil gerade erst abgeschwächt? tst R16 ; Wenn Wert > 1.. breq MAINAC dec R16 sts AAWAIT,R16 ; .. nur Wartezähler dekrementieren breq MAINAC ; Bei altem oder neuem Wert 0 Automatik handeln MAINAB: rjmp MAINB ; MAINAC: lds R16,AUTOON ; Automatik eingeschaltet? cpi R16,' ' brne MAINAB ; .. sonst nix tun ; lds R16,VRMUTE ; V/R-Mute unterdrückt Knacksen tst R16 brne MAINAB ; .. während Mute nix tun ; MAINA0: lds R16,ASMMOD ; Wenn ACSM-Mode = 0,1 (Aus, V/R-Lupe) andi R16,2 brne MAINA1 lds R16,VRWAIT ; .. und V/R-Taster aktiv (oder gerade gewesen) tst R16 brne MAINAB ; .... dann Abschwächer-Automatik unterdrücken ; MAINA1: lds R17,UMESSP ; Messpannung > Schwelle? cpi R17,128 ; 128 ist S-Meter Vollausschlag brcc MAINA2 rjmp MAINB ; sonst fertig ; MAINA2: lds R16,ABSBIN ; .. ja: Abschwächer hochschalten cpi R16,22 ; .. ausser wenn schon am Anschlag breq MAINB inc R16 sts ABSBIN,R16 call UMR50P ; .. ASM-Referenz-Buffer halbieren cpi R17,$FF ; .. falls Messpannung > 2 * Schwelle (Anschlag) brne MAINA4 cpi R16,22 breq MAINA4 inc R16 ; .... um insgesamt 2 Stufen hochschalten sts ABSBIN,R16 call UMR50P ; .... ASM-Referenz-Buffer noch mal halbieren MAINA4: call CONVAB ; .. neuen Abschwächerwert einstellen stsi AAWAIT,2 ; .. Wartezeit vor nächster Abschwächung (120 ms) stsi NAHTIM,0 ; .. NahWarnTon-Timer rücksetzen lds R16,FLATIM ; .. Wenn Textanzeige nicht aktiv 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 ; ; Annäherungswarntöne erzeugen MAINB: call CLOSUP ; ; ACSM Referenzwert ermitteln lds R16,VRWAIT ; Wenn V/R nicht gedrückt tst R16 brne MAINB0 lds R16,AAWAIT ; und Abschwächer hat nicht gerade erst runtergeschaltet tst R16 brne MAINB0 call UMRNXT ; Referenzwert Buffer weiterschieben, Spitzenwert ermitteln ; ; ++++ Alarm-Tonfolge erzeugen, wenn Flag gesetzt und Mode = 3 ; und mehr als 1 Fuchs MAINB0: 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 ; Timer setzt BATTIM Flag zur Zeit n*10' + 12" auf 1 MAINB1: lds R17,BATTIM ; Timer BATTIM holen tst R17 ; Wenn = 0 breq MAINB6 ; .. nix tun ; stsi BATTIM,0 ; Wenn = 1 auf 0 setzen ; 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: ; ; ; ++++ 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 = 14 (Mode 1x2**v3) cpi R17,14 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: lds R16,TIK300 ; Nur alle 300 ms ausführen tst R16 ; Wenn 300 ms Timer > 0 nichts tun brne MAIN61 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,1 ; Pointer auf Anzeige-Fenster ldi XL,LOW(UBATT) rcall B3BCD ; Ergebnis in BCD wandeln und ablegen ; ; ++++ Entfernungsanzeige und S-Meter-Balken erzeugen ; MAIN61: call CONVAB ; Abschwächer-Einstellung in Entfernung umrechnen ; call CONVUM ; Messspannung in Bargraph-Anzeige wandeln ; rcall CONVNF ; Zahl der Frequenzen umwandeln rcall CONVFX ; Aktuelle Frequenz Nummer umwandeln ; ; ++++ 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,49 ; Bei Zählerstand 49 (= -3 Sekunden) 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 lds ZH,FLASTR ; .. Flash-String auffrischen lds ZL,FLASTR+1 call LCDSTR call OUTLCD ; .. und Ergebnis anzeigen rjmp MAIN8 ; MAIN7: lds R16,MODE M70: cpi R16,0 brne M72 show STR00 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 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 M78 lds R18,LOCKED ; .. bei Locked unterdrücken cpi R18,$20 brne M771 show STR07 rjmp M710 M771: show STRMEN M78: cpi R16,8 brne M710 show STR08 M710: cpi R16,$10 brne M711 lds R18,NFOX+1 ; NFuchs = 1: Foxoring zeigen cpi R18,1 breq M7101 show STR10 rjmp M711 M7101: show STR101 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 lds R18,NFREQ ; Wenn Sondermodi 13 oder 14 cpi R18,13 brne M7141 show STR145 ; .. Sondertexte zeigen rjmp M715 M7141: cpi R18,14 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 ; .. sonst Alarmzeit zeigen M716: cpi R16,$16 ; Modus akustisches S-Meter brne M717 lds R18,ASMMOD cpi R18,0 brne M7161 show STR160 rjmp M717 M7161: cpi R18,1 brne M7162 show STR161 rjmp M717 M7162: show STR162 ; M717: cpi R16,$17 breq M7170 rjmp M720 M7170: lds R18,NAHTON cpi R18,0 brne M7171 show STR170 M7171: cpi R18,1 brne M7172 show STR171 M7172: cpi R18,2 brne M7173 show STR172 M7173: cpi R18,3 brne M7174 show STR173 M7174: cpi R18,4 brne M7175 show STR174 M7175: cpi R18,5 brne M7176 show STR175 M7176: cpi R18,6 brne M7177 show STR176 M7177: cpi R18,7 brne M720 show STR177 ; 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 show STR28 M729: cpi R16,$29 breq M72A0 rjmp M799 M72A0: lds R18,EDTCNT cpi R18,0 brne M72A1 show STR2A0 M72A1: cpi R18,1 brne M72A2 show STR2A1 M72A2: cpi R18,2 brne M72A3 show STR2A2 M72A3: cpi R18,3 brne M72A4 show STR2A3 M72A4: cpi R18,4 brne M72A5 show STR2A4 M72A5: cpi R18,5 brne M72A6 show STR2A5 M72A6: cpi R18,6 brne M72A7 show STR2A6 M72A7: cpi R18,7 brne M799 show STR2A7 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: sts STOPWR,C0 ; Run-Flag löschen sts STOPW,C0 ; Zeit auf 0 setzen sts STOPW+1,C0 sts STOPW+2,C0 sts STOPW+3,C0 sts STOPW+4,C0 sts STOPWR,C1 ; und Run-Flag setzen ret ; ; **** Timer löschen bei Klick, +/- bei Drück + Dreh UDCTMR: sbrc R17,4 ; Wenn Drückerpuls rcall CLRTIM ; .... dann Timer löschen und starten ; UDCT2: andi R17,$0C ; Switch-Flag Up Oder Down gesetzt? breq UDCT9 ; .. dann derzeitige Fuchs# ändern ; push R16 ldi XL,LOW(NFOX) ; Pointer auf NFox-BCD-String ldi XH,1 rcall 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 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,LOW(FOX) ; Pointer auf BCD-String ldi XH,1 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 ; ; **** Memory anzeigen bei Klick, +/- bei Drück + Dreh UDMEM: sbrs R17,4 ; Wenn Drückerpuls rjmp UDMEM0 call CONVPF ; .. dann Sendeleistungseinstellung in Text wandeln flash STROVW,30 ; .. und Übersicht Einstellungen zeigen ; UDMEM0: andi R17,$0C ; Switch-Flag Up Oder Down gesetzt? breq UDMEM9 ; .. dann derzeitige Fuchs# ändern ; push R16 lds R16,MEMNUM sbrs R17,3 ; Up-Flag, dann Memory-Nummer erhoehen inc R16 sbrs R17,2 ; Down-Flag dec R16 cpi R16,-1 ; Auf 0..5 begrenzen brne UDMEM1 ldi R16,5 UDMEM1: cpi R16,6 brne UDMEM2 ldi R16,0 UDMEM2: sts MEMNUM,R16 rcall SAVNUM ; Geänderte Nummer ins EEPROM rcall GETMEM ; Neues Memory aus EEPROM holen sound SOUPOS pop R16 ; UDMEM9: 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..14) 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..14 (Wrap) brne NFRQ2 ldi R16,14 NFRQ2: cpi R16,15 brne NFRQ3 ldi R16,1 NFRQ3: sts NFREQ,R16 ; NFRQ32: stsi FRQX,1 ; Nach Änderung: Frequenz 1 aktivieren stsi FRQ1X2,1 ; Für Modus 13, 14 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 ; NFRQ9: ret ; ; *** Set Zero Flag Z if number of frequencies 5..12 NF5T12: push R16 lds R16,NFREQ cpi R16,5 brcs NF50 cpi R16,13 brcs NF59 NF50: clr R16 NF59: tst R16 ; Set Z Flag if 5..12 pop R16 ret ; ; **** Convert Number of frequencies Binary to Decimal for display CONVNF: push R16 push R20 lds R16,NFREQ mov R20,R16 ; Convert one Binary to two decimals subi R20,10 brcc CNF1 sts NFREQV+1,R16 sts NFREQV,C0 rjmp CNF9 CNF1: sts NFREQV+1,R20 sts NFREQV,C1 CNF9: pop R20 pop R16 ret ; ; **** Convert current Frequency Number Binary to Decimal for display CONVFX: push R16 push R20 lds R16,FRQX mov R20,R16 ; Convert one Binary to two decimals subi R20,10 brcc CFX1 sts FRQXV,R16 ; Up to 9: x,' ' ldi R16,' ' sts FRQXV+1,R16 rjmp CFX9 CFX1: sts FRQXV+1,R20 ; Else: 1,x sts FRQXV,C1 CFX9: pop R20 pop R16 ret ; ; **** EOT Alarm-Zeit (0..30) verändern UDTA: push R16 TA1: sbrs R17,2 ; Up Flag rjmp TA2 i2bcd TALARM,0,30 rjmp TA8 TA2: sbrs R17,3 ; Down Flag rjmp TA8 d2bcd TALARM,0,30 TA8: pop R16 ret ; ; **** Laufzeit Fuchs Sekunden(1..99) verändern UDTFS: sbrs R17,2 ; Up Flag rjmp TFS2 i2bcd TFOXS,1,99 rjmp TFS8 TFS2: sbrs R17,3 ; Down Flag rjmp TFS9 d2bcd TFOXS,1,99 TFS8: rcall CLRTIM ; Nach Änderung: Fuchstimer neu starten TFS9: ret ; ; **** Laufzeit Fuchs ms (0,2..98) verändern UDTFMS: sbrs R17,2 ; Up Flag rjmp TFM2 i2bcd TFOXMS,0,99 i2bcd TFOXMS,0,99 brcs TFM1 rjmp TFM8 TFM1: i2bcd TFOXS,1,99 rjmp TFM8 TFM2: sbrs R17,3 ; Down Flag rjmp TFM9 d2bcd TFOXMS,0,99 brcc TFM3 d2bcd TFOXS,1,99 TFM3: d2bcd TFOXMS,0,99 TFM8: rcall CLRTIM ; Nach Änderung: Fuchstimer neu starten TFM9: ret ; ; **** Leistung der Füchse verändern UDPF: lds R16,PFOXBN sbrs R17,2 ; Up Flag rjmp UDPFA inc R16 rjmp UDPFB UDPFA: sbrs R17,3 ; Down Flag rjmp UDPF9 dec R16 UDPFB: cpi R16,17 ; Limit to -3..16 brne UDPFC ldi R16,16 UDPFC: cpi R16,-4 brne UDPFD ldi R16,-3 UDPFD: sts PFOXBN,R16 rcall CONVPF ; Convert Code to Textform UDPF9: ret ; ; **** Sprache auswählen UDSPRA: lds R16,SPRACH ; Get current language sbrc R17,2 ; Up Flag inc R16 sbrc R17,3 ; Down Flag dec R16 andi R16,1 ; Limit to 0, 1 sts SPRACH,R16 ; Geänderte Sprache speichern UDSP9: 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 ; ; **** 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 CPFM3: cpi R16,-3 brne CPFM2 stsi PFOX+0,3 stsi PFOX+3,'n' CPFM2: cpi R16,-2 brne CPFM1 stsi PFOX+2,1 stsi PFOX+3,$E4 ; 'µ' CPFM1: cpi R16,-1 brne CPF0 stsi PFOX+2,3 stsi PFOX+3,$E4 ; 'µ' 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 ; 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: cpi R25,$08 ; und wenn Ergebnis > 2200 = $0898 (3,71 MHz) brne UDFRQ8 cpi R24,$98 brcs UDFRQ8 ldi R24,$98 ; .. auf 2200 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 ; ; **** Akustisches SM Ein-/ausschalten UDASM: lds R18,ASMMOD sbrc R17,2 ; Wenn Up Flag inc R18 ; .. toggeln sbrc R17,3 ; Wenn Down Flag dec R18 ; .. toggeln sbrc R17,4 ; Wenn Druckpuls gesetzt inc R18 ; .. toggeln cpi R18,3 ; Auf 0..2 begrenzen, wrappen brne UDASM1 ldi R18,0 UDASM1: cpi R18,-1 brne UDASM9 ldi R18,2 UDASM9: sts ASMMOD,R18 ret ; ; ; **** Nahwarn-Ton Entfernungsschwelle einstellen 0..7 UDNATO: lds R18,NAHTON sbrc R17,2 ; Wenn Up Flag inc R18 ; .. toggeln sbrc R17,3 ; Wenn Down Flag dec R18 ; .. toggeln andi R18,$07 sts NAHTON,R18 ret ; ; ; **** Switch to next Frequency NEXTF: push R17 push R18 rcall PUTFRQ ; Put current frequency FRQBIN -> FRQ1..4 ; lds R16,MODE cpi R16,3 ; Bei Mode 3 (also Doppelklick) brne NEXTFA lds R16,NFREQ ; und NFREQ = 13,14 cpi R16,13 brcc NEXTFB ; .. Sonderbehandlung NEXTFA: rjmp NEXTF0 NEXTFB: lds R16,DEBST ; Sonderfall NFREQ = 13,14 und 'A' gedrückt tst R16 breq NEXTFX ldi R16,3 ; .. dann neue Frequenz 3 (Zielfuchs) rjmp NEXTF2 NEXTFX: lds R16,NFREQ ; Sonderfall NFREQ = 13 cpi R16,13 brne NEXTFE lds R16,FRQX cpi R16,1 ; Aktuelle Frequenz = 1 brne NEXTFC ldi R16,2 ; .. neue Frequenz = 2 sts FRQ512,R16 ; .. Freq.-Nr. merken rjmp NEXTF2 NEXTFC: cpi R16,2 ; Aktuelle Frequenz = 2 brne NEXTFD ldi R16,1 ; .. neue Frequenz = 1 sts FRQ512,R16 ; .. Freq.-Nr. merken rjmp NEXTF2 NEXTFD: lds R16,FRQ512 ; Aktuelle Frequenz = 3, auf vorige Frequenz zurück rjmp NEXTF2 ; NEXTFE: ldi ZH,1 ; Sonderfall NFREQ = 14 lds ZL,FOX+1 ; Pointer auf FRQ1X2-Entry bauen ldi R16,LOW(FRQ1X2) add ZL,R16 ld R16,Z ; .. und Entry lesen ; lds R18,FRQX cpi R18,3 ; Wenn derzeitige Frequenz = 3 brne NEXTFF rjmp NEXTF2 ; .... dann auf FRQ1X2 wechseln ; NEXTFF: ldi R18,$03 ; Sonst: FRQ1x2 toggeln 1<>2 eor R16,R18 st Z,R16 rjmp NEXTF2 ; NEXTF0: lds R16,FRQX ; Normalmodus: Frequenz-Nummer weiterschalten lds R18,NFREQ ; .. und bei > Maximum nach 1 wrappen cpi R18,13 brcs NXTF01 ; .. bei NFREQ = 13,15 ist Maximum = 3 ldi R18,3 NXTF01: inc R18 sbrc R17,2 ; Push + Right turn inc R16 sbrc R17,3 ; Push + left turn dec R16 sbrc R17,4 ; Click inc R16 cp R16,R18 brne NXTF02 ldi R16,1 NXTF02: tst R16 brne NEXTF2 mov R16,R18 dec R16 ; NEXTF2: sts FRQX,R16 rcall GETFRQ ; Get new Frequency FRQ 1..12 -> FRQBIN rcall CONVF ; Dezimale Frequenzanzeige bereitstellen rcall NF5T12 ; <> 5..12 Frequenzen? brne NXTF21 flash STRFRQ,20 ; Neue Frequenz String flashen rjmp NEXTF3 NXTF21: flash STRFRX,20 ; Neue Frequenz bei >= 5 Sender ; NEXTF3: rcall NF5T12 ; 5..12 Frequenzen? breq NXTF31 sound SOUFX ; .. Standard-Tonfolge rjmp NEXTF9 NXTF31: lds R16,FRQX 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 NEXTF9 sound SOUF4 ; Neue Frequenz 4 Tonfolge NEXTF9: pop R18 pop R17 ret ; ; ; ; Switch to Frequency # in R16 THISF: push R17 push R18 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..12 GETFRQ: rcall NF5T12 ; 5..12 Frequenzen? breq GETF1 ; Bei >= 5 Frequenzen ldi R17,$A1 ; .. festes Frequenzsymbol rjmp GETF5 GETF1: lds R16,FRQX cpi R16,1 ; .. sonst 1..4 Punkte 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 -> 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,$DC ; Hex von 34900 - 4600 - 128, LSB ldi R17,$75 ; 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,LOW(UBFVAL) ; Aktuellen Wert ... ldi XH,1 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,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 cbi DDRB,3 ; Sicherheitshalber: Sound ausschalten cbi DDRC,4 ; .. und Mute ausschalten ldi YL,low(ABSTAB) ; Tabelle mit Abschwächerwerten ldi YH,high(ABSTAB) ; stsi ABSBIN,0 ; Abschwächer auf 0 dB setzen ; CALAB1: sbic PIND,7 ; Wenn Kippschalter nicht mehr auf Menü (FRQ) rjmp CALAB9 ; .. abbrechen ld R16,Y+ ; Aktuellen Wert Hi holen ld R20,Y ; Aktuellen Wert Lo holen dec YL lds R17,SWIFLG ; Switch Flags holen clr R18 ; .. und löschen sts SWIFLG,R18 ldi R19,$80 ; Increment/Decrement-Wert sbrs R17,0 ; Increment? rjmp CALA11 add R20,R19 adc R16,R18 CALA11: sbrs R17,1 ; Decrement? rjmp CALA12 sub R20,R19 sbc R16,R18 CALA12: st Y+,R16 ; Aktuellen Wert speichern andi R20,$80 st Y,R20 dec YL ; sbrs R17,4 ; Click? rjmp CALAB2 lds R16,ABSBIN ; Nächste 5 dB-Abschwächereinstellung inc R16 cpi R16,23 ; bis maximal 22 breq CALAB9 sts ABSBIN,R16 inc YL ; Pointer auf nächsten Abschwächerwert inc YL rjmp CALAB1 ; CALAB2: rcall CONVAB ; Abschwächer einstellen ld R16,Y+ ; Aktuellen Analogwert Hi ld R17,Y ; " Lo dec YL ldi XL,low(ABSVAL) ; ldi XH,1 rcall N3BCD ; .. 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 ; ; **** 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 ; ; ; **** 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 1 Byte 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 ; ; **** Convert 9 bits in R16/R17 to 3B BCD @ X, X+1, X+2 N3BCD: push R16 push R17 push R18 push R19 in R19,SREG ; Save Statusreg mit Carry Flag push R19 ; rol R17 ; Highest Bit in R17 is least significant Bit rol R16 ; Result: Bits 0..7 in R16, 8 in Carry brcc N3B0 ldi R17,6 ; Wenn Bit 8 = 1, Startwert 256 ldi R18,5 ldi R19,2 rjmp N3B1 N3B0: clr R17 ; Einerstelle clr R18 ; Zehnerstelle clr R19 ; Hunderterstelle N3B1: rjmp B3B1 ; Weiter wie oben ; ; ; **** 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 ; ; ; **** Namen der Speicher und des Empfängers ändern UDEDIT: push R16 lds R20,EDTCNT ; Nummer des aktuellen Namens sbrs R17,4 ; Bit 4 = Druckpuls gesetzt? rjmp UDED2 tst R20 ; Wenn nicht Edit Neustart breq UDED01 rcall EDTPUT ; Aktuellen Editcharacter retten UDED01: inc R20 ; Nummer weiterschalten andi R20,$07 ; und auf 0..7 begrenzen sts EDTCNT,R20 sts EDTPOS,C0 ; Cursor auf Anfang stsi EDTADR,low(MEMNAM) ; Adresse des Edit-Strings ; cpi R20,1 ; Wenn Edit Neustart brne UDED05 lds R16,MEMNUM ; Aktuelle Speichernummer retten sts EDTNUM,R16 stsi EDTADR,low(RXNAM) rjmp UDED1 ; UDED05: call SAVCHG ; Wenn Wechsel auf nächstes Memory: Änderungen sichern cpi R20,0 ; Wenn Edit beendet brne UDED06 lds R16,EDTNUM ; .. Ursprüngliche Speichernummer wiederherstellen sts MEMNUM,R16 call GETMEM call SAVSTN ; Geänderten RXNAM ins EEPROM rjmp UDED9 ; UDED06: dec R20 ; Für neues Memory 0..5 dec R20 sts MEMNUM,R20 ; UDED07: call GETMEM ; Aktuellen Speicher laden ; ; Start neuer Edit UDED1: rcall EDTGET ; Aktuellen Character in Edit-Fenster ; UDED2: mov R16,R17 andi R16,$03 ; Rechts/Links drehen ohne drücken? breq UDED4 rcall EDTPUT ; Dann bisherigen Editcharacter ablegen lds R20,EDTPOS ; Cursorposition schalten sbrc R17,0 inc R20 sbrc R17,1 dec R20 andi R20,$07 sts EDTPOS,R20 rcall EDTGET ; und neuen Editcharacter holen ; UDED4: lds R20,EDTCHR ; Rechts/links drehen mit Drücken sbrc R17,2 ; Character fortschalten inc R20 sbrc R17,3 dec R20 sts EDTCHR,R20 rcall EDTLIM ; Character auf erlaubten Bereich einschränken ; UDED7: rcall EDTPUT lds R20,TIK20M ; Editier-Character blinken lassen andi R20,$F0 brne UDED79 ldi R16,'^' st X,R16 ; X-Register noch gültig von EDTPUT UDED79: UDED9: pop R16 ret ; ; ** Den Character auf EDTADR+EDTPOS+$100 nach EDTCHR kopieren, durch ^ ersetzen EDTGET: push R20 lds XL,EDTADR ; Pointer auf aktuellen Character lds R20,EDTPOS add XL,R20 ldi XH,1 ld R20,X ; Character holen zum editieren sts EDTCHR,R20 pop R20 ret ; ; ** Den Character EDTCHR nach EDTADR+EDTPOS+$100 kopieren EDTPUT: push R20 lds XL,EDTADR ; Pointer auf aktuellen Character lds R20,EDTPOS add XL,R20 ldi XH,1 lds R20,EDTCHR ; Character holen st X,R20 pop R20 ret ; ; ** EDTCHR auf den gewünschten Bereich beschränken EDTLIM: push R20 lds R20,EDTCHR EDTL0: cpi R20,'0'-1 ; Wrappen Blank <> 0 brne EDTL1 ldi R20,' ' EDTL1: cpi R20,' '+1 brne EDTL2 ldi R20,'0' EDTL2: cpi R20,'A'-1 ; Wrappen 9 <> A brne EDTL3 ldi R20,'9' EDTL3: cpi R20,'9'+1 brne EDTL4 ldi R20,'A' EDTL4: cpi R20,'a'-1 ; Wrappen Z <> a brne EDTL5 ldi R20,'Z' EDTL5: cpi R20,'Z'+1 brne EDTL6 ldi R20,'a' EDTL6: cpi R20,' '-1 ; Wrappen z <> Blank brne EDTL7 ldi R20,'z' EDTL7: cpi R20,'z'+1 brne EDTL9 ldi R20,' ' EDTL9: sts EDTCHR,R20 pop R20 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: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 R25,2 ; 2 msec Abstand zwischen den Messwerten rcall DELXMS ; 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 sbrc R16,7 ; Ergebnis verdoppeln ldi R16,$FF ; .. begrenzen auf 255 sec rol R16 sts UMESSA,R16 ; Momentanwert speichern für akustische Ausgabe ; lds R16,UMESSA+3 ; 4 letzte Werte Messspannung (2 msec Abstand) mitteln clr R17 ; .. zur Störimpulsunterdrückung clr R19 lds R18,UMESSA+2 sts UMESSA+3,R18 ; .. und weiterschieben add R16,R18 adc R17,R19 lds R18,UMESSA+1 sts UMESSA+2,R18 add R16,R18 adc R17,R19 lds R18,UMESSA sts UMESSA+1,R18 add R16,R18 adc R17,R19 clc ; Ergebnis durch 4 teilen ror R17 ror R16 clc ror R17 ror R16 ; Ergebnis ist max. 255 ; sts UMESS4,R16 ; 8 msec Average speichern für ACSM lds R17,UMESSP ; Spitzenwert für Balken-S-Meter bilden cp R16,R17 brcs ADUM8 sts UMESSP,R16 ADUM8: ; ; ; **** Akustisches S-Meter erzeugen ; ACSM: lds R19,SOUPNT+1 ; Ist Sound Pointer <> 0 (Sound aktiv)? tst R19 breq ACSM00 rjmp ACSM9 ; .. dann hat Sound Vorrang ; ACSM00: lds R16,ASMMOD ; ASM-Modus aus Einstellmenü cpi R16,0 ; Modus 0 = Aus breq ACSM80 ; .. ASM ausschalten cpi R16,1 ; Modus 1 = V/R-Lupe breq ACSMM1 rjmp ACSMM2 ; Sonst Modus 2 = Maximum ; ; ASM Modus 1 = V/R-Lupe ; Eingangswert ist UMESS4 0..255, Bar-S-Meter ab 127 am Anschlag ; Ton wird nur ausgegeben, wenn der V/R-Taster gedrückt ist ; und das S-Meter mehr als den Referenzwert (Spitzenwert der letzten 10*60ms) zeigt ACSMM1: lds R16,UMESS4 ; Messpannung holen lds R17,UMREF ; .. und um Referenzwert verringern sub R16,R17 cpi R16,50 ; Wenn > 50 brcs ACSM0 ldi R16,50 ; auf 50 begrenzen ; ACSM0: ldi R17,66 ; 0..50 -> 66..16 sub R17,R16 ; ; ACSM71: lds R16,TCNT2 ; Wait until Counter <16 andi R16,$F0 ; .. to avoid noise by counter tst R16 ; .. counting to max (< 5ms @ 200 Hz) brne ACSM71 ; stsi TCCR2B,$04 ; Sound = 40 kHz / Compare Value sts OCR2A,R17 ; Variablen Oscillator laden ; lds R16,ACSMTH ; ACSM-Schwellwertschalter handeln lds R17,UMESS4 ; Wenn Messpannung < Referenzwert lsr R17 lds R18,UMREF lsr R18 sub R17,R18 sbrc R17,7 clr R16 ; .. Schwellwertschalter aus ldi R18,3 sub R17,R18 ; Wenn Messpannung > Referenzwert + 6 sbrs R17,7 ldi R16,1 ; .. Schwellwertschalter ein sts ACSMTH,R16 ; Abspeichern ; lds R16,VRWAIT ; Wenn VRWAIT = 0 (V/R nicht gedrückt) tst R16 breq ACSM80 lds R16,ACSMTH ; .. oder Schwellwertschalter aus tst R16 breq ACSM80 lds R16,AUTOON ; .. oder Abschwächer Automatik aus cpi R16,'*' brne ACSM81 ; ACSM80: cbi DDRB,3 ; dann Sound ausschalten lds R16,VRMUTE ; .. und wenn nicht V/R-Taster-Knacken-Unterdrückung aktiv tst R16 brne ACSM84 cbi DDRC,4 ; .... Mute ausschalten rjmp ACSM9 ACSM84: sbi DDRC,4 ; .... sonst Mute einschalten (V/R-Mute bei ASM aus) rjmp ACSM9 ; ACSM81: sbi DDRC,4 ; Sonst Mute einschalten lds R16,VRMUTE ; .. und wenn nicht V/R-Taster-Knacken-Unterdrückung aktiv tst R16 brne ACSM82 sbi DDRB,3 ; .... Sound einschalten rjmp ACSM9 ACSM82: cbi DDRB,3 ; .... sonst Sound ausschalten (V/R-Mute bei ASM ein) ; ACSM9: ret ; ; ASM Modus 2 = Maximum ; Eingangswert ist UMESS4 0..255, Bar-S-Meter ab 127 am Anschlag ; Werte größer 127 auf 127 begrenzt, für 31 .. 127 ansteigenden Ton 320-3200 Hz ; Ton nur ausgegeben, wenn Abschwächerautomatik ein ACSMM2: lds R16,UMESS4 ; Messwert holen sbrc R16,7 ; Auf 0..127 begrenzen ldi R16,127 cpi R16,32 ; Wenn < 32 brcs ACSM28 ; Ton aus ldi R17,127 sub R17,R16 ; 127..31 -> 0..96 mov R16,R17 ; ; Ton 0..96 (R16) in 26..250 (R17) wandeln, geknickte Kennlinie ldi R18,26 ; 0..31 -> 26..57 add R17,R18 cpi R17,57 brcs ACSM22 ldi R18,32 ; 32..63 -> 58..120 sub R17,R18 add R17,R16 cpi R17,120 brcs ACSM22 ldi R18,64 ; 64..96 -> 122..250 sub R16,R18 add R17,R16 add R17,R16 ; ACSM22: lds R16,TCNT2 ; Wait until Counter <16 andi R16,$F0 ; .. to avoid noise by counter tst R16 ; .... counting to max (< 5ms @ 200 Hz) brne ACSM22 ; stsi TCCR2B,$03 ; Sound = 80 kHz / Compare Value sts OCR2A,R17 ; Variablen Oscillator laden ; lds R16,VRWAIT ; Wenn VRWAIT = 0 (Max/Min-Schalter auf Min) tst R16 breq ACSM28 ; .. kein ASM ; lds R16,ABSBIN ; Wenn ABSBIN = 0 (Höchste Empfindlichkeit) tst R16 brne ACSM27 lds R16,UMESS4 ; .. und Messwert < 64 (1/2 S-Meter statt 1/4) cpi R16,64 brcs ACSM28 ; .. kein ASM ACSM27: rjmp ACSM81 ; Sonst Ton ausgeben ACSM28: rjmp ACSM80 ; ;**** 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 ; .. schon fertig ; SOUG1: lpm ; Get one Byte to R0 adiw ZL,1 ; Increment Z stsi TCCR2B,$06 ; Sound = 10 kHz / Compare Value sts OCR2A,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 ; ldi XH,1 ; Pointer auf Bargraph ldi XL,LOW(UMESS) rcall NF5T12 ; Wenn >= 5 Frequenzen breq CUM0A ldi XL,LOW(UMESS+3) ; Bargraph 2 Stellen rechts schieben ldi R16,4 ; und nur 4 Stellen statt 8 lsr R17 ; Und Anzeigewert zusätzlich halbieren auf 0..15 rjmp CUM0B CUM0A: ldi R16,8 ; Stellenzähler CUM0B: lsr R17 ; 0..127 für Anzeige auf 0..31 skalieren lsr R17 dec R17 ; Um 1 verringern auf -1 .. 30 ; CUM1: ldi R19,$20 ; Blank ist Bargraph-Wert 0 tst R17 ; Wenn Anzeigewert < 0 brmi CUM3 ; .. diese Stelle Blank ; ldi R19,$85 ; Bargraphwert auf 4 voreinstellen cpi R17,$04 ; Wenn Anzeigewert < 4 brcc CUM3 ; mov R19,R17 ; .. Bargraphwert ist 2 LSb von Anzeigewert andi R19,$03 ldi R18,$82 ; .. + $82 add R19,R18 ; CUM3: st X+,R19 ; Bargraphwert speichern ldi R18,4 ; Anzeigewert um 4 verringern sub R17,R18 dec R16 ; Loopcount, 8 Passes brne CUM1 ; rcall NF5T12 ; Wenn > 4 Frequenzen breq CUM7 lds R16,FRQXV ; .. Frequenznummer in Position 1,2,3 anzeigen sts UMESS+1,R16 ; .... im Format Fx bzw F1x lds R16,FRQXV+1 sts UMESS+2,R16 stsi UMESS,'F' stsi UMESS+7,' ' ; CUM7: lds R16,LOCKED ; Wenn Verriegelt sbrc R16,0 sts UMESS+7,R16 ; .. in Position 7 Schlüssel zeigen ; CUM8: ret ; ; *** Referenzwert Puffer halbieren (wenn Abschwächung hochschaltet) UMR50P: push R16 ldi YL,low(UMESSR) ; Pointer auf Referenzwert Puffer ldi YH,1 UMR501: ld R16,Y ; Einen Wert holen lsr R16 ; halbieren st Y+,R16 ; ablegen und Y weiterschalten cpi YL,low(UMESSR+10) ; insgesamt 10 * brne UMR501 stsi UMESSP,0 ; Messspannung Momentanspitzenwert löschen pop R16 ret ; ; *** Referenzwert Puffer Service alle 60 ms ; Alles eins weiterschieben, neuesten Spitzenwert einfügen ; Gesamt-Spitzenwert ermitteln, auf 64..127 begrenzen, Ergebnis in UMREF UMRNXT: push R16 push R17 ldi YL,low(UMESSR+9) ; Pointer auf Referenzwertbuffer (10 Stellen) ldi YH,1 UMRG0: ld R16,-Y ; Bisherigen Inhalt eins nach rechts rücken std Y+1,R16 ; 8->9, 7->8 ... 0->1 cpi YL,low(UMESSR) brne UMRG0 lds R17,UMESSP ; Spitzenwert der letzten 60 ms in Position 0 sts UMESSR,R17 ; ldi YL,low(UMESSR) ; Pointer auf Referenzwert Puffer ldi YH,1 clr R16 UMRG1: ld R17,Y+ ; einen Wert holen cp R16,R17 ; wenn grösser als bisheriges Maximum brcc UMRG2 mov R16,R17 ; als neues Maximum nehmen UMRG2: cpi YL,low(UMESSR+10) ; insgesamt 10 * brne UMRG1 cpi R16,127 ; Wenn Ergebnis > 127 brcs UMRG3 ldi R16,127 ; .. auf 127 begrenzen UMRG3: cpi R16,40 ; Wenn Ergebnis < 40 brcc UMRG4 ldi R16,40 ; .. auf 40 begrenzen UMRG4: sts UMREF,R16 pop R17 pop R16 ret ; ; **** Abschwächercode in Anzeige Dämpfung/Entfernung umrechnen CONVAB: ; ** 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,1 ; In BCD wandeln für dB-Anzeige ldi XL,LOW(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,10 ; Basis-Offset dazu add R16,R17 ; lds R17,ASMMOD ; Wenn Maximumpeilung cpi R17,2 brne DIS3 lds R17,VRWAIT ; .. und Schalter auf Max tst R17 breq DIS3 dec R16 ; .. Entfernung eine Stufe weiter ; 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: sts DISTBN,R16 ; Distanz-Codewert für Annäherungs-Warnton sbrc R16,7 ; Wenn Code Negativ ist rjmp CUR490 ; .. dB anzeigen ; ldi R18,'k' ldi R19,'m' ; cpi R16,0 ; 9 km brne CUR41 ldi R17,9 CUR41: cpi R16,1 ; 8 km brne CUR42 ldi R17,8 CUR42: cpi R16,2 ; 7 km brne CUR43 ldi R17,7 CUR43: cpi R16,3 ; 6 km brne CUR44 ldi R17,6 CUR44: cpi R16,4 ; 5 km brne CUR45 ldi R17,5 CUR45: cpi R16,5 ; 4 km brne CUR46 ldi R17,4 CUR46: cpi R16,6 ; 3 km brne CUR47 ldi R17,3 CUR47: cpi R16,7 ; 2 km brne CUR48 ldi R17,2 CUR48: cpi R16,8 ; 1,5 km brne CUR49 ldi R17,1 ldi R19,5 CUR49: cpi R16,9 ; 1 km brne CUR410 ldi R17,1 CUR410: cpi R16,10 ; 700 m brne CUR411 ldi R17,7 clr R18 clr R19 CUR411: cpi R16,11 ; 500 m brne CUR412 ldi R17,5 clr R18 clr R19 CUR412: cpi R16,12 ; 300 m brne CUR413 ldi R17,3 clr R18 clr R19 CUR413: cpi R16,13 ; 200 m brne CUR414 ldi R17,2 clr R18 clr R19 CUR414: cpi R16,14 ; 150 m brne CUR415 ldi R17,1 ldi R18,5 clr R19 CUR415: cpi R16,15 ; 100 m brne CUR416 ldi R17,1 clr R18 clr R19 CUR416: cpi R16,16 ; 50 m brne CUR417 ldi R17,5 clr R18 CUR417: cpi R16,17 ; 30 m brne CUR418 ldi R17,3 clr R18 CUR418: cpi R16,18 ; 20 m brne CUR419 ldi R17,2 clr R18 CUR419: cpi R16,19 ; 10 m brne CUR420 ldi R17,1 clr R18 CUR420: cpi R16,20 ; 5 m brne CUR421 clr R17 ldi R18,5 CUR421: cpi R16,21 ; 2 m brne CUR422 clr R17 ldi R18,2 CUR422: cpi R16,22 ; 1 m brne CUR423 clr R17 ldi R18,1 CUR423: cpi R16,23 ; < 1 m brcs CUR490 ldi R17,'<' ldi R18,1 ; CUR490: sts DIST+0,R17 ; Entfernungsanzeige bereitstellen sts DIST+1,R18 sts DIST+2,R19 ; ; Abschwächer-Spannung aus Tabelle holen und in ABSSET ablegen ; ABSSET und ABSSET+1 werden alle 400 usec abwechselnd ausgegeben ; lds R16,ABSBIN ; Abschwächer-Code ldi XL,low(ABSTAB) ; ist Pointer in Tabelle ldi XH,high(ABSTAB) add XL,R16 add XL,R16 ld R18,X+ ; Analogwert Hi aus Tabelle holen sts ABSSET,R18 ; Und als Set Wert ablegen sts ABSSET+1,R18 ld R19,X+ ; Analogwert Lo (1 bit) holen andi R19,$80 ; Wenn least significant bit = 1 breq CUR495 inc R18 ; .. und Set Wert < 255 breq CUR495 sts ABSSET+1,R18 ; 2ten Analogwert 1 höher CUR495: ; ; CUR9: ret ; ; ++++ Annäherungswarntöne erzeugen (wird alle 60 ms aufgerufen) ; Bei Annäherunga auf z.B. 300/100/30 (je nach Einstellung ; der Schwelle) alle 4 Sekunden Warnton ausgeben, ; zusätzlich nach automatischem Abschwächer 2 x Warntonn ; CLOSUP: lds R20,PFOXBN ; Wenn Leistungseinstellung 'nur dB' cpi R20,16 ; .. keine Sounds breq CU9 ; lds R20,NAHTON ; Nahton-Wert holen tst R20 ; Keine Sounds wenn Bit 2..0 = 000 breq CU9 ; lds R16,NAHTIM ; NahWarnTon Timer inkrementieren inc R16 brne CU8 ; Bei Überlauf ldi R16,$80 ; .. auf $80 setzen CU8: sts NAHTIM,R16 ; lds R16,SOUPNT+1 ; Wenn Soundgenerator busy tst R16 ; Keine Sounds brne CU9 ; lds R16,NAHTIM ; Zur Zeit $X8 x 60msec andi R16,$0F cpi R16,$08 brne CU9 lds R16,NAHTIM andi R16,$F0 ; Zur Sekunde X = 0,1,4,8,.. cpi R16,$10 breq CU0 andi R16,$30 brne CU9 ; CU0: lds R16,DISTBN ; Distanz-Codewert holen sub R16,R20 ; Schwelle je nach Nahton-Einstellung cpi R16,15 ; <= Stufe 3 brmi CU1 sound SOUD3 rjmp CU9 CU1: cpi R16,13 ; <= Stufe 2 brmi CU2 sound SOUD2 rjmp CU9 CU2: cpi R16,11 ; <= Stufe 1 ? brmi CU9 sound SOUD1 ; CU9: ret ; ; ################### ; #### EEPROM Handling ############################################# ; ################### ; ; ++++ Initialisierung der Abgleichwerte im RAM und EEPROM aus Tabelle im Flash ; Called at Start if EEPROM is empty or by menu item 'Total Reset' ; INIABG: ldi ZL,low(2*EEPABG) ; Pointer auf Ini.-Werte im Flash ldi ZH,high(2*EEPABG) ldi XL,low(EEPCLR+1) ; Pointer auf EEPROM-Kopie im RAM ldi XH,high(EEPCLR+1) ; INIA1: lpm ; Copy one Byte from Flash st X+,R0 ; .. to RAM adiw ZL,1 ; Next cpi XL,low(MEMNUM) brne INIA1 ; rcall SAVCAL ; Abgleichwerte ins EEPROM schreiben ret ; ; ++++ Initialisierung der Memories im EEPROM aus der Tabelle im Flash ; Called at Start if EEPROM is empty ; INIMEM: ldi ZL,low(2*EEPMEM) ; Pointer auf Ini.-Werte im Flash ldi ZH,high(2*EEPMEM) clr R22 ; Memory-Zähler 1..5 INIM1: ldi XL,low (EEPM) ; Pointer auf EEPROM-Kopie im RAM ldi XH,high(EEPM) ; INIM2: lpm ; Copy one Byte from Flash st X+,R0 ; .. to RAM adiw ZL,1 ; Next cpi XL,low(EEPM+60) brne INIM2 ; sts MEMNUM,R22 rcall SAVCHG ; Dieses Memory speichern inc R22 ; Nächstes Memory cpi R22,6 brne INIM1 ; stsi MEMNUM,5 ; Aktuelles Memory = 5 rcall SAVNUM ; Aktuelle Nummer auch im EEPROM speichern rcall GETMEM ; Aktuelles Memory laden ret ; ; ; ++++ Geänderte Parameter von EEPM bis EEPM+55 ; ins EEPROM, aktuelle Speichernummer, speichern ; SAVCHG: push R16 push R17 push R18 push R20 push R21 push XL push XH push YL push YH ldi YL,LOW(EEPM) ; Startadress of Variables in RAM ldi YH,HIGH(EEPM) ldi XL,136 ; Startaddress Memory 0 in EEPROM ldi XH,0 lds R20,MEMNUM ; + Memorynumber * 60 SAVCH0: tst R20 breq SAVC01 adiw XL,60 dec R20 rjmp SAVCH0 ; SAVC01: clr R20 ; Bytecounter bis 60 OUT EEARH,XH ; High Adresse SAVCH1: LD R16,Y+ ; 1 Variable holen ; Derzeitigen Wert aus EEPROM holen und vergleichen OUT EEARL,XL ; EEPROM Entry Adresse laden LDI R17,$01 OUT EECR,R17 ; Set EEPROM Read Cmd IN R17,EEDR ; Daten lesen CP R16,R17 ; .. und vergleichen BREQ SAVCH4 ; Wenn ungleich: ins EEPROM schreiben rcall EEPRDY ; Wait for EEPROM Write complete OUT EEARL,XL 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 rcall EEPRDY ; Wait for EEPROM Write complete ; SAVCH4: INC XL INC R20 CPI R20,60 ; Gesamter Bereich geschrieben? BRNE SAVCH1 pop YH pop YL pop XH pop XL pop R21 pop R20 pop R18 pop R17 pop R16 RET ; ; ++++ Abgleichwerte von EEPCLR bis MEMNUM-1 ins EEPROM speichern ; SAVCAL: stsi EEPCLR,VALKEY ; EEPROM valid key setzen LDI YL,LOW(EEPCLR) ; Pointer auf Variablen im RAM ldi YH,1 clr R20 ; Pointer auf Variablen im EEPROM (Low Address) ldi R21,MEMNUM-EEPCLR ; Ende des EEPROM-Schreibbereichs SAVCA0: OUT EEARH,C0 ; EEPROM High Adresse ist 0 SAVCA1: LD R16,Y+ ; 1 Variable holen rcall EEPRDY ; Wait for EEPROM Write complete 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 CP R20,R21 ; Gesamter Bereich geschrieben? BRNE SAVCA1 rcall EEPRDY ; Wait for EEPROM Write complete RET ; ; ++ Nur den Startnamen ins EEPROM schreiben SAVSTN: ldi YL,low(RXNAM) ; Pointer auf Name im RAM ldi YH,1 ldi R20,low(RXNAM-EEPCLR) ; Pointer auf Name im EEPROM ldi R21,low(RXNAM+8-EEPCLR) ; Ende des Schreibbereichs im EEPROM rjmp SAVCA0 ; ; ++++ Aktuelle Speichernummer ins EEPROM speichern ; Falls Locked: Speichernummer + $80 ; SAVNUM: push R17 rcall EEPRDY ; Wait for EEPROM Write complete OUT EEARH,C0 ; High Address ist 0 ldi R16,MEMNUM-EEPCLR ; Low Address im EEPROM OUT EEARL,R16 lds R16,MEMNUM ; Aktuelle Speichernummer lds R17,LOCKED ; Falls Locked $80 dazu andi R17,$80 or R16,R17 OUT EEDR,R16 CLI ; Interrupt ausschalten LDI R17,$04 LDI R16,$02 OUT EECR,R17 ; Set EEPROM Master Write Enable OUT EECR,R16 ; Set EEPROM Write SEI ; Interrupt wieder an rcall EEPRDY ; Wait for EEPROM Write complete pop R17 RET ; EEPRDY: push R17 EEPR1: IN R17,EECR ; Wait for EEPROM Write complete ANDI R17,$02 BRNE EEPR1 pop R17 ret ; ; ++++ Abgleichwerte + EEPCLR + MEMNUM aus EEPROM holen +++++++++++++++ ; GETCAL: LDI YL,Low(EEPCLR) ; Pointer auf Variablen ldi YH,1 LDI R20,$00 ; Bytecounter und EPROM Low Adresse OUT EEARH,C0 ; High Adresse ist 0 GETC1: OUT EEARL,R20 LDI R17,$01 OUT EECR,R17 ; Set EEPROM Read Cmd IN R16,EEDR ; Daten lesen ST Y+,R16 ; Byte bzw low nibble speichern INC R20 ; Loopcounter CPI R20,MEMNUM+1-EEPCLR ; Alle Bytes gelesen? BRNE GETC1 ; MEMNUM aus EEPROM zerlegen in MEMNUM und LOCKED ldi R17,$20 ; Locked ist $20 (Aus) oder $81 (Ein) sbrc R16,7 ; .. je nach MSb im EEPROM Wert ldi R17,$81 sts LOCKED,R17 andi R16,$07 ; Locked-Flag entfernen sts MEMNUM,R16 RET ; ; ++++ Einstellwerte aus Speicher im EEPROM holen ++++++++++++++++++++++ ; GETMEM: push R16 push R17 push R20 push R21 push XL push XH push YL push YH ; ldi YL,LOW(EEPM) ; Startadress of Variables in RAM ldi YH,HIGH(EEPM) ; ldi XL,136 ; Startaddress Memory 0 in EEPROM ldi XH,0 lds R20,MEMNUM ; + Memorynumber * 60 GETM0: tst R20 breq GETM01 adiw XL,60 dec R20 rjmp GETM0 GETM01: ; clr R20 ; Bytecounter bis 60 OUT EEARH,XH ; High Adresse is 0 or 1 GETM1: OUT EEARL,XL LDI R17,$01 OUT EECR,R17 ; Set EEPROM Read Cmd IN R16,EEDR ; Daten lesen ST Y+,R16 ; Byte bzw low nibble speichern inc XL INC R20 ; Loopcounter CPI R20,60 ; Alle Bytes gelesen? BRNE GETM1 ; ; Nach Wechsel des Speichers alles auf Anfangswert (ausser Stopuhr, Auto-On/Off) call GETFRQ ; Aktuelle Frequenz laden call CONVF ; Frequenz Dezimal ausrechnen call CLRTIM ; Fuchstimer auf Startwert stsi FRQTIM,1 ; Bei Mode NFREQ=14 richtige Frequenz laden stsi FRQ512,1 ; Vorige Frequenz-Nr für 12<>3, Rückkehr 3 -> 1 call CONVPF ; Leistung Dezimal ausrechnen ; pop YH pop YL pop XH pop XL pop R21 pop R20 pop R17 pop R16 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: 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,8 ; Language 1: Post-Offset 8 RJMP LCDS15 LCDS12: ADIW ZL,8 ; Language 0: Pre-Offset 8 LDI XL,0 ; 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: 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 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 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,$80 ; Pull-Up 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 * 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 ; ; ++++ 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 ; ; ************************************ ; ******* 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 R20 PUSH R21 ; used by STSI! PUSH R22 PUSH R23 ; Get some work registers PUSH R24 PUSH XL PUSH XH IN R24,SREG ; Save Statusreg PUSH R24 ; ; ++ 400 us Service ; TIM40: rcall SETAV ; Set Attenuator Value ; rcall TUNE ; Tune VCO to target Frequency ; inctim TIK43,3,TIM401 ; Increment 400 us to 1,2 ms rcall DEBNCE ; Debounce Drehgeber every 1,2 ms ; TIM401: inctim TIK425,25,TIM402 ; Increment 400 us to 10 ms rcall DEBNC2 ; Schnelltaster Debounce alle 10 ms ; TIM402: inctim TIK450,50,TIM991 ; Increment 400 us to 20 ms rjmp TIM504 ; TIM991: rjmp TIM99 ; ; ++ 20 ms Service ; TIM504: sei ; Enable next Interrupt 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 ; 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 ; 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 60 set Timing Flag for Main inctim TIK300,5,TIM21 ; .. and increment 300 ms Timer up to 5 ; TIM21: inctim TIK20M,50,TIM992 ; 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 rjmp TIM30 ; TIM992: rjmp TIM99 ; TIM30: inctim TIK1S,60,TIM31 ; Increment 1 sec Timer ; ; ++ 1 min Service lds R24,AOWAIT ; Auto Off Timer 1 Minute weiterzählen inc R24 sts AOWAIT,R24 ; inctim TIKMIN,10,TIM99 ; Increment Minute Counter to 10 Minutes ; ; ++ Zur Zeit n*10' + 12" Batterie prüfen Flag setzen TIM31: lds R24,TIKMIN cpi R24,0 brne TIM39 lds R24,TIK1S cpi R24,12 brne TIM39 stsi BATTIM,1 TIM39: ; ; ++ 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 R20 POP R16 RETI ; Interrupt-Handling beendet ; ; ; ; ++++ Set Attenuator Value ; ; Setzt den Vergleicher für den Abschwächer-PWM abwechselnd ; auf ABSSET und ABSSET+1 SETAV: lds R23,TIK450 ; LSb toggelt alle 400 usec sbrs R23,0 lds R22,ABSSET ; Abwechselnd die beiden Werte holen sbrc R23,0 lds R22,ABSSET+1 com R22 out OCR0A,R22 ; Analogwert an PWM übergeben ret ; ; ++++ Tune VCO to Target Frequency ; ; Zaehlt für jeweils 100 msec die VCO Frequenz und erzeugt ; einen der Abweichung proportionalen Abstimmimpuls ; This Subroutine is called by the interrupt handler once per 400 us ; TUNE: PUSH R22 PUSH R23 ; Get some work registers PUSH R24 PUSH R25 ; lds R24,TIK100 ; Increment 400 usec Timer to 250 = 100 ms inc R24 sts TIK100,R24 cpi R24,250 ; up to 250 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 ; ; ++ 100 ms Service TUN50M: clr R24 sts TIK100,R24 ; clr R24 lds R22,TCNT1L ; Frequenzzähler auslesen lds R23,TCNT1H ; sts TCNT1H,R24 ; .. und wieder auf 0 setzen sts 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 ; 3 Stellen links rotieren rol R24 ; Ergibt (0..95) in MSB rol R25 clc rol R24 rol R25 clc rol R24 rol R25 clc ror R24 ; .. und 0..32 in LSB ror R24 ror R24 clc rol R25 ; MSB verdoppeln auf 0..190 (für 250 400 us slots) tst R25 ; Wenn MSB <> 0 breq TUN504 clr R24 ; Dann LSB auf 0 ; TUN504: sts TUNLEN,R25 ; Puls-Länge in Vielfachen von 400us 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 cpi R24,8 ; Wenn Kurzpuls > 8 brcs tun506 ; lsl R24 ; .. Länge verdoppeln ; TUN506: ldi R25,16 ; Inner Loop ist 3 cyc * 16 = 10 usec TUN507: dec R25 brne TUN507 ; Sie wird 1..31 * 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,2 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 ; .if TARGET == 0 ; **** Standard Rotary Encoder DEBINC: LDI R20,$1 RJMP DEB2 ; DEBDEC: LDI R20,$2 ; .elif TARGET == 1 ; **** Alternate Rotary Encoder ; DEBINC: LDS R20,SWICNT SBRS R20,0 RJMP DEBINC_0 STSI SWICNT,0 LDI R20,$1 RJMP DEB2 ; DEBINC_0: STSI SWICNT,$1 RJMP DEB3 DEBDEC: LDS R20,SWICNT SBRS R20,1 RJMP DEBDEC_0 STSI SWICNT,0 LDI R20,$2 RJMP DEB2 ; DEBDEC_0: STSI SWICNT,$2 RJMP DEB3 ; **** End Encoder Alternatives .endif ; 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,2 ms) ; DEB3: LDS R20,AOCYC ; Ausser wenn gerade Auto-Off-Versuch: TST R20 BRNE DEB6 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 DEB6 ; .. dann nix tun INC R20 ; .. sonst Counter hochzaehlen DEB39: STS DEBDD,R20 ; .. und retten ; ; ++ Mute Timer für V/R-Taster-Knacken dekrementieren DEB6: lds R20,VRMUTE ; Timer holen tst R20 ; .. und wenn grösser 0 breq DEB9 dec R20 ; .... dekrementieren sts VRMUTE,R20 sbi DDRC,4 ; .... und Mute einschalten ; DEB9: POP R20 RET ; ; **** Debounce Abschwächertaster (alle 10 ms) ; DEBNC2: PUSH R20 ; Used as Temp Register ; DEB4: LDS R20,DEBST ; Timer holen SBIC PINB,5 ; Wenn Bit (SU) nicht auf 0 rjmp DEB41 ; .. dann Taster offen ; ; Lang drücken handeln CPI R20,200 ; Counter schon am Limit (2 sec)? BREQ DEB8 ; dann nix tun INC R20 ; Counter hochzaehlen STS DEBST,R20 ; und retten CPI R20,200 ; Jetzt am Limit? BRNE DEB8 LDS R20,SWIFLG ; Dann Flag Lang setzen ORI R20,$40 ; STS SWIFLG,R20 ; rjmp DEB8 ; ; Kurz drücken handeln DEB41: cpi R20,5 ; War Taster 50 - 2000 ms gedrückt? brcs DEB42 cpi R20,200 breq DEB42 LDS R20,SWIFLG ; Dann Flag Kurz 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 (Locked) .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 ; ; ; ++++ Initialisierung EEPROM Abgleichbereich mit EEPCLR + MEMNUM EEPABG: .DB 0,0, 67,0,117,0,135,0 ; ABSTAB, 25 Werte hl .DB 146,0,150,0,154,0,158,0 .DB 161,0,164,0,167,0,170,0 .DB 172,0,175,0,178,0,181,0 .DB 185,0,189,0,193,0,197,0 .DB 201,0,205,0,211,0,223,0 .DB 226,0 .if TARGET == 0 .DB " Hallo " ; 8B RXNAM .elif TARGET == 1 .DB "RigExprt" ; 8B RXNAM .endif .DB 128+30,119,70,5+0 ; FFINE, UBFINE, UBWBIN, DISTCF .DB 0,0,3,9,9,9,9,9 ; SPAREF,SPRACH, AOTIM, 5*SPARE ; FFINE = +30 für 455 kHz ZF, -71 für 460 kHz ; ;++++ Initialisierung EEPROM Einstellungs-Speicherbereich 6x60B EEPMEM: .DB "Classic " ; 8B MEMNAM .DW 894,600,877,877 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 2,1,0,0,0,0,0,0,0,0,0,0 ; NFREQ, FREQX, 10B FRQ1X2 .DB 0,5,6,0,0,0,1,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 12,1,2,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM .DB "Sprint " .DW 410,660,900,1101 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 4,1,0,0,0,0,0,0,0,0,0,0 ; NFREQ, FREQX, 10B FRQ1X2 .DB 0,5,1,2,0,0,0,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 12,1,5,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM .DB "Foxoring" .DW 894,600,877,877 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 2,1,0,0,0,0,0,0,0,0,0,0 ; NFREQ, FREQX, 10B FRQ1X2 .DB 0,1,6,0,0,0,0,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 0,0,6,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM .DB "China " .DW 200,300,400,500 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 11,1,0,0,0,0,0,0,0,0,0,0; NFREQ, FREQX, 10B FRQ1X2 .DB 0,1,6,0,0,0,0,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 12,1,2,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM .DB "Extra 1 " .DW 894,600,877,877 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 2,1,0,0,0,0,0,0,0,0,0,0 ; NFREQ, FREQX, 10B FRQ1X2 .DB 0,5,6,0,0,0,1,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 12,1,2,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM .DB "Extra 2 " ; Extra2 = Abgleich .DW 800,000,1700,877 ; FRQ 1..4 (*100 Hz über 3,490 kHz) .DW 600,700,800,900,1000,1100,1200,1300 ; FRQ5..12 .DB 3,1,0,0,0,0,0,0,0,0,0,0 ; NFREQ, FREQX, 10B FRQ1X2 .DB 0,5,6,0,0,0,0,0 ; NFOX ze,TFOX ze, TFOXMS hz, TALARM ze .DB 16,0,0,9,9,9,9,9 ; PFOXBN, ASMMOD, NAHTON, 5xSPAREM ; ; ******************* ; **** 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 " = 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 "RX85 ",VERSHI,".",VERSLO .DB "........" .DB 1,2,3,4,5,6,7,8 .DB RXNAM,0,0,0,0,0,0,0 ; ; >12345678< EEPROM Ungültig STR00: .DB "EEPROM ?" .DB "A^=Reset" .DW 0 ; ; >12345678< Frequenz ändern + S-Meter anzeigen STR02: .DB "3...:. " .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,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 .DB "UhrStart" .DB "ClkStart" .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 .DB "Einstell" .DB "Setup- " .DW $1010 ; 1,2 .DB $7E," -men",$F5 .DB $7E," menu" .DW 0 ; ; >12345678< Frequenz ändern anbieten STR07: .DB "3...:. " .DW $1010 ; 1,2 .DB $7E," ",$E1,"ndern" .DB $7E," change" .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB 1,2,3,4,5,6,7,8 ; ; >12345678< Speicher umschalten STR08: .DW $1010 ; 1,2 .DB "Speicher" .DB "Memory " .DB "........" .DB 1,2,3,4,5,6,7,8 .DB MEMNAM,0,0,0,0,0,0,0 ; ; >12345678< Zahl Füchse einstellen STR10: .DW $1010 ; 1,2 .DB "N F",$F5,"chse" .DB "N Foxes " .DB " :. " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,NFOX,0,6,7,8 ; STR101: .DW $1010 ; 1,2 .DB "N F",$F5,"chse" .DB "N Foxes " .DB "Foxoring" .DW 0 ; ; >12345678< Zeit Füchse Sekunden einstellen STR11: .DW $1010 ; 1,2 .DB "T Fuchs " .DB "T Fox " .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: .DW $1010 ; 1,2 .DB "T Fuchs " .DB "T Fox " .DB ":.,>..12345678< Sendeleistung Füchse einstellen STR13: .DW $1010 ; 1,2 .DB "P Fu :.." .DB "PFox :.." .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' STR130: .DW $1010 ; 1,2 .DB "P Fuchs " .DB "P Fox " .DW $1010 ; 1,2 .DB "nur dB " .DB "dB only " .DW 0 ; ; >12345678< Zahl Frequenzen einstellen STR14: .DB "N Freq. " .DB " :. " .DB 1,2,3,4,5,6,7,8 .DB 1,2,3,NFREQV,0,6,7,8 ; ; >12345678< Sondermodus 12**A3 STR145: .DB "N Freq. " .DB "12 **A 3" .DW 0 ; ; >12345678< Sondermodus 1x2**A3 STR146: .DB "N Freq. " .DB "1x2 **A3" .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 .DB " Aus " .DB " Off " .DW 0 ; ; >12345678< Modus Akustisches S-Meter STR160: .DW $1010 ; 1,2 .DB "Akust.SM" .DB "AcoustSM" .DW $1010 ; 1,2 .DB " Aus " .DB " Off " .DW 0 ; ; >12345678< STR161: .DW $1010 ; 1,2 .DB "Akust.SM" .DB "AcoustSM" .DW $1010 ; 1,2 .DB "V/R-Lupe" .DB "F/B-Zoom" .DW 0 ; ; >12345678< STR162:.DW $1010 ; 1,2 .DB "Akust.SM" .DB "AcoustSM" .DW $1010 ; 1,2 .DB "Maximum " .DB "Maximum " .DW 0 ; ; >12345678< Annäherungs-Ton Entfernungsschwelle STR170: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DW $1010 ; 1,2 .DB " Aus " .DB " Off " .DW 0 ; STR171: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB "300m/50m" .DW 0 ; STR172: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB "200m/30m" .DW 0 ; STR173: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB "150m/20m" .DW 0 ; STR174: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB "100m/10m" .DW 0 ; STR175: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB " 50m/5m " .DW 0 ; STR176: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB " 30m/3m " .DW 0 ; STR177: .DW $1010 ; 1,2 .DB "Nah-Ton " .DB "NearTone" .DB " 20m/2m " .DW 0 ; ; >12345678< STR20: .DW $1010 ; 1,2 .DB "Sprache " .DB "Language" .DW $1010 ; 1,2 .DB "Deutsch " .DB "English " .DW 0 ; ; >12345678< STR21: .DB " EEPROM " .DB $7E," Reset " .DW 0 ; ; >12345678< UBat kalibrieren STR22: .DW $1010 ; 1,2 .DB "Abg UBat" .DB "Cal 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 .DB "AbgF ..." .DB "CalF ..." .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 .DB "Abg Absw" .DB "Cal Att." .DB $7E," Start " .DW 0 ; ; >12345678< Batterie-Warnschwelle einstellen STR25: .DB "BatAlarm" .DB "< .,. V " .DB 1,2,3,4,5,6,7,8 .DB 1,2,UBWARN,4,0,6,7,8 ; ; >12345678< Entfernung kalibrieren STR26: .DW $1010 ; 1,2 .DB "Abg Entf" .DB "Cal Dist" .DB " .. :.. " .DB 1,2,3,4,5,6,7,8 .DB 1,DCFVAL,0,4,DIST,0,0,8 ; ; >12345678< Auto Aus-Zeit einstellen STR27: .DW $1010 ; 1,2 .DB "Auto Aus" .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< STR28: .DW $1010 ; 1,2 .DB "Abgleich" .DB "Save Cal" .DW $1010 ; 1,2 .DB $7E,"Sichern" .DB $7E," Values" .DW 0 ; ; >12345678< STR2A0: .DW $1010 ; 1,2 .DB "Namen " .DB "Change " .DW $1010 ; 1,2 .DB $7E," ",$E1,"ndern" .DB $7E," Names" .DW 0 ; ; STR2A1: .DB "Start >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB RXNAM,0,0,0,0,0,0,0 ; STR2A2: .DB "Memo1 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; STR2A3: .DB "Memo2 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; STR2A4: .DB "Memo3 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; STR2A5: .DB "Memo4 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; STR2A6: .DB "Memo5 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; STR2A7: .DB "Memo6 >." .DB "........" .DB 1,2,3,4,5,6,7,EDTCHR .DB MEMNAM,0,0,0,0,0,0,0 ; ; >12345678< Ein Wert Abschwächer kalibrieren STRCAL: .DB ":.. :..",0 .DB " " .DB ABSVAL,0,0,4,ABSCHW,0,0,8 .DB UMESS,0,0,0,0,0,0,0 ; ; ** Die folgenden Strings sind Flash-Meldungen ; ; >12345678< Geänderte Daten in EEPROM schreiben STRSAV: .DB ">>EEPROM" .DB " " .DW 0 ; ; >12345678< Total-Reset incl. EEPROM STRTRE: .DB "<< Total" .DB "Reset >>" .DW 0 ; ; >12345678< Batteriespannung niedrig STRBAT: .DW $1010 ; 1,2 .DB "Batterie" .DB "Battery " .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 "3...:. " .DB ".:..:.,." .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,LOCKED .DB STOPW,1,0,0,UBATT,0,7,0 ; ; >12345678< Zurück aus Einstellungen STRBAK: .DB " :.." .DB "........" .DB 1,2,3,4,AUTOON,DIST,0,0 .DB MEMNAM,0,0,0,0,0,0,0 ; ; >12345678< Übersicht Zeiten, Leistung STROVW: .DB ".x:.,..s" .DB ":.,. .W " .DB NFOX+1,2,TFOXS,0,5,0,0,8 .DB PFOX,0,3,0,5,0,7,8 ; ; >12345678< Frequenznummer geändert (nur 1..4) STRFRQ: .DB "3..... " .DB " - F . -" .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB 1,2,3,4,5,FRQXV,7,8 ; ; >12345678< Frequenznummer geändert (>=5) STRFRX: .DB "3..... " .DB ".. " .DB 1,FRQ,0,0,FRQXSY,FRQ+3,7,8 .DB UMESS,0,0,0,0,0,0,0 ; ; >12345678< Abschwächer-Automatik aus STRAA0: .DW $1010 ; 1,2 .DB "Automa- " .DB "Auto-Att" .DW $1010 ; 1,2 .DB "tik AUS" .DB " OFF " .DW 0 ; ; >12345678< Abschwächerautomatik ein STRAA1: .DW $1010 ; 1,2 .DB "Automa- " .DB "Auto-Att" .DW $1010 ; 1,2 .DB "tik EIN" .DB " ON " .DW 0 ; ; >12345678< Sendezeit-Ende Alarm STRALA: .DW $1010 ; 1,2 .DB " Noch " .DB " Only " .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 ; SOUINV: .DB 1,1,20,1,20,1,20,20,20,1 ; Power-On-Fanfare bei ungültigem EEPROM .DB 20,20,20,1,20,1,20,1,1,0 ; SOUPOS: .DB 1,22,1,17,1,13,1,10,10,1,0,0 ; Power-On-Fanfare, Kurzversion ; 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 ; 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 SOUFX: .DB 1,24,18,12,9,6,1,0 ; Frequenz > 4 ; SOUOK: .DB 1,1,15,1,15,15,15,1,15,1,1,0 ; Ok ; SOUPIP: .DB 5,1,0,0 ; Piep 2 kHz SOUPAP: .DB 6,1,0,0 ; Piep 1,7 kHz ; SOUD1: .DB 80,1,0,0 ; Distanz-Indikator Stufe 1 SOUD2: .DB 80,1,80,1,0,0 ; Distanz-Indikator Stufe 2 SOUD3: .DB 80,1,80,1,80,1,0,0 ; Distanz-Indikator Stufe 3 ; ; ************************ ;******** This is the End..... *************************************** ; ************************ ;