;*********************************************************** ; PLL controller code ; ; Author Richard Hosking ; Dec 1999 ; Allows control of 2 VCOs (not on board) ; and drives 16X2 LCD display for operating freq ; and debugging info ; Key entry for mode and freq up/down ; EEPROM user programmable to setup PLL chip (MC145170) ; controller AVR AT90S1200 ; ;*********************************************************** .include "header.asm" .include "ppll_def.asm" ; ;****************************** ; Start of code ;**************** rjmp RESET ;*************** ; Subroutines ;**************** ;*************************************************************************** ;* ;* "BCD2bin24" - BCD to 24-Bit Binary Conversion ;* ;* This subroutine converts a 6-digit packed BCD number represented by ;* 3 bytes (BCDMSB:BCD2SB:BCDLSB) to a 24-bit number (mp10H:mp102:mp10L). ;* MSD of the 6-digit number must be placed in the lowermost nibble of BCDMSB. ;* ;* Let "abcdef" denote the 6-digit number. The conversion is done by ;* computing the formula: 10(10(10(10(10a+b)+c)+d)+e)+f. ;* The subroutine "mul10a"/"mul10b" does the multiply-and-add operation ;* which is repeated six times during the computation. ;* ;* Number of words :43 ;* Number of cycles : ;* Registers used :11 ;* ;*************************************************************************** ;***** "mul10a"/"mul10b" Subroutine Register Variables ;***** Code mul10a: ;***** multiplies "mp10H:mp10L" with 10 and adds "adder" high nibble swap adder mul10b: ;***** multiplies "mp10H:mp10L" with 10 and adds "adder" low nibble mov copyL,mp10L ;make copy mov copy2,mp102 mov copyH,mp10H lsl mp10L ;multiply original by 2 rol mp102 rol mp10H lsl copyL ;multiply copy by 2 rol copy2 rol copyH lsl copyL ;multiply copy by 2 (4) rol copy2 rol copyH lsl copyL ;multiply copy by 2 (8) rol copy2 rol copyH add mp10L,copyL ;add copy to original adc mp102,copy2 adc mp10H,copyH andi adder,0x0f ;mask away upper nibble of adder add mp10L,adder ;add lower nibble of adder brcc m10_1 ;if carry not cleared inc mp102 ; inc middle byte brcc m10_1 ; and high byte if relevant inc mp10H m10_1: ret ; ;****************** ; Main routine BCD2BIN ;****************** BCD2BIN: clr mp10H clr mp102 clr mp10L mov adder,BCDMSB rcall mul10a ; = 10a+b mov adder,BCDMSB rcall mul10b ; = 10(10a+b)+c mov adder,BCD2SB rcall mul10a ; = 10(10(10a+b)+c)+d mov adder,BCD2SB rcall mul10b ; = 10(10(10(10a+b)+c)+d)+e mov adder,BCDLSB rcall mul10a ; = 10(10(10(10(10a+b)+c)+d)+e)+f mov adder,BCDLSB rcall mul10b ; = 10(10(10(10(10(10a+b)+c)+d)+e)+f)+g ret ; ;*********************************** ; ; Display frequency data ; writes the 6 digit BCD number ; in BCDMSB,BCD2SB,BCDLSB ; 2 digits per byte to the LCD ; Uses temp, temp_2, Z pointer ; ;*********************************** DISPLAY_FREQ: ldi temp,0b00000010 ; Cursor home rcall COMMAND_DISPLAY rcall WAIT_2msec ldi temp,$20 ; Blank rcall DATA_DISPLAY ; ldi temp_2,3 ; Loop counter ldi r30,AtBCDMSB-1 ; Load ZL (pointer) with address of ; tBCDMSB (Most Sig Byte) + predecrement LOOP_DD: inc r30 ld temp,Z ; MSByte of BCD data swap temp andi temp,0b00001111 ; Mask off upper 4 bits sbr temp,$30 ; Add hex 30 to give ASCII cpi temp_2,3 ; Blank leading zero brne NOT_BLANK cpi temp,$30 ; ? zero brne NOT_BLANK ldi temp,$20 ; Blank NOT_BLANK: rcall DATA_DISPLAY ld temp,Z ; get next digit andi temp,0b00001111 sbr temp,$30 rcall DATA_DISPLAY dec temp_2 brne LOOP_DD ; Repeat till all digits done ; ret ;************************************************ ; ; Write command/data to display ; command/data word in temp ; built in 50 usec delay ; uses temp_1 and T bit in SREG ; ;************************************************ DATA_DISPLAY: set ; Uses bit T in SREG to rjmp CONT_DISPLAY ; store bit for data/command COMMAND_DISPLAY: clt ; data/command bit low CONT_DISPLAY: mov temp_1,temp ; Copy data to temp_1 andi temp,0b11110000 ; mask off lower 4 bits sbr temp,OE ; OE bit high bld temp,2 ; get data/command bit T from SREG out PORTB,temp ; write upper 4 bits to display nop ; wait 1 usec total command nop ; Stabilize line cbi PORTB,3 ; OE low to clock in data ; swap temp_1 ; get lower 4 bits andi temp_1,0b11110000 ; mask off lower 4 bits sbr temp_1,OE ; OE high bld temp_1,2 ; get data/command bit T from SREG out PORTB,temp_1 ;write lower 4 bits to LCD ; nop ; nop ; cbi PORTB,3 ; OE low to clock in data ; ldi Delay,100 ; Wait about 50 usec D4: dec Delay brne D4 ; ret ; return ; ;********************************************* ; Write data to PLL chip ; command register 8 clocks ; reference divider 15 or 24 clocks ; main divider 16 clocks ; clock count in temp ; MSB in temp_1 ; LSB in temp_2 ; clock bit0 Port D ; enable bit1 Port D ; data bit 7 Por D ;************************************************ ; DATA_TO_PLL: cbi PORTB,pll_clock ; (do not write to enable with clock high) cbi PORTB,pll_enable; Clear enable to allow data to PLL ; PLL_LOOP: lsl temp_2 ; Shift least sig byte to carry rol temp_1 ; Shift data through carry brcs PLL_DATA_SET ; and write to PLL cbi PORTB,pll_data rjmp PLL_DATA_CLEAR PLL_DATA_SET: sbi PORTB,pll_data PLL_DATA_CLEAR: sbi PORTB,pll_clock ; and clock data to PLL cbi PORTB,pll_clock dec temp ; repeat till finished brne PLL_LOOP ; sbi PORTB,pll_enable; Restart PLL ret ;************************************************* ; Read data from EEPROM ; EEPROM address in temp ; Number of bytes in temp_1 ; Destination register in r30 (Z) ;************************************************** EEPROM_READ: out EEAR,temp EELOOP21: sbi EECR,EERE ; Set read bit EELOOP22: sbic EECR,EERE ; Wait till hardware finished rjmp EELOOP22 ; (read bit cleared by hardware) in temp,EEDR ; data from EEPROM st Z,temp ; save data inc r30 in temp,EEAR ; next byte increment EEAR inc temp ; (EEPROM address reg) out EEAR,temp dec temp_1 ; loop counter brne EELOOP21 ; repeat till bytes done ret ; ;************************************************* ; Write data to EEPROM ; EEPROM address in temp ; Number of bytes in temp_1 ; Source register in r30 (Z) ; Uses temp_2 ;************************************************** EEPROM_WRITE: out EEAR,temp ; address register EELOOP1: ld temp_2,Z out EEDR,temp_2 ; data to EEPROM sbi EECR,EEWE ; Set write bit EELOOP2: sbic EECR,EEWE ; Wait till hardware finished rjmp EELOOP2 ; (write bit cleared by hardware) inc r30 in temp,EEAR ; next byte increment EEAR inc temp ; (EEPROM address reg) out EEAR,temp dec temp_1 ; loop counter brne EELOOP1 ; ret ; ;****************************************** ; ; GET_KEYS subroutine ; Wait till key is pressed (D0 to D4 low) ; return status in temp ; approx 200 msec debounce delay ; Delay uses temp_1(delay1) and temp_2(delay2) ; routine waits until key is pressed ; ;******************************************* GET_KEYS: GKLOOP1: in temp,PIND ; test TX_RX andi temp,0b00010000 ; Compare with current mov temp_1,ppll_flags ; situation andi temp_1,0b00010000 ; If changed, then return cp temp,temp_1 brne GKTXRX ; and change status of TX_RX flag in temp,PIND ; test all switches except TX_RX andi temp,0b00001111 ; Return if any pressed cpi temp,0b00001111 breq GKLOOP1 ; Otherwise keep polling keys ; in temp,PIND ; Return key status in temp andi temp,0b00001111 ;**************************************** ; Delay to allow time for keypress ;**************************************** ldi temp_4,75 ; 150 msec delay GKLOOP2: rcall WAIT_2msec dec temp_4 brne GKLOOP2 ret ; GKTXRX: bst temp,TX_RX ; save bit in flags bld ppll_flags,TX_RX ; ret ; ;****************************************** ; Delay 2 msec with a 4MHz clock ;****************************************** WAIT_2msec: ldi Delay1,$0B D24002: ldi Delay2,$FF D24001: dec Delay2 brne D24001 dec Delay1 brne D24002 ret ; ;*************************** ; Start of main code ;************************** RESET: ldi temp,0b11111111 out DDRB,temp ; PORTB = all outputs cbi PORTB,pll_clock ;(do not write to enable with clock high) sbi PORTB,pll_enable ; ldi temp,0b11100000 ; PORTD = inputs bits 0-4 bits 5,6 outputs out DDRD,temp ; ;************************************************************************* ; Display setup ; Port B bit 3 OE Enable - clocks on neg transition ; 2 RS Register Select ; command=0, data=1 ; bits 4-7 data 4 bits, high nibble first ; ASCII format ; RW grounded (write) ; Note that commands take up to 1.6 msec for display to implement ; at a nominal display clock rate of 250 KHz ; Display initialize routine after power up ; ;************************************************************************ ; ldi temp,50 ; Wait at least 15msec after D1: ; powerup before writing rcall WAIT_2msec ; to display dec temp brne D1 ldi temp,0b00111000 ; System set out PORTB,temp cbi PORTB,3 ; OE low to clock in data ; rcall WAIT_2msec ; Wait 4 msec rcall WAIT_2msec ; ldi temp,0b00111000 ; System set out PORTB,temp cbi PORTB,3 ; OE low to clock in data ; rcall WAIT_2msec ; wait at least 100usec ; ldi temp,0b00111000 ;System set out PORTB,temp cbi PORTB,3 ; OE low to clock in data ; rcall WAIT_2msec ; Wait at least 40usec (2 msec) ; ldi temp,0b00101000 ; Function set ; 4 bit mode, 2 lines 5X7 pixels rcall COMMAND_DISPLAY ;write to display ; ldi temp,0b00001000 ;Display off, cursor off ; blink off rcall COMMAND_DISPLAY ; ldi temp,0b00000001 ; Display clear rcall COMMAND_DISPLAY rcall WAIT_2msec ; Need to wait 1.6 msec after clear ; ldi temp,0b00000110 ; Entry mode set ; Increment RAM, dont shift display rcall COMMAND_DISPLAY ; ldi temp,0b00001100 ; Display on, cursor/blink off rcall COMMAND_DISPLAY ; ;********************************************************************** ; Data entry routine ; Allows entry of: code ; reference freq 1 ; reference divider ratio 2 ; max main divider ratio TX 3 ; min main divider ratio TX 4 ; IF offset mode 1 5 ; IF offset mode 2 6 ; IF offset mode 3 7 ; IF offset mode 4 8 ; Start freq 9 ; ;********************************************************************** ; in temp,PIND ; Check keys at startup andi temp,0b00001111 cpi temp,0b00000011 ; If mode/enter keys pressed breq DATA_ENTRY ; then enter data entry routine rjmp MAIN ; Otherwise go to main program ; DATA_ENTRY: ldi temp,$01 ; Clear display rcall COMMAND_DISPLAY rcall WAIT_2msec ldi loop_counter,1 DATA_ENTRY_LOOP: clr BCDMSB ; Clear registers clr BCD2SB ; clr BCDLSB ; ; ldi temp,$C4 ; Cursor to 44 rcall COMMAND_DISPLAY ldi temp,$30 ; Display loop counter add temp,loop_counter rcall DATA_DISPLAY ; for coding of data entry ; ;******************************* ; Write the current entered data ; and get the required BCD data ;******************************** clr offset_count ; Digit counter ldi temp,$0F ; Cursor on, flashing on rcall COMMAND_DISPLAY REFJUMP1: rcall WAIT_2msec rcall DISPLAY_FREQ ; Display current digits ; ldi temp,$81 ; Set cursor add temp,offset_count ; Adjust to current digit rcall COMMAND_DISPLAY ; rcall GET_KEYS ; wait for keypress sbrs temp,0 ; If enter pressed rjmp REFJUMP2 ; then advance to next digit ; ;****************** ; Set up pointer ;***************** ldi temp_2,AtBCDMSB mov temp_1,offset_count ; Adjust pointer ror temp_1 ; divide by 2 add temp_2,temp_1 ; (2 digits per byte) mov r30,temp_2 ; ld temp,Z sbrs offset_count,0 ; If a "high" digit swap temp ; add 1 to the high nibble inc temp mov temp_1,temp andi temp_1,$0F ; mask off high nibble cpi temp_1,$0A ; ? >9 brlo REFJUMP3 ; If yes nibble to 0 andi temp,$F0 REFJUMP3: sbrs offset_count,0 ; If it was a high nibble swap temp ; then restore st Z,temp rjmp REFJUMP1 ; go to write freq to display ; REFJUMP2: inc offset_count ; Advance to next digit cpi offset_count,6 ; If last digit then end routine breq REFEND rjmp REFJUMP1 ; repeat ; REFEND: ; rcall BCD2BIN ; Convert to binary data ; mov temp,loop_counter ; EEPROM address lsl temp ; multiply by 2 ldi temp_1,2 ; Byte counter 2 ldi r30,Atmp102 ; Source register address rcall EEPROM_WRITE ; Write to EEPROM inc loop_counter ; Continue cpi loop_counter,10 breq MAIN ; until all data entered rjmp DATA_ENTRY_LOOP ; MAIN: ; ldi temp,8 ; Write to control register clr temp_2 ; POL N,DiffPD,LD disabled,refout disabled ; FV AND FR disabled ldi temp_1,0b00000000 rcall DATA_TO_PLL ; ldi temp,4 ; EEPROM address ldi temp_1,2 ; Byte counter ldi r30,Atmp102 ; Address of destination register ; rcall EEPROM_READ ; Get reference divider data ldi temp,15 ; Counter for PLL loop, mov temp_1,mp102 ; mov temp_2,mp10L lsl temp_2 ; Preshift by 1 bit rol temp_1 rcall DATA_TO_PLL ; ldi temp,18 ; EEPROM address for initial freq ldi temp_1,2 ; Byte counter ldi r30,AtdivideMSBTX ; Address of destination register rcall EEPROM_READ ; ldi ppll_flags,0b00010000 ; Initialize flags ; Mode I1, memory 0, receive ;************************* ; Main loop ;************************* MAIN_LOOP: ; ldi temp,$01 ; Clear display rcall COMMAND_DISPLAY rcall WAIT_2msec ldi temp,$0C ; Cursor off rcall COMMAND_DISPLAY ldi temp,$C4 ; Cursor to 44 rcall COMMAND_DISPLAY ; ldi temp_4,8 ; mov temp_3,ppll_flags debug_loop: ; ldi temp,$30 ; sbrc temp_3,7 ; inc temp ; lsl temp_3 ; rcall DATA_DISPLAY ; ; dec temp_4 ; brne debug_loop ; ;************************************************************ ; Calculate correct ratio to PLL ;************************************************************* ldi temp,$4D ; Write "M (no) memory channel rcall DATA_DISPLAY ; Bottom line mov temp_2,ppll_flags swap temp_2 lsr temp_2 ; Get memory channel no from flags andi temp_2,0b00000111 ldi temp,$30 ; Convert number to ASCII add temp,temp_2 ; and display rcall DATA_DISPLAY ldi temp,$20 ; Space rcall DATA_DISPLAY ; Bottom line ; mov temp,ppll_flags ; Check for memory mode andi temp,0b00000100 cpi temp,0b00000100 ; If so then go to memory module breq MEM_MODE ldi temp,$49 ; Write "I"(IF offset mode ?) rcall DATA_DISPLAY ; Bottom line mov temp,ppll_flags ; Check other mode status andi temp,0b00000011 cpi temp,0 ; If mode 1 breq MODE_1 ; etc cpi temp,1 breq MODE_2 cpi temp,2 breq MODE_3 cpi temp,3 ; breq MODE_4 MODE_1: ldi temp,$31 ; Write "1" rcall DATA_DISPLAY ldi temp,10 ; EEPROM address of I1 offset rjmp GET_OFFSET MODE_2: ldi temp,$32 rcall DATA_DISPLAY ldi temp,12 ; EEPROM address of I2 offset rjmp GET_OFFSET MODE_3: ldi temp,$33 rcall DATA_DISPLAY ldi temp,14 ; EEPROM address of I3 offset rjmp GET_OFFSET MODE_4: ldi temp,$34 rcall DATA_DISPLAY ldi temp,16 ; EEPROM address of I4 offset rjmp GET_OFFSET MEM_MODE: ldi temp,$4D ; Write "ME" rcall DATA_DISPLAY ; Bottom line ldi temp,$45 ; rcall DATA_DISPLAY ; lsl temp_2 ; Multiply by 4 for EEPROM address lsl temp_2 ldi temp,32 ; and add 32 add temp,temp_2 ldi temp_1,2 ; Byte counter ldi r30,AtdivideMSBTX ; Address of destination register ; in this case main divider rcall EEPROM_READ ; bst ppll_flags,TX_RX ; Save transmit/receive status ldi temp_1,1 ; Byte counter ldi r30,Atppll_flags ; Address of destination register ; in this case flags rcall EEPROM_READ ; sbr ppll_flags,4 ; restore bit 2 in flags (memory) bld ppll_flags,TX_RX ; restore transmit/receive status mov temp_1,ppll_flags ; Get EEPROM address of offset andi temp_1,0b00000011 ; Mask off other bits lsl temp_1 ; Multiply by 2 ldi temp,10 ; add to give EEPROM address add temp,temp_1 ; of offsets GET_OFFSET: ldi temp_1,2 ; Byte counter ldi r30,AtoffsetMSB ; Address of destination register rcall EEPROM_READ ; mov temp_1,divideMSBTX ; Write new data to PLL mov temp_2,divideLSBTX sbrs ppll_flags,TX_RX ; Check transmit/receive status rjmp PLL ; If transmit skip offsets add temp_2,offsetLSB ; If receive then add offsets adc temp_1,offsetMSB PLL: ldi temp,16 rcall DATA_TO_PLL ; ;***************************** ; Calculate displayed frequency ; by multiplying reference by ratio ; and converting to BCD for display ;********************************** ldi temp,2 ; EEPROM address of reference freq ldi temp_1,1 ; Byte counter ldi r30,Atmp16uH ; Address of destination register ; in this case mc16uH,mc16uL rcall EEPROM_READ ; Get reference frequency ; ldi temp,3 ; EEPROM address of reference freq ldi temp_1,1 ; Byte counter ldi r30,Atmp16uL ; Address of destination register ; in this case mc16uH,mc16uL rcall EEPROM_READ ; Get reference frequency mov mc16uH,divideMSBTX ; current PLL freq to multiplier mov mc16uL,divideLSBTX ; routine ;*************************************************************************** ;* ;* "mpy16u" - 16x16 Bit Unsigned Multiplication ;* ;* This subroutine multiplies the two 16-bit register variables ;* mp16uH:mp16uL and mc16uH:mc16uL. ;* The result is placed in m16u3:m16u2:m16u1:m16u0. ;* ;* Number of words :14 + return ;* Number of cycles :153 + return ;* Low registers used :None ;* High registers used :7 (mp16uL,mp16uH,mc16uL/m16u0,mc16uH/m16u1,m16u2, ;* m16u3,mcnt16u) ;* ;*************************************************************************** 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 m16u1 ;rotate result byte 1 and multiplier High ror m16u0 ;rotate result byte 0 and multiplier Low dec mcnt16u ;decrement loop counter brne m16u_1 ;if not done, loop more ; mov temp_LSB,m16u0 ; Move to registers for Binary mov temp_2SB,m16u1 ; to BCD routine mov temp_MSB,m16u2 ;*************************************************************************** ;* ;* "bin2BCD24" - 24-bit Binary to BCD conversion ;* ;* This subroutine converts a 24-bit binary number (tempMSB:temp2SB:tempLSB) to a 6-digit ;* packed BCD number represented by 3 bytes (BCDMSB:BCD2SB:BCDLSB). ;* MSD of the 6-digit number is placed in the uppermost nibble of BCDMSB. ;* Note that there is a max 65536 times 4 (ie 18 bit limit) ;* ;*************************************************************************** ; bin2BCD24: ldi cnt16a,24 ; Init loop counter clr BCDMSB clr BCD2SB clr BCDLSB bBCDx_1: lsl temp_LSB ;shift input value rol temp_2SB rol temp_MSB ;through all bytes brcc bBCDx_4 ; Restore count sbr temp_LSB,01 ; to count registers rjmp bBCDx_5 bBCDx_4: cbr temp_LSB,01 bBCDx_5: rol BCDLSB ; rol BCD2SB rol BCDMSB dec cnt16a ;decrement loop counter brne bBCDx_2 ;if counter not zero rjmp B2BCD_END ; return bBCDx_2: ldi r30,AtBCDMSB-1 ;Z points to result MSB - 1 bBCDx_3: inc r30 ; Increment pointer to next digit ld tmp16a,Z ; Get digit value subi tmp16a,-$03 ;add 0x03 sbrc tmp16a,3 ;if bit 3 not clear st Z,tmp16a ; store back ld tmp16a,Z ;get (Z) subi tmp16a,-$30 ;add 0x30 sbrc tmp16a,7 ;if bit 7 not clear st Z,tmp16a ; store back cpi r30,AtBCDLSB ;done all digits? brne bBCDx_3 ;loop again if not rjmp bBCDx_1 B2BCD_END: ; ;********************************************************* ; Display frequency ;******************************************************** ; ldi temp,$82 ; Cursor to 02 rcall COMMAND_DISPLAY rcall DISPLAY_FREQ ; Write current freq to display ldi temp,$20 rcall DATA_DISPLAY ; KHz ldi temp,$4B rcall DATA_DISPLAY ldi temp,$48 rcall DATA_DISPLAY ldi temp,$7A rcall DATA_DISPLAY ; ;******************************************************************** ; Poll keys for any change ;********************************************************************* rcall GET_KEYS ; Poll keys cpi temp,0b00001110 ; If up key pressed then increment breq UP_FREQ cpi temp,0b00001101 ; If down key pressed then decrement breq DOWN_FREQ cpi temp,0b00001011 ; If mode key pressed then breq SCROLL_MODE ; Move to next mode cpi temp,0b00000111 ; If memory key pressed then breq MEMORY_ENTER ; Add to memeory rjmp TESTFINISH ; If error then repeat ;*************************** ; Up freq or memory locaton ;*************************** UP_FREQ: mov temp,ppll_flags ; get mode data andi temp,0b00000111 ; Mask all but mode bits sbrc temp,2 ; ?memory mode rjmp INC_MEMORY ; ldi temp,6 ; EEPROM address of Max ratio M+ ldi temp_1,2 ; Byte counter ldi r30,25 ; Address of destination register ; rcall EEPROM_READ ; Get data cp divideLSBTX,r26 ; If limit reached brne INCREMENT ; then dont increment cp divideMSBTX,r25 breq END_INC INCREMENT: inc divideLSBTX ; Otherwise increment ratio cpi divideLSBTX,0 brne TESTFINISH inc divideMSBTX rjmp TESTFINISH ; INC_MEMORY: ldi temp,0b00100000 add ppll_flags,temp ; next memory laocation END_INC: rjmp TESTFINISH ; ;***************************** ; Down freq or memory location ;***************************** DOWN_FREQ: mov temp,ppll_flags ; get mode data andi temp,0b00000111 ; Mask all but mode bits sbrc temp,2 ; ?memory mode rjmp DEC_MEMORY ; If so then next memory location ; ldi temp,8 ; EEPROM address of Min ratio M- ldi temp_1,2 ; Byte counter ldi r30,25 ; Address of destination register ; rcall EEPROM_READ ; Get data cp divideLSBTX,r26 ; If limit reached brne DECREMENT ; then dont decrement cp divideMSBTX,r25 breq TESTFINISH DECREMENT: dec divideLSBTX ; Otherwise decrement ratio cpi divideLSBTX,$FF brne TESTFINISH dec divideMSBTX rjmp TESTFINISH DEC_MEMORY: ldi temp,0b00100000 sub ppll_flags,temp ; next memory laocation rjmp TESTFINISH ; ;************************* ; Move to next mode ;******************* SCROLL_MODE: sbrc ppll_flags,2 ; If already memory mode rjmp RESET_FLAGS inc ppll_flags ; Next mode rjmp TESTFINISH RESET_FLAGS: cbr ppll_flags,$07 rjmp TESTFINISH ; ;**************************** ; Enter new memory data ;*************************** MEMORY_ENTER: sbrc ppll_flags,2 ; If memory mode already rjmp TESTFINISH ; Then bypass ldi temp,250 ; 500 msec delay MEMLOOP1: rcall WAIT_2msec ; Wait total of 1 sec dec temp brne MEMLOOP1 ldi temp,250 ; 500 msec delay MEMLOOP2: rcall WAIT_2msec dec temp brne MEMLOOP2 in temp,PIND ; test memory switch again sbrc temp,3 ; If still pressed then add rjmp TESTFINISH ; Otherwise bypass mov temp,ppll_flags ; calculate address in EEPROM andi temp,0b11100000 swap temp ; memory address 4 bytes per location lsl temp ldi temp_1,32 ; starting at location 32 add temp,temp_1 ldi temp_1,2 ; Byte counter 2 ldi r30,AtdivideMSBTX ; Source register address rcall EEPROM_WRITE ; Write to EEPROM ; ldi temp_1,1 ; Byte counter 1 ldi r30,Atppll_flags ; Save flags rcall EEPROM_WRITE ; Note that temp has next address ; rjmp INC_MEMORY ; Shift to next memory address ;***************************** ; Repeat main loop ;**************************** TESTFINISH: sbrc ppll_flags,TX_RX ; Check transmit/receive status rjmp RECEIVE ; If receive then set/clear bits cbi PORTD,6 ; Receive off sbi PORTD,5 ; Set transmit bit in PORTD rjmp MAIN_LOOP RECEIVE: cbi PORTD,5 ; Transmit off sbi PORTD,6 ; Set receive bit in PORTD rjmp MAIN_LOOP