MAX30208 I2C Terminal Interface
Dependencies: max32630fthr USBDevice
Diff: MAX30208_I2C_Terminal_Interface.cpp
- Revision:
- 17:65cd58826416
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX30208_I2C_Terminal_Interface.cpp Fri Sep 04 21:15:38 2020 +0000 @@ -0,0 +1,632 @@ +#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 \ No newline at end of file