MAX30208 I2C Terminal Interface
Dependencies: max32630fthr USBDevice
MAX30208_I2C_Terminal_Interface.cpp
- Committer:
- elloway
- Date:
- 2020-09-04
- Revision:
- 17:65cd58826416
File content as of revision 17:65cd58826416:
#include "mbed.h" #include "max32630fthr.h" #include "USBSerial.h" //#define OT07_ADDRESS 0xA0 // OTO7 Base Address #define DEBUG 1 // 0->off, 1-> on, debug prints to daplink port //OT07 Registers #define OT07_STATUS 0x00 // OT07 status regiter #define OT07_INT_EN 0x01 // OT07 Interrupt Enable #define OT07_FIFO_W 0x04 // OT07 FIFO Write Pointer #define OT07_FIFO_R 0x05 // OT07 FIFO Read Pointer #define OT07_FIFO_OF 0x06 // OT07 FIFO Overflow Counter #define OT07_FIFO_COUNT 0x07 // OT07 FIFO Data Count #define OT07_FIFO_DATA 0x08 // OT07 FIFO Data #define OT07_FIFO_CNFG1 0x09 // OT07 FIFO Configuration 1 (FIFO_A_FULL) #define OT07_FIFO_CNFG2 0x0A // OT07 FIFO Configuration 2 #define OT07_SYS 0x0C // OT07 System Configuration #define OT07_ALARM_HIGH_MSB 0x10 // OT07 Alarm High MSB #define OT07_ALARM_HIGH_LSB 0x11 // OT07 Alarm High LSB #define OT07_ALARM_LOW_MSB 0x12 // OT07 Alarm Low MSB #define OT07_ALARM_LOW_LSB 0x13 // OT07 Alarm LOW LSB #define OT07_ADC_SETUP 0x14 // OT07 Temp Seneor Setup (ADC_RES[7:6]) & Convert Temperature [0] #define OT07_GPIO_SETUP 0x20 // OT07 GPIO Setup, sets GPIO modes #define OT07_GPIO_CTRL 0x21 // OT07 GPIO control #define OT07_ROM_ID 0x30 // OT07 ROM_ID address of LSB? #define ID_LENGTH 8 // Rom ID length in bytes #define BS 8 // ASCII Back Space #define CR 13 // ASCII Carriage Return //global variable struct OT07_struct { char rom_id[ID_LENGTH]; // device 8 byte ROM ID char I2C_address; // I2C addess, based on GPIO0 and GPIO1 at power up }; bool sample_flag; // global flag indicating its time to take next sample. //******************** init Feather Boared Hardware *********************** MAX32630FTHR pegasus(MAX32630FTHR::VIO_1V8); //Configure serial ports Serial db(P2_1, P2_0); // Hardware serial debug port over DAPLink, 9600 defult baudrate USBSerial pc; // Virtual serial port over USB // I2C setup I2C i2c(P3_4,P3_5); // P3_4 -> I2C1_SDA, P3_5-> I2C1_SCL //Timer setup Ticker timer_1; // timer for blinking led heartbeat and setting tick_flag Ticker timer_2; // timer for controling sample rate. //LED blink setup DigitalOut rLED(LED1); DigitalOut gLED(LED2); DigitalOut bLED(LED3); // ***************************************************************************** // LED_blink_callback() attached to timer1 interupt // blinks Feather board led and sets tick_flag true // ***************************************************************************** void LED_blink_callback(){ // LED Heart beat bLED=!bLED; //toggle Green LED } // ***************************************************************************** // set_sample_flag_callback() sets sample_flag = true// // ***************************************************************************** void set_sample_flag_callback(){ //set sample flag interrupt sample_flag = true; } // ***************************************************************************** // OT07_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 OT07_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); //if(DEBUG)db.printf("wr[%02X %02X %d]\r\n", data[0], data[1], error); return error; } /// **************************************************************************** // OT07_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 OT07_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; } // ***************************************************************************** // OT07_read_register(char, char, char *, int) writes single byte to 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 OT07_read_register(char I2C_add, char reg_add, char *bytes, int n){ int error; error = i2c.write(I2C_add,®_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; } // ***************************************************************************** // search_I2C_bus(OT07_struct *) searches I2C address 0xA0, 0xA2, 0xA4 and 0xA6 // OT07_struct * structure array to holds I2C address and rom_ids // returns number of devices found // ***************************************************************************** int search_I2C_bus(OT07_struct OT07[]){ char data[16]; char I2C_add; //char GPIO; int error; int device_count = 0; int i; int j; for(i = 0;i<4;i++){ I2C_add = 0xA0 + i*2; error = OT07_read_register(I2C_add,0xff,data,1); //if(DEBUG)db.printf("i2c[%02X] e[%d]\n\r",I2C_add,error); if(error == 0){ if(data[0] == 0x30){ OT07_read_register(I2C_add,OT07_GPIO_CTRL,data,1); //read GPIO location address //if(DEBUG)db.printf("Found device at address 0x%02X\n\rGPIO location %02X dc[%d]\r\n",I2C_add,data[0],device_count); OT07[device_count].I2C_address = I2C_add; OT07_read_register(I2C_add,OT07_ROM_ID,data,8); for(j=7;j>=0;j--){ OT07[device_count].rom_id[j] = data[j]; } device_count++; } } }//end for(i...) return device_count; }// end search_I2C() // ***************************************************************************** // convert_temperature(char) sends convert command to OT07 device // char I2C address // ***************************************************************************** void convert_temperature(char I2C_add){ // set convert bit to start conversion char data[2]; //read ADC_SETUP register 0x14 OT07_read_register(I2C_add,OT07_ADC_SETUP,data,1); //mask convert register value with 0x01 and write back register 0x14 OT07_write_register(I2C_add,OT07_ADC_SETUP, data[0]|0x01); } //****************************************************************************** // get_temperature(char) read temperature from OT07 device FIFO register // char I2C address // returns double temperature in oC //****************************************************************************** double get_temperature(char I2C_add){ char data[2]; double T; int count; OT07_read_register(I2C_add,OT07_FIFO_DATA,data,2); // Read temperature from FIFO, 2 bytes //if(DEBUG)db.printf("get_temperature -- FIFO[%02X %02X]\r\n",data[0],data[1]); //calculate temperture from data count = (int)(data[0]*256 + data[1]); if (count >= 32768)count = count - 65536; // 2s comp T = (double)count*0.005; return T; } //****************************************************************************** // print_device_list(OT07_struct *, int) prints list of devices found // OT07_struct* pointer to OT07 device structure array // int number of devices i array // returns 0 //****************************************************************************** int print_device_list(OT07_struct OT07[], int n){ int i; int j; for(j=0;j<n;j++){ // loop thru n devices pc.printf("%02d, ",j); // print device index pc.printf("%02X, ",OT07[j].I2C_address); // print I2C address pc.printf("%02X, ",OT07[j].rom_id[7]); // print CRC for(i=6;i>=1;i--){ pc.printf("%02X",OT07[j].rom_id[i]); // printf ROM ID } pc.printf(", %02X",OT07[j].rom_id[0]); // print family code pc.printf("\r\n"); } return 0; } //****************************************************************************** // main() //****************************************************************************** int main() { OT07_struct OT07[4]; // structure that holds I2C address and ROM_ID char data[130]; // char vector used for passing data to read and write register calls char s[128]; // temp char array int device_count = 0; // number of I2C devices found by search_I2C_bus() int i; // loop counter int j; // loop counter double T[4]; // holds temperature reading // i/o variables for serial com port char rx_buff[128]; // comport input buffer int rx_index; // rx_buffer pointer char c; // command type character char str[16]; // temp string int n; // argument count int arg0; // device argument int arg1; // argumnet 1 int arg2; // argument 2 int num_bytes; // calculated number of byte to read int period = 1000; // sample period in ms int sample_count = 0; // sample index for log int delay = 25; int i2c_freq = 1; // i2c clock frequency 0->100000kHz, 1->400000kHz bool log_flag = false; // true -> log temperature to serial port, false -> do not log bool ext_convert_flag = true; int echo = 1; // 0 -> echo off, 1 -> echo terminal input and use verbose output int L3out = 1800; // Sets mV for L3OUT (3V3 on DS2484 Feather Wing board) 1800 to 3600 mV allowed. //************* init ticker timer callbacks **************** timer_1.attach(&LED_blink_callback,1.0); //start ticker interupt, once per sec. //********************* init I2C port *********************** i2c.frequency(i2c_freq); //set I2C clock 0-->100kHz, 1-->400kHz //******************* init VDD (L3OUT) ********************** if(DEBUG)db.printf("set LDO3 to %dmV\r\n",L3out); pegasus.max14690.ldo3SetVoltage(L3out); // sets VDD and I2C to L3out //********* echo firmware info to both serial ports ********* wait(1); //wait 1 sec for USB serial port to init. sprintf(s,"--- MAX30208 I2C Terminal Interface V0.3 ---\r\n"); if(DEBUG)db.printf("%s",s); pc.printf("%s",s); pc.printf("VDD = %dmV, I2C clock = %dkHz\r\n",L3out, 100*(i2c_freq*3 + 1)); //********************** init LEDs ************************* rLED = LED_OFF; gLED = LED_ON; bLED = LED_OFF; //******************** Find I2C devices on bus ************** pc.printf("<search for devices>\r\n"); device_count = search_I2C_bus(OT07); pc.printf("<device, I2C Add, CRC, ROM ID, Family>\r\n"); print_device_list(OT07, device_count); //************* init rx input buffer index ****************** rx_index = 0; sample_flag = false; //************** start main loop *************************** if(DEBUG)db.printf("start Main loop\r\n"); while(1) { // start main loop, take data if log flag true, check for input, repeat //wait(0.2); if(log_flag == true){ if(sample_flag == true){// take sample. sample_flag = false; convert_temperature(OT07[0].I2C_address); wait_ms(delay); T[0] = get_temperature(OT07[0].I2C_address); pc.printf("%5d, %7.3f\r\n",sample_count++,T[0]); } }// end if(log_flag == true) // ---------------------------------------------------------------------------- // test for charater input for USB com port // ---------------------------------------------------------------------------- //test if PC sent some charaters while(pc.readable()){ //characters in buffer, get them rx_buff[rx_index] = pc.getc(); if(echo)pc.putc(rx_buff[rx_index]); //echo character //pc.printf("<[%02x] %c i[%d]>",rx_buff[i],rx_buff[i],i); //echo charater if(rx_buff[rx_index] == CR){ //if(DEBUG)db.printf("\r\n"); if(echo)pc.printf("\r\n"); rx_buff[++rx_index] = 0; if(DEBUG)db.printf("%s",rx_buff); //pc.printf("%s\r\n",rx_buff); rx_index = -1; // because i++ at end of while give i=0 on next loop arg0 = 0; arg1 = 0; arg2 = 0; n = sscanf(rx_buff, " %c %d %x %x", &c, &arg0, &arg1, &arg2); //if(DEBUG)db.printf("c[%c] d[%d] a1[%x] a2[%x] n[%d]\r\n",c,arg0,arg1,arg2,n); //echo values read in //process input if(n > 0){//got input so process it switch(c){ case 'd': case 'D': // Delay after convert command sent (ms) if(n == 2){ delay = arg0; if(delay < 5)delay = 5; if(delay > 1000)delay = 1000; } if(echo)pc.printf("<delay = %dms>\r\n",delay); break; case 'e': case 'E': // Turn echo ON/OFF if(arg0 == 0){ echo = 0; }else{ echo = 1; pc.printf("<echo on>\r\n"); } break; case 'f': case 'F': // change I2C Frequency if(n == 2){ if((arg0 == 0)||(arg0 == 1)){ i2c_freq = arg0; i2c.frequency(i2c_freq); } } if(echo)pc.printf("<I2C Frequency = %dkHz>\r\n",100*(i2c_freq*3 + 1)); break; case 'h': case 'H': case '?': //print command list pc.printf("Command Help\r\n"); pc.printf("\r\n"); pc.printf("d ms Set delay time for read command after convert command in ms\r\n"); pc.printf(" ms, Delay time in ms (int) \r\n"); pc.printf(" 5ms through 10000ms allowed \r\n"); pc.printf("\r\n"); pc.printf("e n Terminal command echo on/off\r\n"); pc.printf(" n, Echo ON/OFF flag (int)\n\r"); pc.printf(" 0 -> echo off\r\n"); pc.printf(" 1 -> echo on\r\n"); pc.printf("\r\n"); pc.printf("f n I2C Clock Frequency set\r\n"); pc.printf(" n, Frequency Index (int)\n\r"); pc.printf(" 0 -> 100kHz\r\n"); pc.printf(" 1 -> 400kHz on\r\n"); pc.printf("\r\n"); pc.printf("h,? Prints Command Help\r\n"); pc.printf("\r\n"); pc.printf("l [ms] Start/Stop interval logging output to terminal\r\n"); pc.printf(" ms, if included sets logging interval in ms (int)\r\n"); pc.printf(" ms = 0 turns off loging\r\n"); pc.printf("\r\n"); pc.printf("p ms Set logging sample period in ms\r\n"); pc.printf(" ms, Convert period in ms (int) \r\n"); pc.printf(" 20ms through 60,000ms allowed \r\n"); pc.printf("\r\n"); pc.printf("r d add [end_add] Read device regester\r\n"); pc.printf(" d, device index (int)\r\n"); pc.printf(" add, address to read (hex)\r\n"); pc.printf(" end_add, if included read all registers from add to end_add (hex)\r\n"); pc.printf("\r\n"); pc.printf("s Search I2C bus for all attached devices\r\n"); pc.printf("\r\n"); pc.printf("t d [end_d] Send convert temperature command to device and read temperature\r\n"); pc.printf(" d, device index (int)\r\n"); pc.printf(" end_d, if included sends skip ROM convert command (int)\r\n"); pc.printf(" and reads back from device d through end_d\r\n"); pc.printf("\r\n"); pc.printf("w d add data Write to device register\r\n"); pc.printf(" d, device index (int)\r\n"); pc.printf(" add, write address (hex)\r\n"); pc.printf(" data, data to write (hex)\r\n"); pc.printf("\r\n"); pc.printf("v mV Set VDD of device\r\n"); pc.printf(" mV, VDD in mV (int)\r\n"); pc.printf(" 1800mV to 3600mV allowed in 100mV steps"); pc.printf("\r\n"); break; case 'l': case 'L': // Toggle logging if((n==2)&&(arg0 == 0)){ //force stop if(echo)pc.printf("<stop logging [by 0]>\r\n"); log_flag = false; timer_2.detach(); sample_flag = false; }else{ if(n == 2){ period = arg0; if(period < 5)period = 5; if(period > 60000)period = 60000; } if(log_flag == false){ //start logging if(echo)pc.printf("<start logging, period = %dms>\r\n",period); sample_count = 0; if(period > 1000){// dont wait for first tick sample_flag = true; }else{ sample_flag = false; } log_flag = true; timer_2.attach_us(&set_sample_flag_callback,period*1000); //start ticker interupt. }else{ // n != 2 and log_flag = true if(echo)pc.printf("<stop logging>\r\n"); log_flag = false; timer_2.detach(); sample_flag = false; } }// end else if((n==2)&&(arg0==0)) break; case 'p': case 'P': //Set sample period in ms if(n == 2){ period = arg0; if(period < 20)period = 20; if(period > 60000)period = 60000; } if(log_flag == true){ //update sample_flag interrupt period timer_2.detach(); // stop current timer if(echo)pc.printf("<period = %dmS>\r\n",period); timer_2.attach_us(&set_sample_flag_callback,period*1000); // restart with new period }else{ if(echo)pc.printf("<set sampling period, %dmS>\r\n",period); } break; case 'r': case 'R': //read register "r device radd.start radd.end" if(n==3){ //read single register from selected device OT07_read_register(OT07[arg0].I2C_address,arg1,data,1); if(echo){ pc.printf("device[%02d] add[%02X] data[%02X] \r\n",arg0,arg1,data[0]); }else{ pc.printf("%02d, %02X, %02X\r\n",arg0,arg1,data[0]); } } if(n==4){ //read a range of regesters from selected device num_bytes = arg2-arg1 + 1; // calculate number of bytes to read if (num_bytes < 1) num_bytes = 1; // if arg2 <= arg 1 just read arg1 address. OT07_read_register(OT07[arg0].I2C_address,arg1,data,num_bytes); for(i=0;i<num_bytes;i++){ if(echo){ pc.printf("\r\ndevice[%02d] add[%02X] data[%02X]",arg0,arg1+i,data[i]); }else{ pc.printf("%02d, %02X, %02X\r\n",arg0,arg1+i,data[i]); } } if(echo)pc.printf("\r\n"); } break; case 's': case 'S': // ****************** search for I2C devices on bus ***************** device_count = search_I2C_bus(OT07); if(echo){ pc.printf("<search I2C bus>\r\n"); pc.printf("<count>\r\n"); pc.printf("<device, I2C Add, CRC, ROM ID, Family>\r\n"); } pc.printf("%2d\r\n",device_count); print_device_list(OT07,device_count); break; case 'T': case 't': if(n == 2){//get temperatures from selected device convert_temperature(OT07[arg0].I2C_address); //send OW convert selected device wait(0.02); //wait 20 ms for convert temperature to complete T[arg0] = get_temperature(OT07[arg0].I2C_address); if(echo)pc.printf("<temperature>\r\n"); pc.printf("%02d, %7.3f\r\n",arg0, T[arg0]); } if(n == 3){ // "t 1 3" get temperature for devices 1 thru 3 sprintf(str,"%x",arg1); //convert arg1 input as hex to decimal i.e. 0x10 becomes 10 dec sscanf(str,"%d",&arg1); for(j=arg0;j<=arg1;j++){ convert_temperature(OT07[j].I2C_address); //send convert to all devices wait(0.02); //wait 20ms for convert temperature to complete T[j] = get_temperature(OT07[j].I2C_address); } if(echo)pc.printf("<device, temperature>\r\n"); for(j=arg0;j<=arg1;j++){ pc.printf("%02d, %7.3f\r\n",j,T[j]); } } break; case 'w': case 'W': //write register //data[0] = arg2; OT07_write_register(OT07[arg0].I2C_address,arg1, arg2); if(echo)pc.printf("write -- add[%02X] data[%02X]\r\n",arg1,arg2); break; case 'v': case 'V': //Set MAX32630FTHR I/O Voltage 0 -> 1.8V, 1 -> 3.3V if(n == 2){ //set LDO3 L3out = arg0; if(L3out < 1600)L3out = 1600; // check for valid mV range if(L3out > 3600)L3out = 3600; L3out = ((L3out+50)/100)*100; // round to 100mV steps pegasus.max14690.ldo3SetVoltage(L3out); // set ldo3 to L3out if(echo)pc.printf("<Set ldo3 (VDD) to %4dmV, ",L3out); if(DEBUG)db.printf("<ldo3 to %4dmV>\r\n",L3out); if(L3out >= 1900){ //set VIO to 3300mV // set VIO to 3v3 pegasus.vddioh(P3_4, pegasus.VIO_3V3); // SDA use LDO2 pegasus.vddioh(P3_5, pegasus.VIO_3V3); // SCL use LDO2 pegasus.vddioh(P5_3, pegasus.VIO_3V3); // GPIO0 use LDO2 pegasus.vddioh(P5_6, pegasus.VIO_3V3); // GPIO1 use LDO2 if(echo)pc.printf(" Set VIO=3V3>\r\n"); }else{//set VIO to 1V8 pegasus.vddioh(P3_4, pegasus.VIO_1V8); // SDA use 1V8 buck pegasus.vddioh(P3_5, pegasus.VIO_1V8); // SCL use 1V8 buck pegasus.vddioh(P5_3, pegasus.VIO_1V8); // GPIO0 use 1V8 buck pegasus.vddioh(P5_6, pegasus.VIO_1V8); // GPIO1 use 1V8 buck if(echo)pc.printf(" Set VIO=1V8>\r\n"); } }else{ if(echo)pc.printf("<ldo3 (VDD) %4dmV>\r\n",L3out); } break; }//end switch(c) }//if(n>0) }//end if(CR) 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(pc.redable()) }//end while(1) Main Loop }// end_Main