;$title (AD9887 control Routines for 89C2051) ;$date (06/13/2003) ;$mod51 ;$debug ;**************************************************************************** ; Definitions ;**************************************************************************** ;I2C Addresses of AD9887 ; Data storage locations BitCnt DATA 40h ;Bit counter for I2C routines. ByteCnt DATA 41h ;Byte counter for I2C routines. SlvAdr DATA 42h ;Slave address for I2C routines. delay1 data 43h delay2 data 44h ch_num data 45h Binaddr data 46h BCDaddr data 47h Bytes data 48h IOstatus0 data 49h IOstatus1 data 4ah IOstatus2 data 4bh disp_bit_cnt data 4ch reg_num data 4dh reg_data data 4eh Delay_cnt data 4fh XmtDat DATA 30h ;I2C transmit buffer, 8 bytes max. RcvDat DATA 38h ;I2C receive buffer, 8 bytes max. Flags DATA 20h ;Location for bit flags NoAck BIT Flags.0 ;I2C no acknowledge flag. BusFault BIT Flags.1 ;I2C bus fault flag. I2CBusy BIT Flags.2 ;I2C busy flag. Multi_reg BIT Flags.3 max_bit BIT Flags.4 min_bit BIT Flags.5 key_push data 21h pointer_1 data 22h pointer_2 data 23h H_width data 24h Int_cnt data 25h Ent_cnt data 26h Nxt_cnt data 27h Pre_cnt data 28h max_data data 29h min_data data 2ah adj_step data 2bh ;50h to 53h reserved for Bin data ;54h to 58h reserved for BCD data ;60h to 63h is the sum ;6ah to 6dh is the adder ; I2C connections. RSLCD equ p1.3 ELCD equ p1.2 SCLPin BIT p1.1 ;I2C serial clock line. SDAPin BIT p1.0 ;I2C serial data line. Pre bit p3.7 Ent bit p3.5 Nxt bit p3.4 ;**************************************************************************** ; Reset and Interrupt Vectors ;**************************************************************************** ORG 0 JMP Reset ORG 0BH JMP TIMER0_INT ;**************************************************************************** ORG 10h ;**************************************************************************** ; Main Program ;**************************************************************************** Reset: lcall initial_cpu lcall Initial_LCD lcall Init_9887 ; lcall Read_9887_RAM lcall Set_PHY mov ch_num,#0 Key_scan_procedure: ;The following prog is for key scanning ; lcall Detec_V ; lcall Detec_V ; mov a,#100 ; lcall Delay_10ms ; ; lcall VCO_RNG ; ; mov a,#100 ; lcall Delay_10ms jnb Pre,Pre_key jnb Ent,Ent_key jnb Nxt,Nxt_key sjmp Key_scan_procedure Pre_key: jnb Pre,Pre_key lcall Disp_Pre sjmp Key_scan_procedure Ent_key: jnb Ent,Ent_key lcall Disp_Ent sjmp Key_scan_procedure Nxt_key: jnb Nxt,Nxt_key lcall Disp_Nxt sjmp Key_scan_procedure Disp_Pre: mov a,reg_num push acc clr max_bit jb min_bit,Exit_Pre mov a,reg_data clr c subb a,adj_step mov 50h,a cjne a,min_data,Dec_value setb min_bit sjmp Noml_dec ;a equal to min value Dec_value: jnc Noml_dec ;a less than minmum value mov a,min_data Noml_dec: mov reg_data,a lcall Write_9887 jnb Multi_reg,Exit_Pre inc reg_num lcall Write_9887 inc reg_num lcall Write_9887 Exit_Pre: pop acc mov reg_num,a ;******************************* mov r0,Ent_cnt PLL_dec:cjne r0,#1,PHY_dec mov Bytes,#2 mov 51h,#53h mov a,50h swap a mov 50h,a sjmp Disp_dec PHY_dec:cjne r0,#2,BRT_dec mov Bytes,#1 mov 51h,#00 mov a,50h rr a rr a rr a mov 50h,a sjmp Disp_dec BRT_dec:cjne r0,#3,CST_dec mov Bytes,#1 mov 51h,#00 mov a,50h rr a mov 50h,a sjmp Disp_dec CST_dec:cjne r0,#4,Disp_dec mov Bytes,#1 mov 51h,#00 sjmp Disp_dec ;****************************** Disp_dec: lcall Bin2BCD mov r2,#0c4h lcall write_lcd_reg mov r2,55h lcall Disp_BCD mov r2,54h lcall Disp_BCD ret Disp_Ent: djnz Ent_cnt,Start_adj mov Ent_cnt,#4 Start_adj: mov a,Ent_cnt PLL_adj:cjne a,#1,PHY_adj ljmp Set_PLL PHY_adj:cjne a,#2,BRT_adj ljmp Set_PHY BRT_adj:cjne a,#3,CST_adj ljmp Set_BRT CST_adj:cjne a,#4,RST_cnt ljmp Set_CST RST_cnt:mov Ent_cnt,#4 Set_PLL: clr Multi_reg mov reg_num,#02h lcall Read_9887 mov adj_step,#10h mov max_data,#0f0h mov min_data,#00h mov a,reg_data swap a mov 50h,a mov 51h,#53h lcall Bin2BCD lcall Clrscr mov r2,#80h lcall write_lcd_reg mov r2,#'P' lcall write_lcd_data mov r2,#'L' lcall write_lcd_data mov r2,#'L' lcall write_lcd_data mov r2,#0c4h lcall write_lcd_reg mov r2,55h lcall Disp_BCD mov r2,54h lcall Disp_BCD ljmp Exit_ENT Set_PHY: clr Multi_reg mov reg_num,#04h lcall Read_9887 mov adj_step,#08h mov max_data,#0f8h mov min_data,#00h mov a,reg_data rr a rr a rr a mov 50h,a mov Bytes,#1 lcall Bin2BCD lcall Clrscr mov r2,#80h lcall write_lcd_reg mov r2,#'P' lcall write_lcd_data mov r2,#'H' lcall write_lcd_data mov r2,#'Y' lcall write_lcd_data mov r2,#0c4h lcall write_lcd_reg mov r2,54h lcall Disp_BCD ljmp Exit_ENT Set_BRT: setb Multi_reg mov reg_num,#0bh lcall Read_9887 mov adj_step,#02h mov max_data,#0feh mov min_data,#00h mov a,reg_data rr a mov 50h,a mov Bytes,#1 lcall Bin2BCD lcall Clrscr mov r2,#80h lcall write_lcd_reg mov r2,#'B' lcall write_lcd_data mov r2,#'R' lcall write_lcd_data mov r2,#'T' lcall write_lcd_data mov r2,#0c4h lcall write_lcd_reg mov r2,55h lcall Disp_BCD mov r2,54h lcall Disp_BCD ljmp Exit_ENT Set_CST: setb Multi_reg mov reg_num,#08h lcall Read_9887 mov adj_step,#01h mov max_data,#0ffh mov min_data,#00h mov a,reg_data mov 50h,a mov Bytes,#1 lcall Bin2BCD lcall Clrscr mov r2,#80h lcall write_lcd_reg mov r2,#'C' lcall write_lcd_data mov r2,#'S' lcall write_lcd_data mov r2,#'T' lcall write_lcd_data mov r2,#0c4h lcall write_lcd_reg mov r2,55h lcall Disp_BCD mov r2,54h lcall Disp_BCD ljmp Exit_ENT Exit_ENT: ret Disp_Nxt: mov a,reg_num push acc clr min_bit jb max_bit,Exit_Nxt mov a,reg_data add a,adj_step mov 50h,a cjne a,max_data,Inc_value setb max_bit sjmp Noml_inc Inc_value: jc Noml_inc ;a larger than maxmium value mov a,max_data Noml_inc: mov reg_data,a lcall Write_9887 jnb Multi_reg,Exit_Nxt inc reg_num lcall Write_9887 inc reg_num lcall Write_9887 Exit_Nxt: pop acc mov reg_num,a ;******************************* mov r0,Ent_cnt PLL_inc:cjne r0,#1,PHY_inc mov Bytes,#2 mov 51h,#53h mov a,50h swap a mov 50h,a sjmp Disp_inc PHY_inc:cjne r0,#2,BRT_inc mov Bytes,#1 mov 51h,#00 mov a,50h rr a rr a rr a mov 50h,a sjmp Disp_inc BRT_inc:cjne r0,#3,CST_inc mov Bytes,#1 mov 51h,#00 mov a,50h rr a mov 50h,a sjmp Disp_inc CST_inc:cjne r0,#4,Disp_inc mov Bytes,#1 mov 51h,#00 sjmp Disp_inc ;****************************** Disp_inc: lcall Bin2BCD mov r2,#0c4h lcall write_lcd_reg mov r2,55h lcall Disp_BCD mov r2,54h lcall Disp_BCD ret ;******************************* Disp_hex: mov a,r2 anl a,#0fh mov r5,a mov a,r2 swap a anl a,#0fh mov dptr,#Char_tbl movc a,@a+dptr mov r2,a lcall write_lcd_data mov a,r5 movc a,@a+dptr mov r2,a lcall write_lcd_data ret ;******************************* Disp_BCD: mov a,r2 push acc swap a anl a,#0fh add a,#30h mov r2,a lcall Write_LCD_data pop acc anl a,#0fh add a,#30h mov r2,a lcall Write_LCD_data ret ;******************************** ; Subroutines ;**************************************************************************** ; BitDly - insures minimum high and low clock times on I2C bus. ; This routine must be tuned for the actual oscilator frequency used, shown ; here tuned for a 12MHz clock. Note that the CALL instruction that invokes ; BitDly already uses 2 machine cycles. ; BitDly: NOP ;NOPs to delay 5 microseconds (minus 4 ;machine cycles for CALL and RET). RET ;**************************************************************************** ; SCLHigh - sends SCL pin high and waits for any clock stretching peripherals. ; SCLHigh: SETB SCLPin ;Set SCL from our end. JNB SCLPin,$ ;Wait for pin to actually go high. RET ;************************************************* Release_I2C: clr I2CBusy setb SDAPin nop setb SCLPin nop ret ;************************************************* ; SendStop - sends an I2C stop, releasing the bus. ; SendStop: CLR SDAPin ;Get SDA ready for stop. lcall SCLHigh ;Set clock for stop. lcall BitDly SETB SDAPin ;Send I2C stop. lcall BitDly CLR I2CBusy ;Clear I2C busy status. RET ;Bus should now be released. ;********************************************************* ; SendByte - sends one byte of data to an I2C slave device. ; Enter with: ; ACC = data byte to be sent. ; SendByte: MOV BitCnt,#8 ;Set bit count. SBLoop: RLC A ;Send one data bit. MOV SDAPin,C ;Put data bit on pin. lcall SCLHigh ;Send clock. lcall BitDly CLR SCLPin lcall BitDly DJNZ BitCnt,SBloop ;Repeat until all bits sent. SETB SDAPin ;Release data line for acknowledge. lcall SCLHigh ;Send clock for acknowledge. lcall BitDly JNB SDAPin,SBEX ;Check for valid acknowledge bit. SETB NoAck ;Set status for no acknowledge. SBEX: CLR SCLPin ;Finish acknowledge bit. lcall BitDly RET ;************************************************ ; GoMaster - sends an I2C start and slave address. ; Enter with: ; SlvAdr = slave address. ; GoMaster: ; SETB I2CBusy ;Indicate that I2C frame is in progress. CLR NoAck ;Clear error status flags. CLR BusFault ; JNB SCLPin,Fault ;Check for bus clear. ; JNB SDAPin,Fault CLR SDAPin ;Begin I2C start. lcall BitDly CLR SCLPin lcall BitDly ;Complete I2C start. MOV A,SlvAdr ;Get slave address. lcall SendByte ;Send slave address. RET Fault: SETB BusFault ;Set fault status RET ; and exit. ;****************************************************************** ; SendData - sends one or more bytes of data to an I2C slave device. ; Enter with: ; ByteCnt = count of bytes to be sent. ; SlvAdr = slave address. ; @R0 = data to be sent (the first data byte will be the ; subaddress, if the I2C device expects one). ; SendData: lcall GoMaster ;Acquire bus and send slave address. JB NoAck,SDEX ;Check for slave not responding. SDLoop: MOV A,@R0 ;Get data byte from buffer. lcall 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: lcall SendStop ;Done, send an I2C stop. RET ;************************************************************ ;RcvByte - receives one byte of data from an I2C slave device. ; Returns: ; ACC = data byte received. ; RcvByte: MOV BitCnt,#8 ;Set bit count. RBLoop: lcall SCLHigh ;Read one data bit. lcall BitDly MOV C,SDAPin ;Get data bit from pin. RLC A ;Rotate bit into result byte. CLR SCLPin lcall BitDly DJNZ BitCnt,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: lcall SCLHigh ;Send acknowledge clock. POP ACC ;Restore accumulator lcall BitDly CLR SCLPin SETB SDAPin ;Clear acknowledge bit. lcall BitDly RET ;*************************************************************************** ;RcvData - receives sends one or more bytes of data from an I2C slave device. ; Enter with: ; ByteCnt = count of bytes to be sent. ; SlvAdr = slave address. ; Returns: ; @R0 = data received. ; Note: to receive with a subaddress, use SendData to set the subaddress ; first (no provision for repeated start). ; RcvData: INC SlvAdr ;Set for READ of slave. lcall GoMaster ;Acquire bus and send slave address. JB NoAck,RDEX ;Check for slave not responding. RDLoop: lcall RcvByte ;Recieve 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: lcall SendStop ;Done, send an I2C stop. RET ;****************************** Detec_V: mov reg_num,#15h lcall Read_9887 mov a,reg_data anl a,#01000000b rr a rr a rr a mov r6,a mov reg_num,#0eh lcall Read_9887 mov a,reg_data xrl a,r6 cpl acc.3 mov reg_num,#0eh mov reg_data,a lcall Write_9887 ret ;****************************** ;Entry --> reg_num ;Return --> reg_data ; Read_9887: mov SlvAdr,#9eh lcall GoMaster mov a,reg_num lcall SendByte lcall Release_I2C mov SlvAdr,#9fh lcall GoMaster lcall RcvByte mov reg_data,a lcall SendStop ; mov a,#2 ; lcall Delay_10ms ret ;****************************** ;Entry --> reg_num ;Entry --> reg_data ; Write_9887: mov SlvAdr,#9eh lcall GoMaster mov a,reg_num lcall SendByte mov a,reg_data lcall SendByte lcall SendStop ; mov a,#2 ; lcall Delay_10ms ret ;****************************** ;No entry/No return ; Initial_cpu: MOV TMOD,#00010001B MOV IE,#10000010B MOV TCON,#00000101B MOV TH0,#00h MOV TL0,#00h SETB TR0 mov PSW,#00 mov p3,#0ffh mov p1,#0ffh mov Int_cnt,#20 mov Ent_cnt,#4 mov Binaddr,#50h mov BCDaddr,#54h mov Bytes,#2 mov Flags,#0 ret ; ;****************************** TIMER0_INT: PUSH ACC ; clr tr0 ; mov TH0,#00h ; mov TL0,#00h djnz Int_cnt,Check_VCO lcall Detec_V mov Int_cnt,#20 sjmp Exit_Timer0 Check_VCO: mov a,Int_cnt cjne a,#10,Exit_Timer0 lcall VCO_RNG Exit_Timer0: ; setb tr0 POP ACC RETI ;****************************** VCO_RNG: mov H_width,#00 mov reg_num,#15h lcall Read_9887 mov a,reg_data jb acc.7,H_posi H_neg: jb p3.2,H_neg H_neg_low: jnb p3.2,H_neg_low H_neg_high: inc H_width jb p3.2,H_neg_high sjmp Set_VCO_RNG H_posi: jnb p3.2,H_posi H_posi_high: jb p3.2,H_posi_high H_posi_low: inc H_width jnb p3.2,H_posi_low Set_VCO_RNG: mov a,H_width clr c cjne a,#4,NE_4 sjmp LT_4 NE_4: jnc GT_4 LT_4: mov reg_num,#03h mov reg_data,#0d4h lcall Write_9887 sjmp Exit_VCO_RNG GT_4: clr c cjne a,#8,NE_8 sjmp LT_8 NE_8: jnc GT_8 LT_8: mov reg_num,#03h mov reg_data,#0b4h lcall Write_9887 sjmp Exit_VCO_RNG GT_8: clr c cjne a,#12,NE_12 sjmp LT_12 NE_12: jnc GT_12 LT_12: mov reg_num,#03h mov reg_data,#94h lcall Write_9887 sjmp Exit_VCO_RNG GT_12: Exit_VCO_RNG: ret ;****************************** Init_9887: ;reg 1 is PLL divide ratio MSB mov reg_num,#01h mov reg_data,#53h lcall Write_9887 ;reg 2 is PLL divide ratio LSB mov reg_num,#02h mov reg_data,#0f0h lcall Write_9887 ;reg 3 is clock generator control mov reg_num,#03h mov reg_data,#0B8h lcall Write_9887 ;reg 4 is clock phase adjust mov reg_num,#04h mov reg_data,#40h lcall Write_9887 ;reg 5 is clamp timing mov reg_num,#05h mov reg_data,#01h lcall Write_9887 ;reg 6 is clamp duration mov reg_num,#06h mov reg_data,#01h lcall Write_9887 ;reg 7 is Hsync width mov reg_num,#07h mov reg_data,#20h lcall Write_9887 ;reg 8 is Red gain mov reg_num,#08h mov reg_data,#60h lcall Write_9887 ;reg 9 is Green gain mov reg_num,#09h mov reg_data,#60h lcall Write_9887 ;reg a is Blue gain mov reg_num,#0ah mov reg_data,#60h lcall Write_9887 ;reg b is Red offset mov reg_num,#0bh mov reg_data,#60h lcall Write_9887 ;reg c is Green offset mov reg_num,#0ch mov reg_data,#60h lcall Write_9887 ;reg d is Blue offset mov reg_num,#0dh mov reg_data,#60h lcall Write_9887 ;reg e is Blue gain mov reg_num,#0eh mov reg_data,#0f8h lcall Write_9887 ;reg f is multi control mov reg_num,#0fh mov reg_data,#0d0h lcall Write_9887 ;reg 10 is mode control 2 mov reg_num,#10h mov reg_data,#34h lcall Write_9887 ;reg 11 is mode control 2 mov reg_num,#11h mov reg_data,#00h lcall Write_9887 ;reg 12 is mode control 2 mov reg_num,#12h mov reg_data,#0a9h lcall Write_9887 ret ;****************************** Read_9887_RAM: mov reg_num,#0 mov r0,#70h Read_9887_ram_next: lcall Read_9887 mov @r0,reg_data inc reg_num inc r0 mov a,#20h cjne a,reg_num,Read_9887_ram_next ret ;****************************** ;Entry: ACC ;Return:null ; ;Delay for Acc X 10 ms ; Delay_10ms: mov delay1,#03 delay_cnt1: mov delay2,#0 delay_cnt2: nop nop djnz delay2,delay_cnt2 djnz delay1,delay_cnt1 djnz acc,Delay_10ms ret ;******************************** ;Delay10Us ; Delay_us: djnz acc,delay_us ret ;******************************** ;LCD driver ; INITIAL_LCD: clr RSLCD mov a,p1 anl a,#00001111b orl a,#00110000b mov p1,a MOV A,#20 LCALL DELAY_US setb ELCD MOV A,#20 LCALL DELAY_US clr ELCD MOV A,#6 LCALL DELAY_10ms mov a,p1 anl a,#00001111b orl a,#00110000b mov p1,a MOV A,#20 LCALL DELAY_US setb ELCD MOV A,#20 LCALL DELAY_US clr ELCD MOV A,#128 LCALL DELAY_US mov a,p1 anl a,#00001111b orl a,#00110000b mov p1,a MOV A,#20 LCALL DELAY_US setb ELCD MOV A,#20 LCALL DELAY_US clr ELCD MOV A,#40 LCALL DELAY_US mov a,p1 anl a,#00001111b orl a,#00100000b mov p1,a MOV A,#20 LCALL DELAY_US setb ELCD MOV A,#20 LCALL DELAY_US clr ELCD MOV A,#40 LCALL DELAY_US MOV r2,#28H ;Cursor,Shift LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS MOV r2,#06H ;Cursor,Shift LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS MOV r2,#0CH ;Display Control LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS MOV r2,#14H ;Cursor move,Right LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS Clrscr: MOV r2,#02H ;Reset LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS MOV r2,#01H ;Clear display LCALL WRITE_LCD_REG MOV A,#01 LCALL DELAY_10MS RET WRITE_LCD_REG: clr ELCD clr RSLCD mov a,r2 anl a,#0f0h mov r3,a mov a,r2 swap a anl a,#0f0h mov r4,a mov a,p1 anl a,#0fh orl a,r3 mov p1,a MOV A,#200 LCALL DELAY_US setb ELCD MOV A,#200 LCALL DELAY_US clr ELCD MOV A,#200 LCALL DELAY_US mov a,p1 anl a,#0fh orl a,r4 mov p1,a MOV A,#200 LCALL DELAY_US setb ELCD MOV A,#200 lcall DELAY_US clr ELCD MOV A,#200 LCALL DELAY_US RET WRITE_LCD_DATA: clr ELCD setb RSLCD mov a,r2 anl a,#0f0h mov r3,a mov a,r2 swap a anl a,#0f0h mov r4,a mov a,p1 anl a,#0fh orl a,r3 mov p1,a MOV A,#100 LCALL DELAY_US setb ELCD MOV A,#100 LCALL DELAY_US clr ELCD MOV A,#200 LCALL DELAY_US mov a,p1 anl a,#0fh orl a,r4 mov p1,a MOV A,#100 LCALL DELAY_US setb ELCD MOV A,#200 lcall DELAY_US clr ELCD MOV A,#100 LCALL DELAY_US RET ;***************************** Read_I2C: mov R0,#38 ;RAM address mov ByteCnt,#1 lcall RcvData ret ;************************************************** ;***** BINARY TO BCD ***** ;Binaddr --> LSB ... MSB ;BCDaddr --> LSB ... MSB ;Bytes Bin2BCD: mov r1,BCDaddr mov r2,Bytes inc r2 clr a bb0: mov @r1,a inc r1 djnz r2,bb0 mov a,Bytes mov b,#8 mul ab mov r3,a bb3: mov r0,Binaddr mov r2,Bytes clr c bb1: mov a,@r0 rlc a mov @r0,a inc r0 djnz r2,bb1 mov r2,Bytes inc r2 mov r1,BCDaddr bb2: mov a,@r1 addc a,@r1 da a mov @r1,a inc r1 djnz r2,bb2 djnz r3,bb3 ret char_tbl: db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' END