Using the Xtender73 with the STAMP II
(General Purpose I/O and A/D)

Drawing of Connection

' Sample routines to do I2C on a STAMPII and an Xtender
' Special Thanks to Victor Epand

xtn_dev  CON $80        ' address for xtender device 0
xtn_reset CON $9e       ' reads current revision and resets xtender
xtn_pins_out CON $9d    ' make GP pins outputs as specified by data_byte
xtn_pins_low CON $9b    ' make GP pins output a low
xtn_pins_high CON $9c   ' make GP pins output a high
xtn_ad_cont CON $82     ' A/D control register
xtn_ad_res CON $82      ' reads from this register are results of last conv.

b var byte      ' temp storage for demo program

main_prog:
    input si2c_data
    input si2c_clk      ' initial state

    ' Show revision of the Xtender and prove communications
    debug "Extender Revision:"
    addr_byte=xtn_dev
    comm_byte=xtn_reset
    gosub si2c_read
    debug dec data_byte, CR
    pause 3000

    ' Blink a light for a while
    addr_byte=xtn_dev
    comm_byte=xtn_pins_out
    data_byte=%00000001         ' only make GP0 an output
    gosub si2c_write

    b=128
    xtn_blink_lp:
        debug "Blinking LED on GP0", CR
        comm_byte=xtn_pins_high
        gosub si2c_write
        pause 50
        comm_byte=xtn_pins_low
        gosub si2c_write
        pause 50
        b = b + 1
        IF b then xtn_blink_lp

    ' read channel one of the A/D
    debug "Reading A/D channel 0", CR
    xtn_adread_lp:
        addr_byte=xtn_dev
        comm_byte=xtn_ad_cont
        data_byte=%00000101   ' channel 0, internal ref, power up
        gosub si2c_write

        comm_byte=xtn_ad_res
        gosub si2c_read
        debug "A/D result: "
        debug dec data_byte, CR
        goto xtn_adread_lp

    end




' Simulated Inter-Integrate Circuit driver (si2c)
' This driver consists of two internal routes (si2c_wbyte and si2c_rbyte)
' and two user functions (si2c_write and si2c_read)
' the si2c_write function needs three byte parameters:
'     addr_byte: the i2c address of the device writing to
'     comm_byte: the sub command to tell the device what to do
'     data_byte: the byte of data to use for the command
'
' the si2c_read function needs two parameters and returns a byte:
'    addr_byte: the i2c address of the device reading from
'    comm_byte: the sub command to tell the device what to read
'    data_byte: the value returned from the device that was read


' This routine used pin 0 as the I2C clock pin and pin 1 as the I2c data pin
' Both of these pins must be pulled high. Both of these pins should initially
' be configured as inputs at power up.

si2c_clk CON 0          ' I/O pin for I2C Clock line
                        ' IN0 is used in some situations
si2c_data CON 1         ' I/O pin for I2C data line
                        ' IN1 is used in some situations

' the following are the storage required by the si2c routines.
in_byte VAR byte        ' used internally by the si2c_wbyte function
bit_count VAR byte      ' used internally by both the si2c_wbyte and rbyte
send_ack VAR bit        ' used to tell rbyte if it should ack or not
exit_ack VAR bit        ' used to indicate if wbyte got an ack or not
data_byte VAR byte      ' either the data to be written or the data just read
addr_byte VAR byte      ' address of I2C device (LSB=read indicator)
comm_byte VAR byte      ' I2C sub command

si2c_wbyte:             ' returns 1 if successful, 0 = NACK
                        ' in_byte is byte to be written
    bit_count=%10000000
    si2c_wbyte_lp:
        low si2c_clk
        input si2c_data
        IF (bit_count & in_byte) then si2c_wbyte_do1
            low si2c_data
        si2c_wbyte_do1:
        bit_count=bit_count>>1
        input si2c_clk
        IF bit_count then si2c_wbyte_lp

    ' now test the acknowledge bit
    low si2c_clk
    input si2c_data
    input si2c_clk
    exit_ack=0
    IF in1 then si2c_wbyte_ex
        exit_ack=1
    si2c_wbyte_ex:
    return


si2c_rbyte:             ' send_ack is set for a post ack or not
    bit_count=%10000000
    low si2c_clk
    data_byte=0
    input si2c_data
    si2c_rbyte_lp:
        input si2c_clk
        si2c_rbyte_wt:
            IF in0=0 then si2c_rbyte_wt
        IF in1=0 then si2c_rbyte_dl
            data_byte=data_byte|bit_count
        si2c_rbyte_dl:
        low si2c_clk
        bit_count=bit_count>>1
        IF bit_count then si2c_rbyte_lp

    ' send ack bit if required
    low si2c_data
    IF send_ack then si2c_rbyte_ak
        input si2c_data
    si2c_rbyte_ak:
    input si2c_clk
    return



si2c_write:     ' must set addr, comm, and data before calling
    low si2c_data ' generate a start bit
    si2c_write_lp:
        in_byte=addr_byte
        gosub si2c_wbyte
        IF exit_ack=0 then si2c_write_lp
    in_byte=comm_byte
    gosub si2c_wbyte
    in_byte=data_byte
    gosub si2c_wbyte
    low si2c_clk        ' generate stop bit
    low si2c_data
    input si2c_clk
    input si2c_data
    return


si2c_read:      ' must set addr, comm,  data_byte will have return
    low si2c_data ' generate a start bit
    IF addr_byte.bit0=1 then si2c_read_sk
        si2c_read_lp:
            in_byte=addr_byte
            gosub si2c_wbyte
            IF exit_ack=0 then si2c_read_lp
        in_byte=comm_byte
        gosub si2c_wbyte
        low si2c_clk
        low si2c_data
        input si2c_clk
        input si2c_data ' generate the stop
        low si2c_data   ' generate a start
        addr_byte=addr_byte+1
    si2c_read_sk:
    in_byte=addr_byte
    gosub si2c_wbyte
    send_ack=0
    gosub si2c_rbyte
    low si2c_clk
    low si2c_data
    input si2c_clk
    input si2c_data     ' generate the stop bit
    return

 

Protean Logic Inc. Copyright 05/06/04         Top of Page