This is one of the demo programs for the MAX30003WING. The program outputs the raw data serially to graphically reproduce the QRS complex. A serial plotter is needed to graph the data.

Dependencies:   MAX30003 max32630fthr

Fork of MAX30003_Demo_Plot by John Greene

Committer:
coreyharris
Date:
Tue Aug 29 20:27:26 2017 +0000
Revision:
6:86ac850c718d
Parent:
5:f8d1f651bef5
Child:
7:cf0855a0450a
updated comments, added ECG FIFO bitmasks and EINT interrupt bitmask

Who changed what in which revision?

UserRevisionLine numberNew contents of line
coreyharris 6:86ac850c718d 1 /*******************************************************************************
coreyharris 6:86ac850c718d 2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
coreyharris 6:86ac850c718d 3 *
coreyharris 6:86ac850c718d 4 * Permission is hereby granted, free of charge, to any person obtaining a
coreyharris 6:86ac850c718d 5 * copy of this software and associated documentation files (the "Software"),
coreyharris 6:86ac850c718d 6 * to deal in the Software without restriction, including without limitation
coreyharris 6:86ac850c718d 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
coreyharris 6:86ac850c718d 8 * and/or sell copies of the Software, and to permit persons to whom the
coreyharris 6:86ac850c718d 9 * Software is furnished to do so, subject to the following conditions:
coreyharris 6:86ac850c718d 10 *
coreyharris 6:86ac850c718d 11 * The above copyright notice and this permission notice shall be included
coreyharris 6:86ac850c718d 12 * in all copies or substantial portions of the Software.
coreyharris 6:86ac850c718d 13 *
coreyharris 6:86ac850c718d 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
coreyharris 6:86ac850c718d 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
coreyharris 6:86ac850c718d 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
coreyharris 6:86ac850c718d 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
coreyharris 6:86ac850c718d 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
coreyharris 6:86ac850c718d 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
coreyharris 6:86ac850c718d 20 * OTHER DEALINGS IN THE SOFTWARE.
coreyharris 6:86ac850c718d 21 *
coreyharris 6:86ac850c718d 22 * Except as contained in this notice, the name of Maxim Integrated
coreyharris 6:86ac850c718d 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
coreyharris 6:86ac850c718d 24 * Products, Inc. Branding Policy.
coreyharris 6:86ac850c718d 25 *
coreyharris 6:86ac850c718d 26 * The mere transfer of this software does not imply any licenses
coreyharris 6:86ac850c718d 27 * of trade secrets, proprietary technology, copyrights, patents,
coreyharris 6:86ac850c718d 28 * trademarks, maskwork rights, or any other form of intellectual
coreyharris 6:86ac850c718d 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
coreyharris 6:86ac850c718d 30 * ownership rights.
coreyharris 6:86ac850c718d 31 *******************************************************************************
coreyharris 6:86ac850c718d 32 */
coreyharris 6:86ac850c718d 33
coreyharris 6:86ac850c718d 34
coreyharris 6:86ac850c718d 35
coreyharris 0:38c49bc37c7c 36 #include "mbed.h"
coreyharris 0:38c49bc37c7c 37 #include "max32630fthr.h"
coreyharris 0:38c49bc37c7c 38 #include "MAX30003.h"
coreyharris 0:38c49bc37c7c 39
coreyharris 0:38c49bc37c7c 40 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
coreyharris 0:38c49bc37c7c 41
coreyharris 0:38c49bc37c7c 42 void ecg_config(MAX30003 &ecgAFE);
coreyharris 0:38c49bc37c7c 43
coreyharris 0:38c49bc37c7c 44 /* ECG FIFO nearly full callback */
coreyharris 0:38c49bc37c7c 45 volatile bool ecgFIFOIntFlag = 0;
coreyharris 0:38c49bc37c7c 46 void ecgFIFO_callback() {
coreyharris 0:38c49bc37c7c 47
coreyharris 0:38c49bc37c7c 48 ecgFIFOIntFlag = 1;
coreyharris 0:38c49bc37c7c 49
coreyharris 0:38c49bc37c7c 50 }
coreyharris 0:38c49bc37c7c 51
coreyharris 0:38c49bc37c7c 52 int main()
coreyharris 3:420d5efbd967 53 {
coreyharris 6:86ac850c718d 54
coreyharris 6:86ac850c718d 55 // Constants
coreyharris 4:06e258ff0b97 56 const int EINT_STATUS_MASK = 1 << 23;
coreyharris 6:86ac850c718d 57 const int FIFO_OVF_MASK = 0x7;
coreyharris 6:86ac850c718d 58 const int FIFO_VALID_SAMPLE_MASK = 0x0;
coreyharris 6:86ac850c718d 59 const int FIFO_FAST_SAMPLE_MASK = 0x1;
coreyharris 6:86ac850c718d 60 const int ETAG_BITS_MASK = 0x7;
coreyharris 3:420d5efbd967 61
coreyharris 6:86ac850c718d 62 // Ports and serial connections
coreyharris 1:86843c27cc81 63 Serial pc(USBTX, USBRX); // Use USB debug probe for serial link
coreyharris 1:86843c27cc81 64 pc.baud(115200); // Baud rate = 115200
coreyharris 1:86843c27cc81 65
coreyharris 1:86843c27cc81 66 DigitalOut rLed(LED1, LED_OFF); // Debug LEDs
coreyharris 0:38c49bc37c7c 67 DigitalOut gLed(LED2, LED_OFF);
coreyharris 0:38c49bc37c7c 68 DigitalOut bLed(LED3, LED_OFF);
coreyharris 0:38c49bc37c7c 69
coreyharris 1:86843c27cc81 70 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
coreyharris 1:86843c27cc81 71 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
coreyharris 0:38c49bc37c7c 72
coreyharris 1:86843c27cc81 73 SPI spiBus(SPI2_MOSI, SPI2_MISO, SPI2_SCK); // SPI bus, P5_1 = MOSI,
coreyharris 1:86843c27cc81 74 // P5_2 = MISO, P5_0 = SCK
coreyharris 0:38c49bc37c7c 75
coreyharris 4:06e258ff0b97 76 MAX30003 ecgAFE(spiBus, P5_3); // New MAX30003 on spiBus, CS = P5_3
coreyharris 4:06e258ff0b97 77 ecg_config(ecgAFE); // Config ECG
coreyharris 1:86843c27cc81 78
coreyharris 0:38c49bc37c7c 79
coreyharris 4:06e258ff0b97 80 ecgAFE.writeRegister( MAX30003::SYNCH , 0);
coreyharris 0:38c49bc37c7c 81
coreyharris 4:06e258ff0b97 82 uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
coreyharris 1:86843c27cc81 83 int16_t ecgSample[32];
coreyharris 2:812d40f1853d 84
coreyharris 1:86843c27cc81 85 while(1) {
coreyharris 1:86843c27cc81 86
coreyharris 4:06e258ff0b97 87 // Read back ECG samples from the FIFO
coreyharris 0:38c49bc37c7c 88 if( ecgFIFOIntFlag ) {
coreyharris 2:812d40f1853d 89
coreyharris 5:f8d1f651bef5 90 ecgFIFOIntFlag = 0;
coreyharris 4:06e258ff0b97 91 status = ecgAFE.readRegister( MAX30003::STATUS ); // Read the STATUS register
coreyharris 2:812d40f1853d 92
coreyharris 3:420d5efbd967 93 // Check if EINT interrupt asserted
coreyharris 3:420d5efbd967 94 if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
coreyharris 3:420d5efbd967 95
coreyharris 4:06e258ff0b97 96 readECGSamples = 0; // Reset sample counter
coreyharris 3:420d5efbd967 97
coreyharris 2:812d40f1853d 98 do {
coreyharris 6:86ac850c718d 99 ecgFIFO = ecgAFE.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
coreyharris 4:06e258ff0b97 100 ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
coreyharris 6:86ac850c718d 101 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK; // Isolate ETAG
coreyharris 4:06e258ff0b97 102 readECGSamples++; // Increment sample counter
coreyharris 3:420d5efbd967 103
coreyharris 3:420d5efbd967 104 // Check that sample is not last sample in FIFO
coreyharris 6:86ac850c718d 105 } while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
coreyharris 6:86ac850c718d 106 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
coreyharris 2:812d40f1853d 107
coreyharris 3:420d5efbd967 108 // Check if FIFO has overflowed
coreyharris 6:86ac850c718d 109 if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
coreyharris 3:420d5efbd967 110 ecgAFE.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
coreyharris 3:420d5efbd967 111 }
coreyharris 3:420d5efbd967 112
coreyharris 4:06e258ff0b97 113 // Print results
coreyharris 4:06e258ff0b97 114 for( idx = 0; idx < readECGSamples; idx++ ) {
coreyharris 6:86ac850c718d 115 pc.printf("%6d\r\n", ecgSample[idx]);
coreyharris 6:86ac850c718d 116 }
coreyharris 6:86ac850c718d 117
coreyharris 0:38c49bc37c7c 118 }
coreyharris 0:38c49bc37c7c 119 }
coreyharris 0:38c49bc37c7c 120 }
coreyharris 0:38c49bc37c7c 121 }
coreyharris 0:38c49bc37c7c 122
coreyharris 0:38c49bc37c7c 123
coreyharris 0:38c49bc37c7c 124
coreyharris 0:38c49bc37c7c 125
coreyharris 0:38c49bc37c7c 126 void ecg_config(MAX30003& ecgAFE) {
coreyharris 0:38c49bc37c7c 127
coreyharris 1:86843c27cc81 128 // Reset ECG to clear registers
coreyharris 1:86843c27cc81 129 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
coreyharris 0:38c49bc37c7c 130
coreyharris 1:86843c27cc81 131 // General config register setting
coreyharris 1:86843c27cc81 132 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
coreyharris 3:420d5efbd967 133 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
coreyharris 3:420d5efbd967 134 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
coreyharris 3:420d5efbd967 135 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
coreyharris 3:420d5efbd967 136 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
coreyharris 3:420d5efbd967 137 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
coreyharris 3:420d5efbd967 138 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
coreyharris 1:86843c27cc81 139 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
coreyharris 1:86843c27cc81 140
coreyharris 1:86843c27cc81 141
coreyharris 1:86843c27cc81 142 // ECG Config register setting
coreyharris 1:86843c27cc81 143 MAX30003::ECGConfiguration_u CNFG_ECG_r;
coreyharris 3:420d5efbd967 144 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
coreyharris 3:420d5efbd967 145 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
coreyharris 3:420d5efbd967 146 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
coreyharris 3:420d5efbd967 147 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
coreyharris 1:86843c27cc81 148 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
coreyharris 1:86843c27cc81 149
coreyharris 1:86843c27cc81 150
coreyharris 1:86843c27cc81 151 //R-to-R configuration
coreyharris 1:86843c27cc81 152 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
coreyharris 3:420d5efbd967 153 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
coreyharris 1:86843c27cc81 154 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
coreyharris 1:86843c27cc81 155
coreyharris 1:86843c27cc81 156
coreyharris 1:86843c27cc81 157 //Manage interrupts register setting
coreyharris 1:86843c27cc81 158 MAX30003::ManageInterrupts_u MNG_INT_r;
coreyharris 3:420d5efbd967 159 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
coreyharris 3:420d5efbd967 160 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
coreyharris 1:86843c27cc81 161 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
coreyharris 0:38c49bc37c7c 162
coreyharris 0:38c49bc37c7c 163
coreyharris 1:86843c27cc81 164 //Enable interrupts register setting
coreyharris 1:86843c27cc81 165 MAX30003::EnableInterrupts_u EN_INT_r;
coreyharris 5:f8d1f651bef5 166 EN_INT_r.all = 0;
coreyharris 3:420d5efbd967 167 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
coreyharris 4:06e258ff0b97 168 EN_INT_r.bits.en_rrint = 0; // Disable R-to-R interrupt
coreyharris 3:420d5efbd967 169 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
coreyharris 1:86843c27cc81 170 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
coreyharris 1:86843c27cc81 171
coreyharris 1:86843c27cc81 172
coreyharris 1:86843c27cc81 173 //Dyanmic modes config
coreyharris 1:86843c27cc81 174 MAX30003::ManageDynamicModes_u MNG_DYN_r;
coreyharris 3:420d5efbd967 175 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
coreyharris 1:86843c27cc81 176 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
coreyharris 5:f8d1f651bef5 177
coreyharris 5:f8d1f651bef5 178 // MUX Config
coreyharris 5:f8d1f651bef5 179 MAX30003::MuxConfiguration_u CNFG_MUX_r;
coreyharris 5:f8d1f651bef5 180 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
coreyharris 5:f8d1f651bef5 181 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
coreyharris 5:f8d1f651bef5 182 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
coreyharris 1:86843c27cc81 183
coreyharris 1:86843c27cc81 184 return;
coreyharris 0:38c49bc37c7c 185 }
coreyharris 0:38c49bc37c7c 186