* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * TRIANGLE.ASM * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * Purpose: Test of I2C bit-banging using the J1A * Target: 705J1A * Author: Brad Bierschenk, MMD Applications * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * Tested using Maxim I2C DAC IC, MAX517 * Has a "2-wire interface" (another word for I2C) * * This code continuously sends 8-bit data to the * Digital to Analog IC, incrementing from $00 to * $FF, and back down again. This creates a * triangular waveform at the output of the DAC chip. * * The SCL frequency is approximately 28 kHz. This is * completely arbitrary. * ------------------------------------------------------------- * Assembler Equates * ------------------------------------------------------------- RAMSPACE EQU $C0 ;RAM start address ROMSPACE EQU $300 ;EPROM start address PORTA EQU $00 ;Port A PORTB EQU $01 ;Port B DDRA EQU $04 ;Data direction A DDRB EQU $05 ;Data direction B * ------------------------------------------------------------- * Emulated I2C lines on Port A pins * Need a clock (SCL) and data (SDA) * ------------------------------------------------------------- SCL EQU 0 ;Serial clock SDA EQU 1 ;Serial data DACADDR EQU $2C ;Slave address of DAC * ------------------------------------------------------------- * RAM Variables * ------------------------------------------------------------- ORG RAMSPACE BitCounter RMB 1 ;Used to count bits in a Tx Value RMB 1 ;Used to store data value Direction RMB 1 ;Indicates increment or ;decrement * ------------------------------------------------------------- * Start of program code * ------------------------------------------------------------- ORG ROMSPACE ;Start of EPROM Start: ;Initialize variables CLR Value ;Clear all RAM variables CLR BitCounter CLR Direction ;Setup parallel ports LDA #$03 ;PA0 and PA1 as outputs STA PORTA ;driven high to start STA DDRA * ------------------------------------------------------------- * This main loop just ramps up and down the data * value that is sent to the DAC chip. * ------------------------------------------------------------- TxLoop: LDA Direction ;Increment or decrement? BEQ GoUp GoDown: LDA Value ;Decrement BNE GD2 ;Change direction if needed CLR Direction BRA SendIt GD2: DEC Value ;Decrement the data value BRA SendIt GoUp: LDA Value ;Increment CMP #$FF ;Change direction if needed BNE GU2 INC Direction ;Increment the data value BRA SendIt GU2: INC Value * ------------------------------------------------------------- * Send the I2C transmission, including START, address, * data, and STOP * ------------------------------------------------------------- SendIt: ;START condition JSR I2CStartBit ;Give START condition ;ADDRESS byte, consists of 7-bit address + 0 as LSbit LDA #DACADDR ;Slave device address ASLA ;Need this to align address JSR I2CTxByte ;Send the eight bits ;DATA bytes LDA #$00 ;$00 is command byte for DAC JSR I2CTxByte ;Send the 8 bits LDA Value ;Value is value to set DAC JSR I2CTxByte ;Send it ;STOP condition JSR I2CStopBit ;Give STOP condition JSR I2CBitDelay ;Wait a bit BRA TxLoop ;Repeat ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ; I2CTxByte ; Transmit the byte in Acc to the SDA pin ; (Acc will not be restored on return) ; Must be careful to change SDA values only while SCL is low, ; otherwise a STOP or START could be implied ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I2CTxByte: ;Initialize variable LDX #$08 STX BitCounter I2CNextBit: ROLA ;Shift MSbit into Carry BCC SendLow ;Send low bit or high bit SendHigh: BSET SDA,PORTA ;Set the data bit value JSR I2CSetupDelay ;Give some time for data setup BSET SCL,PORTA ;Clock it in JSR I2CBitDelay ;Wait a bit BRA I2CTxCont ;Continue SendLow: BCLR SDA,PORTA JSR I2CSetupDelay BSET SCL,PORTA JSR I2CBitDelay I2CTxCont: BCLR SCL,PORTA ;Restore clock to low state DEC BitCounter ;Decrement the bit counter BEQ I2CAckPoll ;Last bit? BRA I2CNextBit I2CAckPoll: BSET SDA,PORTA BCLR SDA,DDRA ;Set SDA as input JSR I2CSetupDelay BSET SCL,PORTA ;Clock the line to get ACK JSR I2CBitDelay BRSET SDA,PORTA,I2CNoAck ;Look for ACK from slave ;device BCLR SCL,PORTA ;Restore clock line BSET SDA,DDRA ;SDA back as output RTS ;No acknowledgment received from slave device ;Some error action can be performed here ;For now, just restore the bus I2CNoAck: BCLR SCL,PORTA BSET SDA,DDRA RTS ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ; A START condition is defined as a falling edge ; on SDA while SCL is high ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=- I2CStartBit: BCLR SDA,PORTA JSR I2CBitDelay BCLR SCL,PORTA RTS ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ; A STOP condition is defined as a rising edge ; on SDA while SCL is high ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I2CStopBit: BCLR SDA,PORTA BSET SCL,PORTA BSET SDA,PORTA JSR I2CBitDelay RTS ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ; Provide some data setup time to allow ; SDA to stabilize in slave device ; Completely arbitrary delay (10 cycles) ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I2CSetupDelay: NOP NOP RTS ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ; Bit delay to provide (approximately) the desired ; SCL frequency ; Again, this is arbitrary (16 cycles) ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I2CBitDelay: NOP NOP NOP NOP NOP RTS * ------------------------------------------------------------- * Vector Definitions * ------------------------------------------------------------- ORG $07FE ;Reset vector FDB Start