;
;
;	FRAME BUFFER INIT PROGRAM FOR SAA9051, TDA 4680 AND TDA 8444
;	87C751 CPU SENDS I2C INIT DATA AFTER 1 SEC. POWER UP DELAY.
;
;
;
;	FRAME10.ASM	03/30/90 CHANGE DATA FIRST SHIP OF BOARD
;			FOR TDA4680 V4X. NTSC MATRIX 1.0 VPP OUTPUT
;      
;
;	FRAME03.ASM	03/09/90 CHANGE COMMENT ; FOR DMSD DATA
;       FRAME02.ASM     03/09/89 HERB KNIESS
;	FRAME01.ASM	12/04/89 HERB KNIESS
;	I2CINIT.ASM	11/16/89 GREG GOODHUE
;
;
;
;
;*****************************************************************************
;
;
;
;            I2C Peripheral Initialization Program for the 83C751
;
; This program first provides both a positive and negative going reset pulse 
; on two port pins to allow any system devices requiring a reset pulse to be 
; initialized. Then, the program will send out one or more I2C messages (from 
; a table) to allow I2C devices to be initialized with specific data. 
;
;
;
;*****************************************************************************
;
$TITLE(FRAME10.ASM  FRAME BUFFER BOARD DMSD2B INIT PROGRAM)
$DATE(03/30/90)
$MOD751
$DEBUG
;
;
; Value definitions.
;
CTVAL      EQU     02h                 ;CT1, CT0 bit values for I2C.
;
;
; Masks for I2CFG bits.
;
BTIR       EQU     10h                 ;Mask for TIRUN bit.
BMRQ       EQU     40h                 ;Mask for MASTRQ bit.
;
;
; Masks for I2CON bits.
;
BCXA       EQU     80h                 ;Mask for CXA bit.
BIDLE      EQU     40h                 ;Mask for IDLE bit.
BCDR       EQU     20h                 ;Mask for CDR bit.
BCARL      EQU     10h                 ;Mask for CARL bit.
BCSTR      EQU     08h                 ;Mask for CSTR bit.
BCSTP      EQU     04h                 ;Mask for CSTP bit.
BXSTR      EQU     02h                 ;Mask for XSTR bit.
BXSTP      EQU     01h                 ;Mask for XSTP bit.
;
;
; RAM locations used by I2C routines.
;
BitCnt     DATA    21h                 ;I2C bit counter.
ByteCnt    DATA    22h
SlvAdr     DATA    23h                 ;Address of active slave.
SubAdr     DATA    24h
;
CmdSav     DATA    25h                 ;Saves last command byte.
PtrSav     DATA    26h                 ;Saves starting index for last command.
StackSave  DATA    27h                 ;Saves stack address for bus recovery.
;
Flags      DATA    20h                 ;I2C software status flags.
NoAck      BIT     Flags.0             ;Indicates missing acknowledge.
Fault      BIT     Flags.1             ;Indicates a bus fault of some kind.
Retry      BIT     Flags.2             ;Indicates that last I2C transmission
;                                      ;  failed and should be repeated.
;
SCL        BIT     P0.0                ;Port bit for I2C serial clock line.
SDA        BIT     P0.1                ;Port bit for I2C serial data line.
;
PosRst     BIT     P3.4                ;Port pin for positive reset pulse.
NegRst     BIT     P3.3                ;Port pin for negative reset pulse.
;
;*****************************************************************************
;                                Begin Code
;*****************************************************************************
;
; Reset and interrupt vectors.
;
           AJMP    Reset               ;Reset vector at address 0.
;
;
; A timer I timeout usually indicates a 'hung' bus.
;
           ORG     1Bh                 ;Timer I (I2C timeout) interrupt.
TimerI:    SETB    CLRTI               ;Clear timer I interrupt.
           CLR     TIRUN
           ACALL   ClrInt              ;Clear interrupt pending.
           MOV     SP,StackSave        ;Restore stack for return to main.
           AJMP    Recover             ;Attempt bus recovery.
ClrInt:    RETI
;
;
;*****************************************************************************
;                    Main Transmit and Receive Routines
;*****************************************************************************
;
; Send data byte(s) to slave.
;   Enter with slave address in SlvAdr, data in XmtDat buffer, # of data 
;   bytes to send in ByteCnt.
;
SendData:  CLR     NoAck               ;Clear error flags.
           CLR     Fault
           CLR     Retry
           MOV     StackSave,SP        ;Save stack address for bus fault.
           MOV     A,SlvAdr            ;Get slave address.
           ACALL   SendAddr            ;Get bus and send slave address.
           JB      NoAck,SDEX          ;Check for missing acknowledge.
           JB      Fault,SDatErr       ;Check for bus fault.
