;*************************************************************************** ; version date change by ; ------ --------- --------------------------------------------------- ---- ; 1.0 22/12/97 first version. JPD ; tx: 1241.250 MHz ; rx: 1295.250 MHz ; shift: 54 MHz ; 2.0 14/08/98 no boot when changing jumpers, and implemented ; 4 freqs incl. the reversed JPD ;*************************************************************************** ;*************************************************************************** ; The VCO-frequency Fvco is determined as follows: ; ; 3.2 MHz ; Fvco = Fr*N = ------- * 8 * n ; 512 ; ; where Fr the reference frequency which is equal to the crystal frequency ; devided by 512, and N the total division. The SDA3302 devides by 8 fixed ; also, so n equals the values to program the device with. ; ; When 3.2 MHz crystal frequency is used the reference frequency gets ; Fr = 3200 kHz / 512 = 6.25 kHz and the final raster equals ; 8 * Fr = 50 kHz. ;*************************************************************************** DSEG ORG 0008H ByteCnt: DS 1 Xmit: DS 8 PrevP1: DS 1 BSEG NoAck: DBIT 1 SCLPin EQU P1.6 ; I2C serial clock line. SDAPin EQU P1.7 ; I2C serial data line. CSEG ORG 0000H LJMP Start ORG 0100H Start: MOV SP,#40H MOV PrevP1,#0C0H Loop: MOV A,P1 ; get P1 in A ANL A,#03CH ; leave only relevant bits MOV R1,A ; save A in R1 XRL A,PrevP1 ; any difference with previous P1? JNZ M1 ; branch if so MOV PrevP1,R1 ; else, update previous SJMP Loop M1: MOV PrevP1,R1 ; update previous MOV A,R1 ; 4 bits of P1 in A MOV DPTR,#FreqTbl1 ; get start of tbl1 JB ACC.5,M2 ; or if reversed, MOV DPTR,#FreqTbl2 ; get start of tbl2 M2: CPL A ; invert logic ANL A,#0CH ; now leave only freqbits RR A ; shift to match tbl MOV R1,A ; save A in R1 MOVC A,@A+DPTR ; get freq INC DPTR ; point to 2nd byte MOV Xmit,A ; store 1st byte MOV A,R1 ; restore A MOVC A,@A+DPTR ; get 2nd byte MOV Xmit+1,A ; store it too ACALL SetFreq ; and program ppll SJMP Loop FreqTbl1: DB 060H,0F9H ; 1241.250 DB 060H,0FCH ; 1241.400 DB 061H,000H ; 1241.600 DB 061H,004H ; 1241.800 FreqTbl2: DB 065H,031H ; 1295.250 DB 065H,034H ; 1295.400 DB 065H,038H ; 1295.600 DB 065H,03CH ; 1295.800 SetFreq: MOV A,#0C0H MOV R0,#Xmit MOV ByteCnt,#2 ACALL SendData RET ;**************************************************************************** ; I2C-stuff ;**************************************************************************** BitDly: NOP NOP ;NOPs to delay 5 microseconds (minus 4 RET ;machine cycles for CALL and RET). SCLHigh: SETB SCLPin ;Set SCL from our end. JNB SCLPin,$ ;Wait for pin to actually go high. RET SendStart: CLR SDAPin ;Begin I2C Start. ACALL BitDly CLR SCLPin ACALL BitDly ;Complete I2C Start. CLR NoAck RET SendStop: CLR SDAPin ;Get SDA ready for stop. ACALL SCLHigh ;Set clock for stop. ACALL BitDly SETB SDAPin ;Send I2C stop. ACALL BitDly RET ;Bus should now be released. ; SendByte - sends one byte of data to an I2C slave device. ; Input A = data byte to be sent. ; Affected: A, R2 SendByte: MOV R2,#8 ;Set bit count. SBLoop: RLC A ;Send one data bit. MOV SDAPin,C ;Put data bit on pin. ACALL SCLHigh ;Send clock. ACALL BitDly CLR SCLPin ACALL BitDly DJNZ R2,SBloop ;Repeat until all bits sent. SETB SDAPin ;Release data line for acknowledge. ACALL SCLHigh ;Send clock for acknowledge. ACALL BitDly JNB SDAPin,SBEX ;Check for valid acknowledge bit. SETB NoAck ;Set status for no acknowledge. SBEX: CLR SCLPin ;Finish acknowledge bit. ACALL BitDly RET ; RcvByte - receives one byte of data from an I2C slave device. ; Output: A = data byte received ; Affected: A, R2 RcvByte: MOV R2,#8 ;Set bit count. RBLoop: ACALL SCLHigh ;Read one data bit. ACALL BitDly MOV C,SDAPin ;Get data bit from pin. RLC A ;Rotate bit into result byte. CLR SCLPin ACALL BitDly DJNZ R2,RBLoop ;Repeat until all bits received. PUSH ACC ;Save accumulator MOV A,ByteCnt CJNE A,#1,RBAck ;Check for last byte of frame. SETB SDAPin ;Send no acknowledge on last byte. SJMP RBAClk RBAck: CLR SDAPin ;Send acknowledge bit. RBAClk: ACALL SCLHigh ;Send acknowledge clock. POP ACC ;Restore accumulator ACALL BitDly CLR SCLPin SETB SDAPin ;Clear acknowledge bit. ACALL BitDly RET ; SendData - sends one or more bytes of data to an I2C slave device. ; Input: ByteCnt = count of bytes to be sent. ; A = slave address. ; @R0 = data to be sent (the first data byte will be the ; subaddress, if the I2C device expects one). ; Affected: A, R0, R2 SendData: ACALL SendStart ACALL SendByte ;Send slave-address JB NoAck,SDEX ;Check for slave not responding SDLoop: MOV A,@R0 ;Get data byte from buffer. ACALL SendByte ;Send next data byte. INC R0 ;Advance buffer pointer. JB NoAck,SDEX ;Check for slave not responding. DJNZ ByteCnt,SDLoop ;All bytes sent? SDEX: ACALL SendStop ;Done, send an I2C stop. RET ; RcvData - receives one or more bytes of data from an I2C slave device. ; Input: ByteCnt = count of bytes to be sent. ; A = slave address. ; Output: @R0 = data received. ; Affected: A, R0, R2 ; ; Note: to receive with a subaddress, use SendData to set the subaddress ; first (no provision for repeated Start). RcvData: INC A ;Set for READ of slave. ACALL SendStart ;Acquire bus and send slave address. ACALL SendByte JB NoAck,RDEX ;Check for slave not responding RDLoop: ACALL RcvByte ;Receive next data byte. MOV @R0,A ;Save data byte in buffer. INC R0 ;Advance buffer pointer. DJNZ ByteCnt,RDLoop ;Repeat untill all bytes received. RDEX: ACALL SendStop ;Done, send an I2C stop. RET END