;---------------------------------------------------------------------- ; ; ; Program: mixer_lo.asm ; ; Function: programs the PLL for the 2.5GHz fixed LO in ; the mixer module of the RF generator ; ; Author: Herbert Dingfelder, DL5NEG ; ; Hardware: AT90S1200 with RCEN-Bit set to enable ; (runs on internal RC-Osc. without crystal) ; PLL IC is a National Semiconductor LMX2320 ; ; Historie: - Based on complete_beacon.asm from 21.02.2001 ; - CW call-sign sending taken out of the code ; - 17.10.2001 comments tranlated in to english ; - 18.10.2001 continue comments translation and ; major cleanup ; - 19.10.2001 final test in simulator ; ;---------------------------------------------------------------------- ; Functionality of this software: ; At power-on the software waits for a moment to make sure that the ; supply voltage at the PLL is stable. Then it sends the programing ; bits that sets the PLL (LMX2320) to 2.500 GHz (Rref=13MHz). The ; programing is done via the (software emulated) 3wirebus interface. ; After the job is done the processor is put into sleep mode to reduce ; the current consumption and the interference to a minimum. ; Note: Remember that the EEPROM data must be loaded to the processor ; separately. (A .epp file is created by the assembler. This must be ; also be sent to the traget with the programer.) ; Note: AVR Studio shows a warning when this code is assembled. This ; warning is not justified! It warns that there is a odd number of ; values in the .db command. Since this .db is in the .cseg (EEPROM) ; part of the code this is absolutely ok. The EEPROM is organized ; in single bytes so there is no need to have an even number of values ; per .db command. ;**** Includes **** .include "1200def.inc" ; Hardware is a AT90S1200 ;**** Definitions (names for used registers) **** .def EEdat = r0 .def EEadr = r16 .def dummy = r17 .def data = r18 .def len = r19 .def pa = r20 .def temp = r21 ;**** Aliases for better code readability **** .equ PLL_BUS = PORTB ; Bits 0-2 of Port B are used as .equ PLL_BUS_DIR = DDRB ; data, clock, enable lines for the ; 3wirebus interface .equ DATA = 0 ; these are the lines on the 3wire-bus .equ CLK = 1 ; to the PLL and the corresponding bits .equ LE = 2 ; on port B ;**** All code from here on is for the program memory (the flash) **** .CSEG ;+++++++++++++++++++++++++ Main program +++++++++++++++++++++++++++++++ ldi temp, 0b00000111 ; set Bit 0-2 of the PLL-BUS as output out PLL_BUS_DIR, temp ; (they form the 3wirebus to the PLL) ldi pa, 7 ; wait for 7*66ms=462ms to make sure that rcall pause ; the supply voltage at the PLL is stable rcall prog_pll ; program the PLL rcall cpu_sleep ; put the CPU into sleep mode end: ; endless loop (just in case the CPU rjmp end ; wakes up for some reason) ;------------------------- EEread -------------------------------------- ; Fetches one byte from the EEPROM. The register EEadr is used as a ; pointer and contains the address in the EEPROM that shall be read. ; The read value is stored in the register EEdat. This routine can ; be generally used whenever one byte shall be read from the EEPROM. EEread: sbic EECR, EEWE ; wait until the EEPROM is ready to respond rjmp EEread out EEAR, EEadr ; put the address that shall be read into ; the EEPROM address register sbi EECR, EERE ; set the EEPROM read-strobe in EEdat, EEDR ; read the data value ret ; return to the main program ;-------------------------- pause -------------------------------------------- ; Waits for certain time, depending on the register pa. One value in pa ; refers to one overflow of the 8-Bit timer with a prescaler of 256. ; => t= (1/fq) * 256 * 256 with fq = crystal frequency ; Since the hardware in this case is a AT90S1200 running on the internal ; RC oscillator, fq is 1MHz (roundabout, the RC osc. is not that stable) ; -> t = 66ms * pa pause: ldi temp, 0b00000100 ; set the prescaler to 256 out tccr0, temp in temp, tifr ; reset the overflow bit of the counter sbr temp, exp2(tov0) out tifr, temp clr temp ; reset the counter out tcnt0, temp cwait: in temp, tifr ; when tcnt0 produces an overflow, tov0 will be set sbrs temp, tov0 ; -> this loop runs until that overflow occurs rjmp cwait dec pa ; now the timer has produced an overflow, brne pause ; count down the register pa and run the counter ; again until pa is down to zero ret ; return to the main program ;------------------------- CPU sleep ----------------------------------- ; puts the CPU into sleep mode (including shutoff of the XCO) cpu_sleep: in dummy, MCUCR ; read the current control register setting sbr dummy, exp2(SE) ; sleepmode enable (not yet switched on) sbr dummy, exp2(SM) ; select 'power down' as sleepmodus out MCUCR, dummy ; write back the control register sleep ; switch on the sleepmode ; (sleep is obviously ignored in the simulator ; but in practice is works just fine ret ; return (the CPU should not make it to this ; point, just in case it wakes up for some ; reason) ;-------------------------- Prog PLL------------------------------------ ; programs the PLL with the datas that are stored in the EEPROM prog_pll: ldi EEadr, PLLDATA ; load pointer with the first EEPROM address prog_word_loop_start: rcall EEread ; read the EEPROM data from the address ; that is pointed to by the pointer sbrc EEdat,1 ; jump to end of this loop if rjmp prog_word_end ; bit 1 in the read value is set, i.e. ; if it was the end-mark (which is 2 or 6) out PLL_BUS, EEdat ; output the data on PLL_BUS, (bit 0) sbi PLL_BUS, CLK ; set CLOCK bit on the PLL_BUS (clock high) cbi PLL_BUS, CLK ; reset CLOCK bit on the PLL_BUS (clock low again) inc EEadr ; set the pointer to the next address rjmp prog_word_loop_start ; go to loop start for the next bit prog_word_end: sbi PLL_BUS, LE ; set LOADENABEL bit on PLL_BUS (load enable high) cbi PLL_BUS, LE ; reset LOADENABLE bit on PLL_BUS (load enable low) inc EEadr ; put the pointer to the next bit (which would be the ; first bit of the next program word, provided there is ; another word) sbrs EEdat, 2 ; if bit 2 was set in the latest EEPROM value then rjmp prog_word_loop_start ; this was the last program word and we will not jump ; upwards, otherwise we do for the next word ret ; return to the main program ; ----- and here are the datas for the PLL that will be stored in the EEPROM -------- ; These are the datas for the PLL. For each bit that shall be send to the PLL ; we use one byte (set to 0 or 1). As a mark for the end of a complete programm ; word we use the value 2, i.e. whenever we want the strobe line on the 3wirebus ; (also called LE for load enable) to go high, we put a 2 in the EEPROM data string. ; If we want to mark the end of all data in the EEPROM we use a 6 instead of a 2. ;**** All code from here on is for the EEPROM **** .ESEG PLLDATA: .db 1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,2 ; Ref. 1MHz at 13MHz fq .db 0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,6 ; 2500 MHz at 250kHz Ref.