python i2c ioctl

Discussion in 'Python' started by luca, Jun 14, 2007.

  1. luca

    luca Guest

    Hi,
    I was trying to make to work directly l i2c with python with the
    calls ioctl. But I have of the problems and I do not succeed to go
    ahead.

    this and l error

    [[email protected] /usr/local/wrap]129# python pcf8591_ioctl.py
    Reading from 4 ch 8 bit A/D converter PCF8591
    Traceback (most recent call last):
    File "pcf8591_ioctl.py", line 269, in ?
    main()
    File "pcf8591_ioctl.py", line 229, in main
    if i2c_open () < 0:
    File "pcf8591_ioctl.py", line 168, in i2c_open
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), 0,
    iomask)
    TypeError: ioctl requires a file or file descriptor, an integer and
    optionally a integer or buffer argument

    the code

    import fcntl
    import os
    ###################################
    #etrax.h
    ETRAXGPIO_IOCTYPE = 43
    GPIO_MINOR_A = 0
    GPIO_MINOR_B = 1
    GPIO_MINOR_LEDS = 2
    GPIO_MINOR_G = 3
    GPIO_MINOR_LAST = 3
    IO_READBITS = 0x1
    IO_SETBITS = 0x2
    IO_CLRBITS = 0x3
    IO_HIGHALARM = 0x4
    IO_LOWALARM = 0x5
    IO_CLRALARM = 0x6
    IO_LEDACTIVE_SET = 0x7
    IO_READDIR = 0x8
    IO_SETINPUT = 0x9
    IO_SETOUTPUT = 0xA
    IO_LED_SETBIT = 0xB
    IO_LED_CLRBIT = 0xC
    IO_SHUTDOWN = 0xD
    IO_GET_PWR_BT = 0xE
    IO_CFG_WRITE_MODE = 0xF

    def IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask):
    ( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) &
    0xFF) )
    def IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask):
    ( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) &
    0xFF) )

    IO_READ_INBITS = 0x10
    IO_READ_OUTBITS = 0x11
    IO_SETGET_INPUT = 0x12
    IO_SETGET_OUTPUT = 0x13
    #######################################
    #######################################
    #ioctl.h

    _IOC_NRBITS = 8
    _IOC_TYPEBITS= 8
    _IOC_SIZEBITS =14
    _IOC_DIRBITS = 2
    _IOC_NRMASK = ((1 << _IOC_NRBITS)-1)
    _IOC_TYPEMASK = ((1 << _IOC_TYPEBITS)-1)
    _IOC_SIZEMASK =((1 << _IOC_SIZEBITS)-1)
    _IOC_DIRMASK =((1 << _IOC_DIRBITS)-1)
    _IOC_NRSHIFT =0
    _IOC_TYPESHIFT =(_IOC_NRSHIFT+_IOC_NRBITS)
    _IOC_SIZESHIFT =(_IOC_TYPESHIFT+_IOC_TYPEBITS)
    _IOC_DIRSHIFT =(_IOC_SIZESHIFT+_IOC_SIZEBITS)
    _IOC_NONE=0
    _IOC_WRITE=1
    _IOC_READ=2
    def _IOC(dir,type,nr,size):
    (((dir) << _IOC_DIRSHIFT) |
    ((type) << _IOC_TYPESHIFT) |
    ((nr) << _IOC_NRSHIFT) |
    ((size) << _IOC_SIZESHIFT))

    def _IO(type,nr):
    _IOC(_IOC_NONE,(type),(nr),0)

    def _IOR(type,nr,size):
    _IOC(_IOC_READ,(type),(nr),sizeof(size))

    def _IOW(type,nr,size):
    _IOC(_IOC_WRITE,(type),(nr),sizeof(size))

    def _IOWR(type,nr,size):
    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

    def _IOC_DIR(nr):
    (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
    def _IOC_TYPE(nr):
    (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
    def _IOC_NR(nr):
    (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
    def _IOC_SIZE(nr):
    (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
    def IOC_IN():
    (_IOC_WRITE << _IOC_DIRSHIFT)

    def IOC_OUT():
    (_IOC_READ << _IOC_DIRSHIFT)
    def IOC_INOUT():
    ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
    def IOCSIZE_MASK():
    (_IOC_SIZEMASK << _IOC_SIZESHIFT)
    def IOCSIZE_SHIFT():
    (_IOC_SIZESHIFT)
    ######################################
    ######################################
    ######################################



    I2C_DATA_LINE = 1<<24
    I2C_CLOCK_LINE = 1<<25


    #Get the SDA line state
    def i2c_getbit():
    value=fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS))
    if ((value&(I2C_DATA_LINE))==0):
    return 0
    else:
    return 1

    #Set the SDA line as output
    def i2c_dir_out():
    iomask = I2C_DATA_LINE
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), iomask)

    #Set the SDA line as input
    def i2c_dir_in():
    iomask = I2C_DATA_LINE
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), iomask)

    #Set the SDA line state
    def i2c_data(state):
    if (state==1):
    i2c_dir_in()
    else:
    i2c_dir_out()
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS),
    I2C_DATA_LINE)
    #Set the SCL line state
    def i2c_clk(state):
    if (state==1):
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), I2C_CLOCK_LINE)
    else:
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_CLOCK_LINE)

    #Read a byte from I2C bus and send the ack sequence
    #Put islast = 1 is this is the last byte to receive from the slave

    def i2c_inbyte(islast):
    value = 0

    #Read data byte

    i2c_clk(0)
    i2c_dir_in()
    for i in range (0,5):
    i2c_clk(1)
    bitvalue = i2c_getbit()
    value |= bitvalue
    if (i<7):
    value = 1
    i2c_clk(0)

    if (islast==0):
    #Send Ack if is not the last byte to read
    i2c_dir_out()
    i2c_data(0)
    i2c_clk(1)
    i2c_clk(0)
    i2c_dir_in()
    else:
    #Doesn't send Ack if is the last byte to read
    i2c_dir_in()
    i2c_clk(1)
    i2c_clk(0)
    return value

    #Open the GPIOB dev
    def i2c_open():
    i2c_fd = os.open("/dev/gpiog", os.O_RDWR)
    iomask = I2C_CLOCK_LINE
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), iomask)
    iomask = I2C_DATA_LINE
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), iomask)
    fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),
    I2C_DATA_LINE)
    i2c_dir_in()
    i2c_clk(1)
    return i2c_fd


    #Close the GPIOB dev
    def i2c_close():
    i2c_dir_in()
    i2c_fd.close()


    #Send a start sequence to I2C bus

    def i2c_start():
    i2c_clk(0)
    i2c_data(1)
    i2c_clk(1)
    i2c_data(0)

    #Send a stop sequence to I2C bus
    def i2c_stop():
    i2c_clk(0)
    i2c_data(0)
    i2c_clk(1)
    i2c_data(1)

    #Send a byte to the I2C bus and return the ack sequence from slave rtc
    #0 = Nack, 1=Ack

    def i2c_outbyte():
    i2c_clk(0)
    for i in range (0,8):
    if (x & 0x80):
    i2c_data(1)
    else:
    i2c_data(0)
    i2c_clk(1)
    i2c_clk(0)
    x <<= 1
    i2c_dir_in()
    i2c_clk(1)
    ack=i2c_getbit()
    i2c_clk(0)
    if (ack==0):
    return 1
    else:
    return 0

    #PCF8591 address scheme
    #| 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W |
    #| i2c_fixed | i2c_addr | 1/0 |
    def main ():
    i2c_fixed = 0x09
    i2c_addr = 0x01

    print "Reading from 4 ch 8 bit A/D converter PCF8591"

    if i2c_open () < 0:
    print "i2c open error"
    return 1

    ch = 0

    while "azz":
    i2c_start ()

    if i2c_outbyte ((i2c_fixed<<4)|(i2c_addr<<1)|0) == 0:
    print "NACK received"
    i2c_stop ()
    continue

    if i2c_outbyte (ch) == 0:
    print "NACK received"
    i2c_stop ()
    continue

    i2c_stop ()
    i2c_start ()

    if i2c_outbyte((i2c_fixed<<4)|(i2c_addr<<1)|1) == 0:
    print "NACK received"
    i2c_stop ()
    continue

    i2c_inbyte (0)
    value = i2c_inbyte (1)
    i2c_stop ()

    print "CH%d = %.4fv (%.4f hex/n)" %
    (ch,value*0.012941,value)

    ch += 1

    if ch == 4:
    break;

    i2c_close ()
    return 0
    main()


    tnx all
     
    luca, Jun 14, 2007
    #1
    1. Advertisements

  2. luca

    Tim Roberts Guest

    The error message pretty much tells you the problem. One of the parameters
    is not correct. Notice this:
    Key question: what do these functions return?

    Answer: nothing. You compute a value and then throw it away. Thus:
    print IO_CFG_WRITE_MODE_VALUE( 15, 0xfff, 0x0f0 )
    This will print "None". Add a "return" before the expression.

    The same thing is true of all of these functions. You are thinking that a
    Python "def" is like a C "#define". It's not. It's like a C function.
    Nothing is returned unless you return it.
    However, there are more problems with this script. Example:
    This will produce a runtime error, because the name "i2c_fd" is not
    defined. Notice this:
    The result of the open is bound in a LOCAL variable called "i2c_fd". As
    soon as the function returns, that variable goes away. You do RETURN the
    value, but you don't store it anywhere:
    You should probably make this:

    i2c_fd = i2c_open()
    if i2c_fd < 0:
    print "i2c open error"
    return 1

    But, of course, that's not enough either; i2c_fd is a local variable in
    THIS function as well. You should change ALL of the functions so that they
    accept an fd as the first parameter, and then pass i2c_fd into the
    functions here.

    Alternatively, you could create a wrapper class to hold the fd and make the
    function methods on that class.
    I'm curious. What do you think "while" statement is doing? The answer is
    that it is an infinite loop; the string "azz" will always be true, so the
    while statement will always loop. I can't guess what you really wanted
    here.
     
    Tim Roberts, Jun 15, 2007
    #2
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.