;
SDLoop:    ACALL   GetNext             ;Get next data byte for slave.
           ACALL   XmitByte            ;Send data to slave.
           JB      NoAck,SDEX          ;Check for missing acknowledge.
           JB      Fault,SDatErr       ;Check for bus fault.
           DJNZ    ByteCnt,SDLoop
;
SDEX:      ACALL   SendStop            ;Send an I2C stop.
           RET
;
;
; Handle a transmit bus fault.
;
SDatErr:   AJMP    Recover             ;Attempt bus recovery.
;
;
;*****************************************************************************
;                               Subroutines
;*****************************************************************************
;
; Send address byte.
;   Enter with address in ACC.
;
SendAddr:  MOV     I2CFG,#BMRQ+BTIR+CTVAL ;Request I2C bus.
           JNB     ATN,$               ;Wait for bus granted.
           JNB     Master,SAErr        ;Should have become the bus master.
           MOV     I2DAT,A             ;Send first bit, clears DRDY.
           MOV     I2CON,#BCARL+BCSTR+BCSTP ;Clear start, releases SCL.
           ACALL   XmitAddr            ;Finish sending address.
           RET
;
SAErr:     SETB    Fault               ;Return bus fault status.
           RET
;
;
; Byte transmit routine.
;   Enter with data in ACC.
;   XmitByte : transmits 8 bits.
;   XmitAddr : transmits 7 bits (for address only).
;
XmitAddr:  MOV     BitCnt,#8           ;Set 7 bits of address count.
           SJMP    XmBit2
;
XmitByte:  MOV     BitCnt,#8           ;Set 8 bits of data count.
XmBit:     MOV     I2DAT,A             ;Send this bit.
XmBit2:    RL      A                   ;Get next bit.
           JNB     ATN,$               ;Wait for bit sent.
           JNB     DRDY,XMErr          ;Should be data ready.
           DJNZ    BitCnt,XmBit        ;Repeat until all bits sent.
           MOV     I2CON,#BCDR+BCXA    ;Switch to receive mode.
           JNB     ATN,$               ;Wait for acknowledge bit.
           JNB     RDAT,XMBX           ;Was there an ack?
           SETB    NoAck               ;Return no acknowledge status.
XMBX:      RET
;
XMErr:     SETB    Fault               ;Return bus fault status.
           RET
;
;
; I2C stop routine.
;
SendStop:  CLR     MASTRQ              ;Release bus mastership.
           MOV     I2CON,#BCDR+BXSTP   ;Generate a bus stop.
           JNB     ATN,$               ;Wait for atn.
           MOV     I2CON,#BCDR         ;Clear data ready.
           JNB     ATN,$               ;Wait for stop sent.
           MOV     I2CON,#BCARL+BCSTP+BCXA ;Clear I2C bus.
           CLR     TIRUN               ;Stop timer I.
           RET
;
;
; Bus fault recovery routine.
;
Recover:   ACALL   FixBus              ;See if bus is dead or can be 'fixed'.
           JC      BusReset            ;If not 'fixed', try extreme measures.
           SETB    Retry               ;If bus OK, return to main routine.
           CLR     Fault
           CLR     NoAck
           SETB    CLRTI
           SETB    TIRUN               ;Enable timer I.
           SETB    ETI                 ;Turn on timer I interrupts.
           RET
;
; This routine tries a more extreme method of bus recovery.
;   This is used if SCL or SDA are stuck and cannot otherwise be freed.
;   (will return to the Recover routine when Timer I times out)
;
BusReset:  CLR     MASTRQ              ;Release bus.
           MOV     I2CON,#0BCh         ;Clear all I2C flags.
           SETB    TIRUN
           SJMP    $                   ;Wait for timer I timeout (this will
;                                      ;  reset the I2C hardware).
;
;
; This routine attempts to regain control of the I2C bus after a bus fault.
;   Returns carry clear if successful, carry set if failed.
;
FixBus:    CLR     MastRQ              ;Turn off I2C functions.
           SETB    C
           SETB    SCL                 ;Insure I/O port is not locking I2C.
           SETB    SDA
           JNB     SCL,FixBusEx        ;If SCL is low, bus cannot be 'fixed'.
           JB      SDA,RStop           ;If SCL & SDA are high, force a stop.
           MOV     BitCnt,#9           ;Set max # of tries to clear bus.
ChekLoop:  CLR     SCL                 ;Force an I2C clock.
           ACALL   SDelay
           JB      SDA,RStop           ;Did it work?
           SETB    SCL
           ACALL   SDelay
           DJNZ    BitCnt,ChekLoop     ;Repeat clocks until either SDA clears
                                       ;  or we run out of tries.
           SJMP    FixBusEx            ;Failed to fix bus by this method.
