How to enable i2c on pin 20/21

Discussion in 'UDOO QUAD' started by iH8c0ff33, Feb 24, 2018.

Tags:
  1. iH8c0ff33

    iH8c0ff33 New Member

    Joined:
    Dec 4, 2014
    Messages:
    1
    Likes Received:
    0
    Hi everyone,
    I've an udoo quad and would like to connect a device using i2c protocol: I saw on the pinout diagram that pin labelled 20 and 21 should be SDA and SCL of an i2c port. Reading other threads I've seen people trying to use that port, but anyone mentioned how did they enable that port. How can I use that port without using the device tree editor (I don't have a screen attached) or how can I use the device tree editor from my computer and not the udoo itself?
    Thanks,
    Daniele
     
  2. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,302
    Likes Received:
    575
  3. Mike Alden

    Mike Alden New Member

    Joined:
    Oct 19, 2018
    Messages:
    2
    Likes Received:
    0
    I have used the Device Tree to associate these 2 pins for I2C communication. But the examples only use this for talking to the Arduino SAM processor.
    Are there any examples of code using the I2C?
    All I have read just says to use the SPIDev module. A little help would be greatly appreciated.
     
  4. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,302
    Likes Received:
    575
    Linux has some tools to check the i2c bus. You could use python with smbus library to communicate with your i2c device. Has the manufacturer of your i2c device no programming examples? See also the following page as a reference, skip the device specific first parts https://www.acmesystems.it/user_i2c
     
  5. Mike Alden

    Mike Alden New Member

    Joined:
    Oct 19, 2018
    Messages:
    2
    Likes Received:
    0
    Yes I have the data sheet for a couple of I2C Devices. I will start with a simple EE-PROM for a write and a read. If you know of any Python code that would be great.

    I think you have answered my question about the Library. Is this uncommon that one would use the Linux host side for I2C Communication? Are most users using the Arduino for the I2C?

    I will give that a shot.

    THANKS~!
     
  6. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,302
    Likes Received:
    575
    Normally you use the Arduino part for Real Time reading sensors and controlling actuators, motors etc based on the input of the sensors (I/O). The communication protocol could be I2C if these devices are I2C. But you could also use general binary input/output (just reading a switch open/closed, switching LED on/off etc) directly.
    You normally use the Linux part for non real-time dependant processes like hosting webserver, sending data to the cloud, communicating with the www, user interface etc and communicate through serial with the Arduino part.

    The linux part performance of I/O is heavily influenced by it's load (it has to do a lot of different things). So if for example you are reading a sensor and want to control a LED based on this switch as fast as possible and within a certain time frame you use the Arduino part. Of the reaction time is not that important then you can also use the Linux part.
     
  7. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    For controlling or troubleshooting i2c devices from the Linux shell, install the package "i2c-tools" if you don't already have it (apt-get install i2c-tools). This pulls in the commands "i2cdetect", "i2cget", "i2cset" and "i2cdump". For all of these you have to give the bus number, e.g. "-y 0" for the /dev/i2c-0 bus mappable to pins 20 and 21.

    A good first step is just to scan the bus for available devices. An example from my home Udoo which has 9 i2c devices sharing the bus:

    Code:
    root@imp:/# i2cdetect -y 0
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- 1d -- --
    20: -- -- -- -- -- -- 26 27 -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- 41 -- -- 44 45 -- -- -- -- -- -- -- -- -- --
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- 75 76 77                         
    
    i2cdump is useful for reading the contents of small serial EEPROMs such as 24LC02's. For example, reading out the monitor's EDID on a PC (bus numbers will vary by motherboard & video card, but the 0x50 i2c address should remain the same):

    Code:
    senin ~ # i2cdump -y 4 0x50
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 ff ff ff ff ff ff 00 10 ac 7b a0 4c 50 48 30    ........??{?LPH0
    10: 2c 19 01 04 a5 34 20 78 3a ee 95 a3 54 4c 99 26    ,????4 x:???TL?&
    20: 0f 50 54 a1 08 00 81 40 81 80 a9 40 b3 00 d1 c0    ?PT??.?@???@?.??
    30: 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20    ??????(<??p?#@0
    40: 36 00 06 44 21 00 00 1a 00 00 00 ff 00 37 57 46    6.?D!..?.....7WF
    50: 47 31 35 41 51 30 48 50 4c 0a 00 00 00 fc 00 44    G15AQ0HPL?...?.D
    60: 45 4c 4c 20 55 32 34 31 32 4d 0a 20 00 00 00 fd    ELL U2412M? ...?
    70: 00 32 3d 1e 53 11 00 0a 20 20 20 20 20 20 00 84    .2=?S?.?      .?
    80: 00 ff ff ff ff ff ff 00 10 ac 7b a0 4c 50 48 30    ........??{?LPH0
    90: 2c 19 01 04 a5 34 20 78 3a ee 95 a3 54 4c 99 26    ,????4 x:???TL?&
    a0: 0f 50 54 a1 08 00 81 40 81 80 a9 40 b3 00 d1 c0    ?PT??.?@???@?.??
    b0: 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20    ??????(<??p?#@0
    c0: 36 00 06 44 21 00 00 1a 00 00 00 ff 00 37 57 46    6.?D!..?.....7WF
    d0: 47 31 35 41 51 30 48 50 4c 0a 00 00 00 fc 00 44    G15AQ0HPL?...?.D
    e0: 45 4c 4c 20 55 32 34 31 32 4d 0a 20 00 00 00 fd    ELL U2412M? ...?
    f0: 00 32 3d 1e 53 11 00 0a 20 20 20 20 20 20 00 84    .2=?S?.?      .?
    
    i2cget and i2cget read & write registers (respectively) one byte at a time, and can work with almost any type of i2c chip, so long as timing isn't critical and you have a register map on hand. Here's an example script I use to switch power on and off to some rarely-used external USB backup drives, using a custom relay board driven by a Microchip MCP23008 i2c I/O-expander chip. I use two leftover output bits from this chip to control an unrelated device, hence the bitwise AND and OR operations to avoid disturbing those pins:

    Code:
    #!/bin/bash
    
    #+ 8 = 3G /w
    #+ 4 = 4G /y
    #+ 2 = 2G /s
    #+ 1 = 3G /u
    
    # 0x40 = main-power latching relay; 0x80 = invert polarity
    
    ADDR=0x27    # MCP23008 i2c address
    DLY=.2
    
    CUR=`i2cget -y 0 $ADDR 0x0a`
    PV=$[ $CUR & 0x30 ]
    
    # PV control bits to be preserved:
    # 0x10 = inhibit DCDC; 0x20 = force-on DCDC
    
    if [ .$1 = .off ]; then
     i2cset -y 0 $ADDR 0x00 0x00; sleep $DLY    # 0 -> IODIR; all pins as output
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0x40 ];`; sleep $DLY
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0xc0 ];`; sleep $DLY
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0x40 ];`; sleep $DLY
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0x00 ];`
    elif [ .$1 = .on ]; then
     i2cset -y 0 $ADDR 0x00 0x00; sleep $DLY
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0x80 ];`; sleep $DLY
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | 0x00 ];`
    elif [ .$1 = . ]; then
     head $0 |grep '^#+'
     echo
     echo $CUR
    else
     i2cset -y 0 $ADDR 0x0a `printf '0x%x' $[ $PV | $1 ];`
    fi
    
     
  8. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    Here's an example of how to control an i2c device on the Linux side from the C language, either plain C or C++. This is a little command-line tool I wrote for sending messages to an HD44780-type LCD character display, connected behind an MCP23017 I/O expander with the pinout given in the #define statements up top. My LCD has a 3-color RGB backlight, so the first parameter is taken as a 3-bit (0-7) decimal number to set the backlight color. This is modeled after some Python code published at Adafruit.

    Code:
    // jnh - based on Adafruit Adafruit_CharLCD_IPclock_example.py
    // I2C/MCP23017 version, 2016-09-17
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <linux/i2c-dev.h>
    #include <error.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    int addr = 0x26;               /* 23017 chip I2C addr */
    char *i2cbus= "/dev/i2c-0";
    
    #define D4   1    // 23017 GPB0
    #define D5   2    // 23017 GPB1
    #define D6   4    // 23017 GPB2
    #define D7   8    // 23017 GPB3
    #define BK_R 16   // 23017 GPB4
    #define BK_G 32   // 23017 GPB5
    #define BK_B 64   // 23017 GPB6
    #define RS   128  // 23017 GPB7
    
    #define EN_HI 0xFF  // 23017 GPA7
    #define EN_LO 0x7F  // 23017 GPA7
    
    #define IODIRA 0x00  // 23017 bit directions for GPIO-A
    #define IODIRB 0x01  // 23017 bit directions for GPIO-A
    #define OLATA  0x14  // 23017 output latch: GPIO-A
    #define OLATB  0x15  // 23017 output latch: GPIO-B
    
    // commands
    #define LCD_CLEARDISPLAY             0x01
    #define LCD_RETURNHOME               0x02
    #define LCD_ENTRYMODESET             0x04
    #define LCD_DISPLAYCONTROL           0x08
    #define LCD_CURSORSHIFT              0x10
    #define LCD_FUNCTIONSET              0x20
    #define LCD_SETCGRAMADDR             0x40
    #define LCD_SETDDRAMADDR             0x80
    
    // flags for display entry mode ( | LCD_ENTRYMODESET = 0x04 );
    #define LCD_ENTRYRIGHT               0x00
    #define LCD_ENTRYLEFT                0x02
    #define LCD_ENTRYSHIFTINCREMENT      0x01
    #define LCD_ENTRYSHIFTDECREMENT      0x00
    
    // flags for display on/off control ( | DISPLAYCONTROL = 0x08 )
    #define LCD_DISPLAYON                0x04
    #define LCD_DISPLAYOFF               0x00
    #define LCD_CURSORON                 0x02
    #define LCD_CURSOROFF                0x00
    #define LCD_BLINKON                  0x01
    #define LCD_BLINKOFF                 0x00
    
    // flags for display/cursor shift  ( | LCD_CURSORSHIFT = 0x10 )
    #define LCD_DISPLAYMOVE              0x08
    #define LCD_CURSORMOVE               0x00
    #define LCD_MOVERIGHT                0x04
    #define LCD_MOVELEFT                 0x00
    
    // flags for function set    ( | LCD_FUNCTIONSET = 0x20 )
    #define LCD_8BITMODE                 0x10
    #define LCD_4BITMODE                 0x00
    #define LCD_2LINE                    0x08
    #define LCD_1LINE                    0x00
    #define LCD_5x10DOTS                 0x04
    #define LCD_5x8DOTS                  0x00
    
    int i2c_fd, gpb, bklt=0;
    unsigned char displaycontrol=0, displayfunction=0, displaymode=0;
    
    wr_reg(unsigned char reg, unsigned char val) {
     unsigned char buf[4];
    
     buf[0]=reg;
     buf[1]=val;
     if ((write(i2c_fd, buf, 2)) != 2) {
       fprintf(stderr,"Error writing 0x%x to reg 0x%x @ addr 0x%x on %s\n",val,reg,addr,i2cbus);
       exit(1);
     }
    }
    
    pulse_en () {
            wr_reg(OLATA,EN_HI);
            usleep(2);
            wr_reg(OLATA,EN_LO);
            usleep(1);
            wr_reg(OLATA,EN_HI);
            usleep(2);
    }
    
    write1nibble(unsigned char nib) {
            wr_reg(OLATB,(bklt | (nib & 0xF)) );  // RS=high-bit => 0
    
            usleep(20);
    
            pulse_en();
    
            usleep(40);
    }
    
    writenibbles(unsigned char value, char mode) {
            unsigned char nib;
    
            //fprintf(stderr,"sending %X / %d]\n",value, mode);
    
            /* high nibble first */
            nib = (value >> 4);
            wr_reg(OLATB,(bklt | (nib & 0xF) | (mode ? 0x80 : 0x00)) );
    
            usleep(20);
    
            pulse_en();
    
            usleep(20);
    
            nib = (value & 0x0f);
            wr_reg(OLATB,(bklt | (nib & 0xF) | (mode ? 0x80 : 0x00)) );
    
            usleep(20);
    
            pulse_en();
    
            usleep(100);
    }
    
    message (char *msg) {
     int j;
    
     for (j=0; (msg[j]!=0); j++) {
      if ((msg[j] == '\n' || msg[j] == '\r'))
            writenibbles(0xC0,0);  /* next line */
       else writenibbles(msg[j],1);
     }
    }
    
    main(int argc, char **argv) {
    
     int i,s;
    
     if (argc < 2) {
           fprintf(stderr,"usage: %s <bkcolor>\n",argv[0]);
           fprintf(stderr,"usage: %s <bkcolor> \"message\"\n",argv[0]);
           fprintf(stderr," -OR-  %s <bkcolor> <charnum1> <param2>...\n",argv[0]);
           exit(1);
     }
    
     bklt=((7 ^ atoi(argv[1])) << 4);
    
     if ((i2c_fd = open(i2cbus, O_RDWR)) < 0) {
           fprintf(stderr,"Failed to open i2c port %s\n",i2cbus);
           exit(1);
     }
     if (ioctl(i2c_fd, I2C_SLAVE, addr) < 0) {
           fprintf(stderr,"Unable to get bus access to talk to addr %x on %s\n",addr,i2cbus);
           exit(1);
     }
    
     wr_reg (IODIRA,0x7F);   // 0xFF & ~EN;
     wr_reg (IODIRB,0x00);   // all GPIO-B pins to output
    
     if (argc == 2) {
       wr_reg(OLATB,bklt);
       exit(0);
     }
    
     /* init: enter & exit 8-bit mode to reset possible nibble misalignment... */
     write1nibble(0x3);
     usleep(5000);
     write1nibble(0x3);
     usleep(5000);
     write1nibble(0x3);
     usleep(1000);
     write1nibble(0x2);
     usleep(1000);
    
     writenibbles(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS,0);
     usleep(50);
     writenibbles(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF,0);  // 0x0C
     usleep(50);
     writenibbles(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT,0);         // 0x06
     usleep(50);
    
     writenibbles(LCD_CLEARDISPLAY,0);
     usleep(3200);
    
     if (argc > 3) {
       s=atoi(argv[2]);
       for (i=s;i<(s+16);i++) writenibbles(i,1);
       writenibbles(0xC0,0);
       for (i=(s+16);i<(s+32);i++) writenibbles(i,1);
     }
     else
      message (argv[2]);
     close(i2c_fd);
    
     return 0;
    }
     
  9. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    As one more Linux i2c C-language example that involves reading a sensor rather than controlling something, here's a short utility I wrote for pulling voltage and current (shunt) measurements from a pair of TI INA219 power monitoring chips, and multiplying them to calculate wattage.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <linux/i2c-dev.h>
    #include <fcntl.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    int fd;
    int addr1 = 0x44;
    int addr2 = 0x45;
    char *i2cbus= "/dev/i2c-0";
    
    unsigned char buf[32];          // Buffer for i2c data being read/written
    
    int read_register(int addr, unsigned char reg, unsigned char mask, unsigned char sh)
    {
            short value;
    
            if ((fd = open(i2cbus, O_RDWR)) < 0) {
                    fprintf(stderr,"Failed to open i2c port\n");
                    exit(1);
            }
           
            if (ioctl(fd, I2C_SLAVE, addr) < 0) {
                    fprintf(stderr,"Unable to get bus access to talk to INA219 at %X\n",addr);
                    exit(1);
            }
    
            buf[0] = reg;
    
            if ((write(fd, buf, 1)) != 1) {
                    fprintf(stderr,"Error sending register address %d to %X\n",reg,addr);
                    exit(1);
            }
    
            if (read(fd, buf, 2) != 2) {
                    fprintf(stderr,"Unable to read from register %d on %X\n",reg,addr);
                    exit(1);
            }
    
            close(fd);
    
            if (mask != 0 ) buf[1] &= mask;
    
            value = ( (buf[0] << 8) | buf[1]);
    
            if (sh != 0 ) return (int)(value << sh);
              else return (int)(value);
    
    }
    
    int read_register_trig(int addr, unsigned char reg, unsigned char mask, unsigned char sh)
    {
            short value;
    
            if ((fd = open(i2cbus, O_RDWR)) < 0) {
                    fprintf(stderr,"Failed to open i2c port\n");
                    exit(1);
            }
           
            if (ioctl(fd, I2C_SLAVE, addr) < 0) {
                    fprintf(stderr,"Unable to get bus access to talk to INA219 at %X\n",addr);
                    exit(1);
            }
    
            // trigger conversion:
            buf[0] = 0;           // config reg
            buf[1] = 0b00001111;  // upper 8 bits
            buf[2] = 0b11111111;  // lower 8 bits
    
            if ((write(fd, buf, 3)) != 3) {
                    fprintf(stderr,"Error writing to config register\n");
                    exit(1);
            }
    
            usleep(68000);
    
            buf[0] = reg;
    
            if ((write(fd, buf, 1)) != 1) {
                    fprintf(stderr,"Error sending register address %d to %X\n",reg,addr);
                    exit(1);
            }
    
            if (read(fd, buf, 2) != 2) {
                    fprintf(stderr,"Unable to read from register %d on %X\n",reg,addr);
                    exit(1);
            }
    
            close(fd);
    
            if (mask != 0 ) buf[1] &= mask;
    
            value = ( (buf[0] << 8) | buf[1]);
    
            if (sh != 0 ) return (int)(value << sh);
              else return (int)(value);
    
    }
    
    void init_conf_cal(int addr, unsigned int Cal)
    {
    
            if ((fd = open(i2cbus, O_RDWR)) < 0) {
                    fprintf(stderr,"Failed to open i2c port\n");
                    exit(1);
            }
           
            if (ioctl(fd, I2C_SLAVE, addr) < 0) {
                    fprintf(stderr,"Unable to get bus access to talk to INA219 at %X\n",addr);
                    exit(1);
            }
           
            // set config register
    
            // bit 15: (0) RESET
            // bit 14: (0) n/c
            // bit 13: (0) 0=16V range, 1=32V
            // bit 12/11: (01) PG1/PG0: Shunt voltage gain
            //           00 = 1, +/- 40mV fullscale
            //       ->  01 = 2, +/- 80mV fullscale  80mV/.01ohm = 8A FS
            //           10 = 4, +/-160mV fullscale
            //           11 = 8, +/-320mV fullscale
            // bits 10,9,8,7: (1111) BADC: bus ADC resolution, samples to average
            // bit 6,5,4,3:   (1111) SADC: shunt ADC resolution, samples to average
            // bits 2,1,0:    (111)  Op Mode: Shunt & Bus, continuous
            //                 011 = shunt & bus, triggered
    
            buf[0] = 0;           // config reg
            buf[1] = 0b00001111;  // upper 8 bits
            buf[2] = 0b11111111;  // lower 8 bits
    
            if ((write(fd, buf, 3)) != 3) {
                    fprintf(stderr,"Error writing to config register\n");
                    exit(1);
            }
    
            // CALIBRATION REGISTER  (REG 5)
            // =============================
            // VBUS_MAX   = 32V   (set above)
            // VSHUNT_MAX = 0.08V (gain 8)
            // RSHUNT     = 0.01 ohm
    
            // MaxPossible_I = VSHUNT_MAX / RSHUNT = 8.0A
            // MaxExpected_I = 8.0A, same
    
            // MinLSB = MaxExpected_I/32767 = .000244148
            // MaxLSB = MaxExpected_I/4096  = .001953125
    
            // CurrrentLSB = MinLSB for now = .00024414807580797753
    
            // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
            // Cal = 16776
    
            // Cal = 16776;
    
            buf[0] = 5;        // calibration register
            buf[1] = ((Cal & 0xFF00) >> 8);
            buf[2] = (Cal & 0xFF);
    
            if ((write(fd, buf, 3)) != 3) {
                    fprintf(stderr,"Error writing to config register\n");
                    exit(1);
            }
    
            // Calculate Power LSB:
            // PowerLSB = 20 * CurrentLSB
            // PowerLSB = .0048829615161595506 (4.89 mW per bit)
            //
            // Compute max current & shunt voltage values before overflow
            //
            // Max_Current_Overflow = min(CurrentLSB*32767,MaxPossible_I) = 8.0 A
            //
            // Max_ShuntVoltage = Max_Current_Overflow * RSHUNT = .08V
            //  (clamp to VSHUNT_MAX if greater)
            //
            // Compute max power
            // MaxPower = Max_Current_Overflow * VBUS_MAX
            // MaxPower = 8.0A * 32V = 256.0W
    
            close(fd);
    }
    
    main (int argc, char **argv) {
            int r,v;
    
            if ( (argc == 3) && (argv[1][0]=='-') && (argv[1][1]=='i') ) {
              init_conf_cal(addr1,atoi(argv[2]));
              init_conf_cal(addr2,atoi(argv[2]));
              fprintf(stderr,"Initialization complete\n");
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='d') ) {
              r=0;
              printf("a%X r%d = %d",addr1,r,read_register_trig(addr1,r,0,0));
              putchar('\t');
              printf("a%X r%d = %d",addr2,r,read_register_trig(addr2,r,0,0));
              putchar('\n');
              for(r=1;r<=5;r++) {
                    printf("a%X r%d = %d",addr1,r,read_register(addr1,r,0,0));
                    putchar('\t');
                    printf("a%X r%d = %d",addr2,r,read_register(addr2,r,0,0));
                    putchar('\n');
              }
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='v') ) {
                    printf("V_a: %5.3f\tV_b: %5.3f\n",
                     (float)read_register_trig(addr2,2,0xF8,0)*1/2000,
                     (float)read_register_trig(addr1,2,0xF8,0)*1/2000);
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='a') ) {
                    printf("A_a: %5.3f\tA_b: %5.3f\n",
                     (float)read_register_trig(addr2,1,0,2)*8/32767,
                     (float)read_register_trig(addr1,1,0,2)*8/32767);
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='A') ) {
                    printf("A_a: %5.3f\tA_b: %5.3f\n",
                     (float)read_register_trig(addr2,4,0,2)*2/32767,
                     (float)read_register_trig(addr1,4,0,2)*2/32767);
            }
            else if ( ( argc == 1 ) || \
                      ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='p') ) ) {
                    printf("P_a: %5.3f\tP_b: %5.3f\n",
                     (float)read_register_trig(addr2,3,0,0)*20*8/32767,
                     (float)read_register_trig(addr1,3,0,0)*20*8/32767);
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='w') ) {
                    float v1,v2,a1,a2;
                    char cf;
                    v1=(float)read_register_trig(addr2,2,0xF8,0)*1/2000;
                    v2=(float)read_register_trig(addr1,2,0xF8,0)*1/2000;
                    a1=(float)read_register(addr2,4,0,2)*2/32767;
                    a2=(float)read_register(addr1,4,0,2)*2/32767;
                    if (a1 > 0 && a2 > 0) cf=(v1>v2 ? 'X' : 'x');
                     else if (a1 > 0)     cf=(v1>v2 ? 'V' : 'v');
                     else                 cf=(v1>v2 ? 'B' : 'b');
                    printf("%4.2f%c %3.1f",
                            (v1>v2 ? v1 : v2), cf, (a1*v1 + a2*v2));
            }
            else if ( (argc == 2) && (argv[1][0]=='-') && (argv[1][1]=='W') ) {
                    float v1,v2,p1,p2,a1,a2;
                    v1=(float)read_register_trig(addr2,2,0xF8,0)*1/2000;
                    v2=(float)read_register_trig(addr1,2,0xF8,0)*1/2000;
                    a1=(float)read_register(addr2,4,0,2)*2/32767;
                    a2=(float)read_register(addr1,4,0,2)*2/32767;
                    p1=(float)read_register(addr2,3,0,0)*20*8/32767;
                    p2=(float)read_register(addr1,3,0,0)*20*8/32767;
                    printf("%4.2f%c %4.2f %4.2f [%4.2f %4.2f]",
                            (v1>v2 ? v1 : v2),
                            (v1>v2 ? 'V' : 'v'),
                            a1*v1,a2*v2,p1,p2);
            }
            else if ( (argc == 2) && (argv[1][0]>='0') && (argv[1][0]<='9') ) {
              r = atoi(argv[1]);
              if (r >= 0 && r <= 5) {
                printf("a%X r%d = %d",addr1,r,read_register_trig(addr1,r,0,0));
                putchar('\t');
                printf("a%X r%d = %d",addr2,r,read_register_trig(addr2,r,0,0));
                putchar('\n');
              }
              else {
                fprintf(stderr,"Invalid register.\n");
                exit(1);
              }
            }
            else {
              fprintf(stderr,"Usage: %s <-i | -d | -[vaApw] | reg_number, 0-5>\n",argv[0]);
              exit(1);
            }
            exit(0);
    }
     
    waltervl likes this.

Share This Page