Virtual COM AO31

Dependencies:   USBDevice

main.cpp

Committer:
walterluu
Date:
2021-12-29
Revision:
28:f86ec29d719c
Parent:
27:6e67717398b6

File content as of revision 28:f86ec29d719c:

// This program is for interacting with the MAX20361 (AO31)
// The PMIC registers: I2C address 0x50/0x51
// The Haptic driver registers: I2C address 0xA0/0xA1
// The MAX17260 m5 Fuel Gauge: I2C address 0x6C/0x6D. The register's length is 16 bits.


#include "mbed.h"
#include "USBSerial.h"

#define BS          8       // ASCII Back Space
#define CR          13      // ASCII Carriage Return

// Virtual serial port over USB TODO NEW VID PID NEEDED!!
USBSerial pc(0x0B6A, 0x0042, 0x0001, false);

// I2C setup
I2C i2c(P1_6, P1_7);            // P1_6 -> I2C1_SDA,  P1_7-> I2C1_SCL

//Timer setup
Ticker timer_1;                 // timer for blinking led heartbeat
bool led_toggle_flag = false;

//LED  blink setup
DigitalOut rLED(LED1);
DigitalOut gLED(LED2);
DigitalOut bLED(LED3);

//InterruptIn button(SW1);

void LED_blink_callback() { // LED Heart beat

    led_toggle_flag = !led_toggle_flag;

    if (led_toggle_flag)
    {
        //toggle teal leds
        rLED = LED_OFF;
        gLED = LED_ON;
        bLED = LED_ON;
    }
    else
    {
        rLED = LED_OFF;
        gLED = LED_OFF;
        bLED = LED_OFF;
    }

}

// *****************************************************************************
//   I2C_write_register(char, char, char)  writes single byte to OT07
//                       char   I2C address
//                       char   OT07 register address
//                       char   data byte to be writen
//   returns                    0 on success ACK, 1 on NACK 
// *****************************************************************************

int I2C_write_register(char I2C_add, char reg_add, char byte) {
    char data[2];
    int error;
    data[0] = reg_add;
    data[1] = byte;
    error = i2c.write(I2C_add, data, 2);
    return error;

}

/// ****************************************************************************
//   I2C_write_register(char, char, char *, int)  writes multiple bytes to OT07
//                       char   I2C address
//                       char   OT07 register address
//                       char * data vector of bytes to be written
//                       int    number of bytes to write
//   returns                    0 on success ACK, 1 on NACK 
// *****************************************************************************

int I2C_write_register(char I2C_add, char reg_add, char *bytes, int n) {
    int i;
    //set start address
    char data[16];
    int error;
    data[0] = reg_add;
    for (i = 1; i <= n; i++) {
        data[i] = bytes[i - 1];
    }
    error = i2c.write(I2C_add, data, n + 1);  // send n bytes of data

    return error;
}

// *****************************************************************************
//   I2C_read_register(char, char, char *, int)  reads byte(s) from OT07
//                       char   I2C address
//                       char   OT07 register address
//                       char * data vector for read bytes to be stored in 
//                       int    number of bytes to read
//   returns                    0 on success, 1 on fail 
// *****************************************************************************

int I2C_read_register(char I2C_add, char reg_add, char *bytes, int n) {
    int error;
    error = i2c.write(I2C_add, &reg_add, 1, 1);
    if (error)return error;
    error = i2c.read(I2C_add, bytes, n);
    //if(DEBUG)db.printf("rr e[%d]\r\n",error);
    return error;
}

int I2C_read(char I2C_add, char *bytes, int n) {
    int error;

    i2c.start();            // create a start bit
    error = i2c.write(I2C_add);

//    pc.printf("Error1: %d\r\n", error);

    wait(0.3);
    
//    if (error)return error;
    error = i2c.read(I2C_add, bytes, n);
//    pc.printf("Error2: %d\r\n", error);
    //if(DEBUG)db.printf("rr e[%d]\r\n",error);
    return error;
}