;
RStop:     CLR     SDA                 ;Try forcing a stop since SCL & SDA
           ACALL   SDelay              ;  are both high.
           SETB    SCL
           ACALL   SDelay
           SETB    SDA
           ACALL   SDelay
           JNB     SCL,FixBusEx        ;Are SCL & SDA still high? If so,
           JNB     SDA,FixBusEx        ;  assume bus is now OK, and return
           CLR     C                   ;  with carry cleared.
FixBusEx:  RET
;
;
; Short delay routine (10 machine cycles).
;
SDelay:    NOP
           NOP
           NOP
           NOP
           NOP
           NOP
           NOP
           NOP
           RET
;
;
; Long delay routine (approx 250,000 machine cycles = 250 ms @12MHz).
;
LDelay:    MOV     R6,A
           MOV     R7,#250
LD1:       NOP
           NOP
           DJNZ    R7,LD1              ;250 x 4 cycles = 1 msec (@12MHz).
           DJNZ    R6,LD1              ;approx. 250 msec (@12MHz)
           RET
;
;
; This routine gets the next command/data byte from the command table.
;   Returns data in ACC.
;   Note: The table length can be 256 bytes maximum, due to the way this 
;   routine is written. 
;
GetNext:   MOV     A,R0                ;Set offset into table.
           MOV     DPTR,#CmdTab        ;Set table start address.
           MOVC    A,@A+DPTR           ;Get table entry
           INC     R0
           RET
;
;
;*****************************************************************************
;                               Main Program
;*****************************************************************************
;
Reset:     MOV     SP,#07h             ;Set stack location.
           SETB    ETI                 ;Enable timer I interrupts.
           SETB    EA                  ;Enable global interrupts.
           MOV     R0,#0               ;Set up initial command pointer.
;
           SETB    PosRst              ;Assert positive reset pulse.
           CLR     NegRst              ;Assert negative reset pulse.
           MOV     A,#250              ;Set for 250 msec delay.
           ACALL   LDelay              ;Wait.
           CLR     PosRst              ;De-assert positive reset pulse.
           SETB    NegRst              ;De-assert negative reset pulse.
           MOV     A,#100              ;Set for 100 msec delay.
           ACALL   LDelay              ;Wait.
;
MainLoop:  MOV     PtrSav,R0
           ACALL   GetNext             ;Get next command.
           JZ      Done                ;Found STOP command.
           MOV     ByteCnt,A           ;Set up byte count.
           ACALL   GetNext             ;Get slave address.
           MOV     SlvAdr,A            ;Set up slave address.
           ACALL   SendData            ;Send data to slave.
           SJMP    MainLoop
;
MainRetry: MOV     R0,PtrSav           ;Restore command pointer to retry.
           AJMP    MainLoop            ;Repeat last command.
;
Done:      MOV     PCON,#02h           ;Done, enter power down mode. 
           NOP
	   NOP	
	   NOP
;
;
;
;		 I2C INITIALIZATION DATA TABLE.
;
;		 Definition of data table contents:
;
;
;	1st byte = Command : 00 - Stop.
;                    : nonzero = length count for sub address and
;		       data bytes. slave address is not included in this
;		       number.
;
;	2nd byte = Slave address. 
;	3rd byte = First data byte or slave subaddress.
;	4th to last byte = Additional data bytes.
;
;
;
           ORG     200h		;COMMAND TABLE AT 200H
;
;
CmdTab:		
;
;
;
;	SAA 9051 ADDRESS 8AH
;	
 	DB      0Dh,8Ah,00H             ;13 DATA BYTES TOTAL        
        DB      64H,35H,0AH,0F8H,0CAH,0FEH,029H,00H,77H,0E0H,40H,00H
;
;
;
;	TDA 8444-1			;ADDRESS 40H
;
	DB	09H,40H,00H		; 9 BYTES TOTAL AFTER SLAVE ADD	
	DB	26H,26H,1EH,00H,00H,23H,3FH,3FH
;
;
;
;
;	TDA4680 ADDRESS 88H		;4680 MOVED TO LAST INIT DEVICE
;
	DB	0CH,88H,00H		;12 DATA BYTES TOTAL
	DB	2AH,13H,33H,22H,34H,34H,34H,20H,20H,20H,3FH             
;
;
;
;	TDA 4680 OTHER ADDRESSES BEGINNING AT SUB ADD OC. (0B IS OMITTED)
;
;
	DB 	03H,88H,0CH 		;SUB ADDRESS 0C AND 2 COMMAND DATA 
	DB	89H,10H	
;
;
	DB	00H		;SETS END OF TABLE 0 LENGTH MESSAGE
	DB	00H
 	DB	00H		;JUST FOR SAFTY
	DB	00H
	DB	00H
	DB	00H
	DB	00H
	DB	00H
	DB	00H
	DB	00H
;
;
           END