/// ****************************************************************************
//   process_command(char *)  writes multiple bytes to OT07
//                       char * receive buffer from virtual serial port
//   returns                    0 on processed command, 1 on invalid command 
// *****************************************************************************
void process_command(char rx_buff[128])
{
    char data[130];         // for storing read results
    char wdata[10];         // for storing write bytes
    int i;
    int num_bytes;
    char c;
    int arg1 = 0;
    int arg2 = 0;
    int arg3 = 0;
    int arg4 = 0;
//    int n = sscanf(rx_buff, " %c %x %x %x", &c, &arg1, &arg2, &arg3);
    int n = sscanf(rx_buff, " %c %x %x %x %x", &c, &arg1, &arg2, &arg3, &arg4);
    //process input
    if (n > 0) {//got input so process it
        switch (c) 
        {
            case 'r':
            case 'R':
                  //read register "r slave.add"                                      
                if (n == 2) {    
                    int error = I2C_read(arg1, data, 2);
                    if (error)
                        pc.printf("nack\r\n");
                    else
                        pc.printf("%02X %02X\r\n", data[0], data[1]);
                }
                
                //read register "r slave.add radd"                                      
                if (n == 3) {   //read single register from selected device
                    int error = I2C_read_register(arg1, arg2, data, 1);
                    if (error)
                        pc.printf("nack\r\n");
                    else
                        pc.printf("%02X\r\n", data[0]);
                }
                
                //read register "r slave.add radd.start radd.end"  
                if (n == 4) {   //read a range of registers from selected device 
                    num_bytes = arg3 - arg2 + 1;// calculate number of bytes to read
                    if (num_bytes < 1) num_bytes = 1;// if arg2 <= arg 1 just read arg1 address.                                      
                    I2C_read_register(arg1, arg2, data, num_bytes);
                    for (i = 0; i<num_bytes; i++) {
                        pc.printf("%02X\r\n", data[i]);
                    }
                }
                
                //read m5 fuel gauge register "r slave.add radd 2 5" 
                if (n == 5) {
                    I2C_read_register(arg1, arg2, data, 2);
//                    pc.printf("m5\r\n");
                    pc.printf("%02X%02X\r\n", data[1], data[0]);
                }
                
                break;
            case 'w':
            case 'W':   
            
                //write register "w device w.addr data"
                if (n == 4) {
                    int error = I2C_write_register(arg1, arg2, arg3); //int I2C_write_register(char I2C_add, char reg_add, char byte)
                    if (error)
                        pc.printf("nack\r\n");
                    else
                        pc.printf("ack\r\n");
                }
                
                //write m5 fuel gauge register "w device w.addr data.upperbyte data.lowerbyte"
                if (n == 5) {
                    wdata[0] = arg4;
                    wdata[1] = arg3;
//                     pc.printf("%02X%02X\r\n", wdata[1], wdata[0]);
                    int error = I2C_write_register(arg1, arg2, wdata, 2); // I2C_write_register(char I2C_add, char reg_add, char *bytes, int n)
                    if (error)
                        pc.printf("nack\r\n");
                    else
                        pc.printf("ack\r\n");
                }
                
                break;
        }//end switch(c)
    }   
}

//******************************************************************************
//        main()
//******************************************************************************

int main()
{
    
    // i/o variables
    char rx_buff[128];              // comport input buffer
    int rx_index;                   // rx_buffer pointer

    //************* init ticker timer callbacks  ****************
    timer_1.attach(&LED_blink_callback, 0.5);     //start ticker, once per  sec.      

    i2c.frequency(400000);      //set I2C clock to 400kHz     

    rLED = LED_OFF;
    gLED = LED_ON;
    bLED = LED_ON;

    rx_index = 0;               //character buffer index for input from PC

    while (1) {  // start main loop, check for input, process command repeat   

        //test if PC sent some charaters
        while (pc.readable()) 
        {  
                               
            //characters in buffer,  get them                               
            rx_buff[rx_index] = pc.getc();
            
            //Process command when carriage return is received
            if (rx_buff[rx_index] == CR) 
            {
                rx_buff[++rx_index] = 0;
                rx_index = -1;  // because i++ at end of while give i=0 on next loop 
                
                process_command(rx_buff);//if carriage return received, process command
                          
            }     
            if (rx_buff[rx_index] == BS) 
            {
                //backspace received, back up buffer pointer                                
                if (rx_index>0)rx_index--;//remove last char from buffer if not at start.                 
            }
            else rx_index++;
        } 
    }//end while(1)
}