diff --git a/.DS_Store b/.DS_Store index e76291e..4589208 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 015918b..009713f 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -1,25 +1,29 @@ name: Compile Examples +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows on: - pull_request: + push: paths: - ".github/workflows/compile-examples.yml" - "examples/**" - "src/**" - push: + pull_request: paths: - ".github/workflows/compile-examples.yml" - "examples/**" - "src/**" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms). + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: jobs: build: + name: ${{ matrix.board.fqbn }} runs-on: ubuntu-latest env: - UNIVERSAL_LIBRARIES: | - - source-path: ./ - SKETCHES_REPORTS_PATH: sketches-reports strategy: @@ -27,40 +31,28 @@ jobs: matrix: board: - - fqbn: arduino:avr:uno + - fqbn: arduino:avr:nano platforms: | - name: arduino:avr - - fqbn: arduino:samd:mkr1000 - platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrzero - platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrwifi1010 - platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrfox1200 - platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrwan1300 + - fqbn: arduino:avr:mega platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrwan1310 + - name: arduino:avr + - fqbn: arduino:avr:leonardo platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrgsm1400 + - name: arduino:avr + - fqbn: arduino:megaavr:nona4809 platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrnb1500 + - name: arduino:megaavr + - fqbn: arduino:sam:arduino_due_x_dbg platforms: | - - name: arduino:samd - - fqbn: arduino:samd:mkrvidor4000 + - name: arduino:sam + - fqbn: arduino:samd:mkrzero platforms: | - name: arduino:samd - - fqbn: arduino:mbed_portenta:envie_m7 + - fqbn: arduino:mbed_portenta:envie_m7:target_core=cm4 platforms: | - name: arduino:mbed_portenta - - fqbn: arduino:mbed_portenta:envie_m4 + - fqbn: arduino:mbed_portenta:envie_m7 platforms: | - name: arduino:mbed_portenta - fqbn: arduino:mbed_nano:nano33ble @@ -69,37 +61,30 @@ jobs: - fqbn: arduino:mbed_nano:nanorp2040connect platforms: | - name: arduino:mbed_nano - - fqbn: arduino:mbed_edge:edge_control - platforms: | - - name: arduino:mbed_edge - - fqbn: esp32:esp32:esp32 - platforms: | - - name: esp32:esp32 - source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - - fqbn: rp2040:rp2040:rpipico - platforms: | - - name: rp2040:rp2040 - source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@v3 - - name: Install ESP32 platform dependencies - if: startsWith(matrix.board.fqbn, 'esp32:esp32') - run: pip3 install pyserial - - name: Compile examples uses: arduino/compile-sketches@v1 with: + github-token: ${{ secrets.GITHUB_TOKEN }} fqbn: ${{ matrix.board.fqbn }} platforms: ${{ matrix.board.platforms }} + libraries: | + # Install the library from the local path. + - source-path: ./ + # Additional library dependencies can be listed here. + # See: https://github.com/arduino/compile-sketches#libraries + sketch-paths: | + - examples enable-deltas-report: true sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} - - name: Save memory usage change report as artifact - if: github.event_name == 'pull_request' + - name: Save sketches report as workflow artifact uses: actions/upload-artifact@v3 with: - name: ${{ env.SKETCHES_REPORTS_PATH }} + if-no-files-found: error path: ${{ env.SKETCHES_REPORTS_PATH }} + name: ${{ env.SKETCHES_REPORTS_PATH }} \ No newline at end of file diff --git a/.vscode/arduino.json b/.vscode/arduino.json new file mode 100644 index 0000000..723b771 --- /dev/null +++ b/.vscode/arduino.json @@ -0,0 +1,5 @@ +{ + "port": "/dev/tty.usbmodem212301", + "board": "arduino:avr:uno", + "sketch": "examples/Example1-ECG-BioZ-stream-Openview/Example1-ECG-BioZ-stream-Openview.ino" +} \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..1f34f71 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,539 @@ +{ + "version": 4, + "configurations": [ + { + "name": "Arduino", + "compilerPath": "/Users/akw/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", + "compilerArgs": [ + "-w", + "-std=gnu++11", + "-fpermissive", + "-fno-exceptions", + "-ffunction-sections", + "-fdata-sections", + "-fno-threadsafe-statics", + "-Wno-error=narrowing" + ], + "intelliSenseMode": "gcc-x64", + "includePath": [ + "/Users/akw/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino", + "/Users/akw/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/standard", + "/Users/akw/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/libraries/SPI/src", + "/Users/akw/Documents/Arduino/libraries/protocentral_max30001_arduino_library/src", + "/Users/akw/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/lib/gcc/avr/7.3.0/include", + "/Users/akw/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/lib/gcc/avr/7.3.0/include-fixed", + "/Users/akw/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include" + ], + "forcedInclude": [ + "/Users/akw/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino/Arduino.h" + ], + "cStandard": "c11", + "cppStandard": "c++11", + "defines": [ + "F_CPU=16000000L", + "ARDUINO=10607", + "ARDUINO_AVR_UNO", + "ARDUINO_ARCH_AVR", + "__DBL_MIN_EXP__=(-125)", + "__HQ_FBIT__=15", + "__cpp_attributes=200809", + "__UINT_LEAST16_MAX__=0xffffU", + "__ATOMIC_ACQUIRE=2", + "__SFRACT_IBIT__=0", + "__FLT_MIN__=1.17549435e-38F", + "__GCC_IEC_559_COMPLEX=0", + "__BUILTIN_AVR_SLEEP=1", + "__BUILTIN_AVR_COUNTLSULLK=1", + "__cpp_aggregate_nsdmi=201304", + "__BUILTIN_AVR_COUNTLSULLR=1", + "__UFRACT_MAX__=0XFFFFP-16UR", + "__UINT_LEAST8_TYPE__=unsigned char", + "__DQ_FBIT__=63", + "__INTMAX_C(c)=c ## LL", + "__ULFRACT_FBIT__=32", + "__SACCUM_EPSILON__=0x1P-7HK", + "__CHAR_BIT__=8", + "__USQ_IBIT__=0", + "__UINT8_MAX__=0xff", + "__ACCUM_FBIT__=15", + "__WINT_MAX__=0x7fff", + "__FLT32_MIN_EXP__=(-125)", + "__cpp_static_assert=200410", + "__USFRACT_FBIT__=8", + "__ORDER_LITTLE_ENDIAN__=1234", + "__SIZE_MAX__=0xffffU", + "__WCHAR_MAX__=0x7fff", + "__LACCUM_IBIT__=32", + "__DBL_DENORM_MIN__=double(1.40129846e-45L)", + "__GCC_ATOMIC_CHAR_LOCK_FREE=1", + "__GCC_IEC_559=0", + "__FLT_EVAL_METHOD__=0", + "__BUILTIN_AVR_LLKBITS=1", + "__cpp_binary_literals=201304", + "__LLACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-47LLK", + "__GCC_ATOMIC_CHAR32_T_LOCK_FREE=1", + "__BUILTIN_AVR_HKBITS=1", + "__BUILTIN_AVR_BITSLLK=1", + "__FRACT_FBIT__=15", + "__BUILTIN_AVR_BITSLLR=1", + "__cpp_variadic_templates=200704", + "__UINT_FAST64_MAX__=0xffffffffffffffffULL", + "__SIG_ATOMIC_TYPE__=char", + "__BUILTIN_AVR_UHKBITS=1", + "__UACCUM_FBIT__=16", + "__DBL_MIN_10_EXP__=(-37)", + "__FINITE_MATH_ONLY__=0", + "__cpp_variable_templates=201304", + "__LFRACT_IBIT__=0", + "__GNUC_PATCHLEVEL__=0", + "__FLT32_HAS_DENORM__=1", + "__LFRACT_MAX__=0X7FFFFFFFP-31LR", + "__UINT_FAST8_MAX__=0xff", + "__has_include(STR)=__has_include__(STR)", + "__DEC64_MAX_EXP__=385", + "__INT8_C(c)=c", + "__INT_LEAST8_WIDTH__=8", + "__UINT_LEAST64_MAX__=0xffffffffffffffffULL", + "__SA_FBIT__=15", + "__SHRT_MAX__=0x7fff", + "__LDBL_MAX__=3.40282347e+38L", + "__FRACT_MAX__=0X7FFFP-15R", + "__UFRACT_FBIT__=16", + "__UFRACT_MIN__=0.0UR", + "__UINT_LEAST8_MAX__=0xff", + "__GCC_ATOMIC_BOOL_LOCK_FREE=1", + "__UINTMAX_TYPE__=long long unsigned int", + "__LLFRACT_EPSILON__=0x1P-63LLR", + "__BUILTIN_AVR_DELAY_CYCLES=1", + "__DEC32_EPSILON__=1E-6DF", + "__FLT_EVAL_METHOD_TS_18661_3__=0", + "__UINT32_MAX__=0xffffffffUL", + "__GXX_EXPERIMENTAL_CXX0X__=1", + "__ULFRACT_MAX__=0XFFFFFFFFP-32ULR", + "__TA_IBIT__=16", + "__LDBL_MAX_EXP__=128", + "__WINT_MIN__=(-__WINT_MAX__ - 1)", + "__INT_LEAST16_WIDTH__=16", + "__ULLFRACT_MIN__=0.0ULLR", + "__SCHAR_MAX__=0x7f", + "__WCHAR_MIN__=(-__WCHAR_MAX__ - 1)", + "__INT64_C(c)=c ## LL", + "__DBL_DIG__=6", + "__GCC_ATOMIC_POINTER_LOCK_FREE=1", + "__AVR_HAVE_SPH__=1", + "__LLACCUM_MIN__=(-0X1P15LLK-0X1P15LLK)", + "__BUILTIN_AVR_KBITS=1", + "__BUILTIN_AVR_ABSK=1", + "__BUILTIN_AVR_ABSR=1", + "__SIZEOF_INT__=2", + "__SIZEOF_POINTER__=2", + "__GCC_ATOMIC_CHAR16_T_LOCK_FREE=1", + "__USACCUM_IBIT__=8", + "__USER_LABEL_PREFIX__", + "__STDC_HOSTED__=1", + "__LDBL_HAS_INFINITY__=1", + "__LFRACT_MIN__=(-0.5LR-0.5LR)", + "__HA_IBIT__=8", + "__FLT32_DIG__=6", + "__TQ_IBIT__=0", + "__FLT_EPSILON__=1.19209290e-7F", + "__GXX_WEAK__=1", + "__SHRT_WIDTH__=16", + "__USFRACT_IBIT__=0", + "__LDBL_MIN__=1.17549435e-38L", + "__FRACT_MIN__=(-0.5R-0.5R)", + "__AVR_SFR_OFFSET__=0x20", + "__DEC32_MAX__=9.999999E96DF", + "__cpp_threadsafe_static_init=200806", + "__DA_IBIT__=32", + "__INT32_MAX__=0x7fffffffL", + "__UQQ_FBIT__=8", + "__INT_WIDTH__=16", + "__SIZEOF_LONG__=4", + "__UACCUM_MAX__=0XFFFFFFFFP-16UK", + "__UINT16_C(c)=c ## U", + "__PTRDIFF_WIDTH__=16", + "__DECIMAL_DIG__=9", + "__LFRACT_EPSILON__=0x1P-31LR", + "__AVR_2_BYTE_PC__=1", + "__ULFRACT_MIN__=0.0ULR", + "__INTMAX_WIDTH__=64", + "__has_include_next(STR)=__has_include_next__(STR)", + "__BUILTIN_AVR_ULLRBITS=1", + "__LDBL_HAS_QUIET_NAN__=1", + "__ULACCUM_IBIT__=32", + "__UACCUM_EPSILON__=0x1P-16UK", + "__BUILTIN_AVR_SEI=1", + "__GNUC__=7", + "__ULLACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-48ULLK", + "__cpp_delegating_constructors=200604", + "__HQ_IBIT__=0", + "__BUILTIN_AVR_SWAP=1", + "__FLT_HAS_DENORM__=1", + "__SIZEOF_LONG_DOUBLE__=4", + "__BIGGEST_ALIGNMENT__=1", + "__STDC_UTF_16__=1", + "__UINT24_MAX__=16777215UL", + "__BUILTIN_AVR_NOP=1", + "__GNUC_STDC_INLINE__=1", + "__DQ_IBIT__=0", + "__FLT32_HAS_INFINITY__=1", + "__DBL_MAX__=double(3.40282347e+38L)", + "__ULFRACT_IBIT__=0", + "__cpp_raw_strings=200710", + "__INT_FAST32_MAX__=0x7fffffffL", + "__DBL_HAS_INFINITY__=1", + "__INT64_MAX__=0x7fffffffffffffffLL", + "__ACCUM_IBIT__=16", + "__DEC32_MIN_EXP__=(-94)", + "__BUILTIN_AVR_UKBITS=1", + "__INTPTR_WIDTH__=16", + "__BUILTIN_AVR_FMULSU=1", + "__LACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-31LK", + "__INT_FAST16_TYPE__=int", + "__LDBL_HAS_DENORM__=1", + "__BUILTIN_AVR_BITSK=1", + "__BUILTIN_AVR_BITSR=1", + "__cplusplus=201402L", + "__cpp_ref_qualifiers=200710", + "__DEC128_MAX__=9.999999999999999999999999999999999E6144DL", + "__INT_LEAST32_MAX__=0x7fffffffL", + "__USING_SJLJ_EXCEPTIONS__=1", + "__DEC32_MIN__=1E-95DF", + "__ACCUM_MAX__=0X7FFFFFFFP-15K", + "__DEPRECATED=1", + "__cpp_rvalue_references=200610", + "__DBL_MAX_EXP__=128", + "__USACCUM_EPSILON__=0x1P-8UHK", + "__WCHAR_WIDTH__=16", + "__FLT32_MAX__=3.40282347e+38F32", + "__DEC128_EPSILON__=1E-33DL", + "__SFRACT_MAX__=0X7FP-7HR", + "__FRACT_IBIT__=0", + "__PTRDIFF_MAX__=0x7fff", + "__UACCUM_MIN__=0.0UK", + "__UACCUM_IBIT__=16", + "__BUILTIN_AVR_NOPS=1", + "__BUILTIN_AVR_WDR=1", + "__FLT32_HAS_QUIET_NAN__=1", + "__GNUG__=7", + "__LONG_LONG_MAX__=0x7fffffffffffffffLL", + "__SIZEOF_SIZE_T__=2", + "__ULACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-32ULK", + "__cpp_rvalue_reference=200610", + "__cpp_nsdmi=200809", + "__SIZEOF_WINT_T__=2", + "__LONG_LONG_WIDTH__=64", + "__cpp_initializer_lists=200806", + "__FLT32_MAX_EXP__=128", + "__SA_IBIT__=16", + "__ULLACCUM_MIN__=0.0ULLK", + "__BUILTIN_AVR_ROUNDUHK=1", + "__BUILTIN_AVR_ROUNDUHR=1", + "__cpp_hex_float=201603", + "__GXX_ABI_VERSION=1011", + "__INT24_MAX__=8388607L", + "__UTA_FBIT__=48", + "__FLT_MIN_EXP__=(-125)", + "__USFRACT_MAX__=0XFFP-8UHR", + "__UFRACT_IBIT__=0", + "__BUILTIN_AVR_ROUNDFX=1", + "__BUILTIN_AVR_ROUNDULK=1", + "__BUILTIN_AVR_ROUNDULR=1", + "__cpp_lambdas=200907", + "__BUILTIN_AVR_COUNTLSLLK=1", + "__BUILTIN_AVR_COUNTLSLLR=1", + "__BUILTIN_AVR_ROUNDHK=1", + "__INT_FAST64_TYPE__=long long int", + "__BUILTIN_AVR_ROUNDHR=1", + "__DBL_MIN__=double(1.17549435e-38L)", + "__BUILTIN_AVR_COUNTLSK=1", + "__BUILTIN_AVR_ROUNDLK=1", + "__BUILTIN_AVR_COUNTLSR=1", + "__BUILTIN_AVR_ROUNDLR=1", + "__LACCUM_MIN__=(-0X1P31LK-0X1P31LK)", + "__ULLACCUM_FBIT__=48", + "__BUILTIN_AVR_LKBITS=1", + "__ULLFRACT_EPSILON__=0x1P-64ULLR", + "__DEC128_MIN__=1E-6143DL", + "__REGISTER_PREFIX__", + "__UINT16_MAX__=0xffffU", + "__DBL_HAS_DENORM__=1", + "__BUILTIN_AVR_ULKBITS=1", + "__ACCUM_MIN__=(-0X1P15K-0X1P15K)", + "__AVR_ARCH__=2", + "__SQ_IBIT__=0", + "__FLT32_MIN__=1.17549435e-38F32", + "__UINT8_TYPE__=unsigned char", + "__BUILTIN_AVR_ROUNDUK=1", + "__BUILTIN_AVR_ROUNDUR=1", + "__UHA_FBIT__=8", + "__NO_INLINE__=1", + "__SFRACT_MIN__=(-0.5HR-0.5HR)", + "__UTQ_FBIT__=128", + "__FLT_MANT_DIG__=24", + "__LDBL_DECIMAL_DIG__=9", + "__VERSION__=\"7.3.0\"", + "__UINT64_C(c)=c ## ULL", + "__ULLFRACT_FBIT__=64", + "__cpp_unicode_characters=200704", + "__FRACT_EPSILON__=0x1P-15R", + "__ULACCUM_MIN__=0.0ULK", + "__UDA_FBIT__=32", + "__cpp_decltype_auto=201304", + "__LLACCUM_EPSILON__=0x1P-47LLK", + "__GCC_ATOMIC_INT_LOCK_FREE=1", + "__FLT32_MANT_DIG__=24", + "__BUILTIN_AVR_BITSUHK=1", + "__BUILTIN_AVR_BITSUHR=1", + "__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__", + "__USFRACT_MIN__=0.0UHR", + "__BUILTIN_AVR_BITSULK=1", + "__ULLACCUM_IBIT__=16", + "__BUILTIN_AVR_BITSULR=1", + "__UQQ_IBIT__=0", + "__BUILTIN_AVR_LLRBITS=1", + "__SCHAR_WIDTH__=8", + "__BUILTIN_AVR_BITSULLK=1", + "__BUILTIN_AVR_BITSULLR=1", + "__INT32_C(c)=c ## L", + "__DEC64_EPSILON__=1E-15DD", + "__ORDER_PDP_ENDIAN__=3412", + "__DEC128_MIN_EXP__=(-6142)", + "__UHQ_FBIT__=16", + "__LLACCUM_FBIT__=47", + "__FLT32_MAX_10_EXP__=38", + "__BUILTIN_AVR_ROUNDULLK=1", + "__BUILTIN_AVR_ROUNDULLR=1", + "__INT_FAST32_TYPE__=long int", + "__BUILTIN_AVR_HRBITS=1", + "__UINT_LEAST16_TYPE__=unsigned int", + "__BUILTIN_AVR_UHRBITS=1", + "__INT16_MAX__=0x7fff", + "__SIZE_TYPE__=unsigned int", + "__UINT64_MAX__=0xffffffffffffffffULL", + "__UDQ_FBIT__=64", + "__INT8_TYPE__=signed char", + "__cpp_digit_separators=201309", + "__ELF__=1", + "__ULFRACT_EPSILON__=0x1P-32ULR", + "__LLFRACT_FBIT__=63", + "__FLT_RADIX__=2", + "__INT_LEAST16_TYPE__=int", + "__BUILTIN_AVR_ABSFX=1", + "__LDBL_EPSILON__=1.19209290e-7L", + "__UINTMAX_C(c)=c ## ULL", + "__INT24_MIN__=(-__INT24_MAX__-1)", + "__SACCUM_MAX__=0X7FFFP-7HK", + "__BUILTIN_AVR_ABSHR=1", + "__SIG_ATOMIC_MAX__=0x7f", + "__GCC_ATOMIC_WCHAR_T_LOCK_FREE=1", + "__cpp_sized_deallocation=201309", + "__SIZEOF_PTRDIFF_T__=2", + "__AVR=1", + "__BUILTIN_AVR_ABSLK=1", + "__BUILTIN_AVR_ABSLR=1", + "__LACCUM_EPSILON__=0x1P-31LK", + "__DEC32_SUBNORMAL_MIN__=0.000001E-95DF", + "__INT_FAST16_MAX__=0x7fff", + "__UINT_FAST32_MAX__=0xffffffffUL", + "__UINT_LEAST64_TYPE__=long long unsigned int", + "__USACCUM_MAX__=0XFFFFP-8UHK", + "__SFRACT_EPSILON__=0x1P-7HR", + "__FLT_HAS_QUIET_NAN__=1", + "__FLT_MAX_10_EXP__=38", + "__LONG_MAX__=0x7fffffffL", + "__DEC128_SUBNORMAL_MIN__=0.000000000000000000000000000000001E-6143DL", + "__FLT_HAS_INFINITY__=1", + "__cpp_unicode_literals=200710", + "__USA_FBIT__=16", + "__UINT_FAST16_TYPE__=unsigned int", + "__DEC64_MAX__=9.999999999999999E384DD", + "__INT_FAST32_WIDTH__=32", + "__BUILTIN_AVR_RBITS=1", + "__CHAR16_TYPE__=unsigned int", + "__PRAGMA_REDEFINE_EXTNAME=1", + "__SIZE_WIDTH__=16", + "__INT_LEAST16_MAX__=0x7fff", + "__DEC64_MANT_DIG__=16", + "__UINT_LEAST32_MAX__=0xffffffffUL", + "__SACCUM_FBIT__=7", + "__FLT32_DENORM_MIN__=1.40129846e-45F32", + "__GCC_ATOMIC_LONG_LOCK_FREE=1", + "__SIG_ATOMIC_WIDTH__=8", + "__INT_LEAST64_TYPE__=long long int", + "__INT16_TYPE__=int", + "__INT_LEAST8_TYPE__=signed char", + "__SQ_FBIT__=31", + "__DEC32_MAX_EXP__=97", + "__INT_FAST8_MAX__=0x7f", + "__INTPTR_MAX__=0x7fff", + "__QQ_FBIT__=7", + "__cpp_range_based_for=200907", + "__UTA_IBIT__=16", + "__AVR_ERRATA_SKIP__=1", + "__FLT32_MIN_10_EXP__=(-37)", + "__LDBL_MANT_DIG__=24", + "__SFRACT_FBIT__=7", + "__SACCUM_MIN__=(-0X1P7HK-0X1P7HK)", + "__DBL_HAS_QUIET_NAN__=1", + "__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)", + "AVR=1", + "__BUILTIN_AVR_FMULS=1", + "__cpp_return_type_deduction=201304", + "__INTPTR_TYPE__=int", + "__UINT16_TYPE__=unsigned int", + "__WCHAR_TYPE__=int", + "__SIZEOF_FLOAT__=4", + "__AVR__=1", + "__BUILTIN_AVR_INSERT_BITS=1", + "__USQ_FBIT__=32", + "__UINTPTR_MAX__=0xffffU", + "__INT_FAST64_WIDTH__=64", + "__DEC64_MIN_EXP__=(-382)", + "__cpp_decltype=200707", + "__FLT32_DECIMAL_DIG__=9", + "__INT_FAST64_MAX__=0x7fffffffffffffffLL", + "__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1", + "__FLT_DIG__=6", + "__UINT_FAST64_TYPE__=long long unsigned int", + "__BUILTIN_AVR_BITSHK=1", + "__BUILTIN_AVR_BITSHR=1", + "__INT_MAX__=0x7fff", + "__LACCUM_FBIT__=31", + "__USACCUM_MIN__=0.0UHK", + "__UHA_IBIT__=8", + "__INT64_TYPE__=long long int", + "__BUILTIN_AVR_BITSLK=1", + "__BUILTIN_AVR_BITSLR=1", + "__FLT_MAX_EXP__=128", + "__UTQ_IBIT__=0", + "__DBL_MANT_DIG__=24", + "__cpp_inheriting_constructors=201511", + "__BUILTIN_AVR_ULLKBITS=1", + "__INT_LEAST64_MAX__=0x7fffffffffffffffLL", + "__DEC64_MIN__=1E-383DD", + "__WINT_TYPE__=int", + "__UINT_LEAST32_TYPE__=long unsigned int", + "__SIZEOF_SHORT__=2", + "__ULLFRACT_IBIT__=0", + "__LDBL_MIN_EXP__=(-125)", + "__UDA_IBIT__=32", + "__WINT_WIDTH__=16", + "__INT_LEAST8_MAX__=0x7f", + "__LFRACT_FBIT__=31", + "__LDBL_MAX_10_EXP__=38", + "__ATOMIC_RELAXED=0", + "__DBL_EPSILON__=double(1.19209290e-7L)", + "__BUILTIN_AVR_BITSUK=1", + "__BUILTIN_AVR_BITSUR=1", + "__UINT8_C(c)=c", + "__INT_LEAST32_TYPE__=long int", + "__BUILTIN_AVR_URBITS=1", + "__SIZEOF_WCHAR_T__=2", + "__LLFRACT_MAX__=0X7FFFFFFFFFFFFFFFP-63LLR", + "__TQ_FBIT__=127", + "__INT_FAST8_TYPE__=signed char", + "__ULLACCUM_EPSILON__=0x1P-48ULLK", + "__BUILTIN_AVR_ROUNDK=1", + "__BUILTIN_AVR_ROUNDR=1", + "__UHQ_IBIT__=0", + "__LLACCUM_IBIT__=16", + "__FLT32_EPSILON__=1.19209290e-7F32", + "__DBL_DECIMAL_DIG__=9", + "__STDC_UTF_32__=1", + "__INT_FAST8_WIDTH__=8", + "__DEC_EVAL_METHOD__=2", + "__TA_FBIT__=47", + "__UDQ_IBIT__=0", + "__ORDER_BIG_ENDIAN__=4321", + "__cpp_runtime_arrays=198712", + "__WITH_AVRLIBC__=1", + "__UINT64_TYPE__=long long unsigned int", + "__ACCUM_EPSILON__=0x1P-15K", + "__UINT32_C(c)=c ## UL", + "__BUILTIN_AVR_COUNTLSUHK=1", + "__INTMAX_MAX__=0x7fffffffffffffffLL", + "__cpp_alias_templates=200704", + "__BUILTIN_AVR_COUNTLSUHR=1", + "__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__", + "__FLT_DENORM_MIN__=1.40129846e-45F", + "__LLFRACT_IBIT__=0", + "__INT8_MAX__=0x7f", + "__LONG_WIDTH__=32", + "__UINT_FAST32_TYPE__=long unsigned int", + "__CHAR32_TYPE__=long unsigned int", + "__BUILTIN_AVR_COUNTLSULK=1", + "__BUILTIN_AVR_COUNTLSULR=1", + "__FLT_MAX__=3.40282347e+38F", + "__cpp_constexpr=201304", + "__USACCUM_FBIT__=8", + "__BUILTIN_AVR_COUNTLSFX=1", + "__INT32_TYPE__=long int", + "__SIZEOF_DOUBLE__=4", + "__FLT_MIN_10_EXP__=(-37)", + "__UFRACT_EPSILON__=0x1P-16UR", + "__INT_LEAST32_WIDTH__=32", + "__BUILTIN_AVR_COUNTLSHK=1", + "__BUILTIN_AVR_COUNTLSHR=1", + "__INTMAX_TYPE__=long long int", + "__BUILTIN_AVR_ABSLLK=1", + "__BUILTIN_AVR_ABSLLR=1", + "__DEC128_MAX_EXP__=6145", + "__AVR_HAVE_16BIT_SP__=1", + "__ATOMIC_CONSUME=1", + "__GNUC_MINOR__=3", + "__INT_FAST16_WIDTH__=16", + "__UINTMAX_MAX__=0xffffffffffffffffULL", + "__DEC32_MANT_DIG__=7", + "__HA_FBIT__=7", + "__BUILTIN_AVR_COUNTLSLK=1", + "__BUILTIN_AVR_COUNTLSLR=1", + "__BUILTIN_AVR_CLI=1", + "__DBL_MAX_10_EXP__=38", + "__LDBL_DENORM_MIN__=1.40129846e-45L", + "__INT16_C(c)=c", + "__cpp_generic_lambdas=201304", + "__STDC__=1", + "__PTRDIFF_TYPE__=int", + "__LLFRACT_MIN__=(-0.5LLR-0.5LLR)", + "__BUILTIN_AVR_LRBITS=1", + "__ATOMIC_SEQ_CST=5", + "__DA_FBIT__=31", + "__UINT32_TYPE__=long unsigned int", + "__BUILTIN_AVR_ROUNDLLK=1", + "__UINTPTR_TYPE__=unsigned int", + "__BUILTIN_AVR_ROUNDLLR=1", + "__USA_IBIT__=16", + "__BUILTIN_AVR_ULRBITS=1", + "__DEC64_SUBNORMAL_MIN__=0.000000000000001E-383DD", + "__DEC128_MANT_DIG__=34", + "__LDBL_MIN_10_EXP__=(-37)", + "__BUILTIN_AVR_COUNTLSUK=1", + "__BUILTIN_AVR_COUNTLSUR=1", + "__SIZEOF_LONG_LONG__=8", + "__ULACCUM_EPSILON__=0x1P-32ULK", + "__cpp_user_defined_literals=200809", + "__SACCUM_IBIT__=8", + "__GCC_ATOMIC_LLONG_LOCK_FREE=1", + "__LDBL_DIG__=6", + "__FLT_DECIMAL_DIG__=9", + "__UINT_FAST16_MAX__=0xffffU", + "__GCC_ATOMIC_SHORT_LOCK_FREE=1", + "__BUILTIN_AVR_ABSHK=1", + "__BUILTIN_AVR_FLASH_SEGMENT=1", + "__INT_LEAST64_WIDTH__=64", + "__ULLFRACT_MAX__=0XFFFFFFFFFFFFFFFFP-64ULLR", + "__UINT_FAST8_TYPE__=unsigned char", + "__USFRACT_EPSILON__=0x1P-8UHR", + "__ULACCUM_FBIT__=32", + "__QQ_IBIT__=0", + "__cpp_init_captures=201304", + "__ATOMIC_ACQ_REL=4", + "__ATOMIC_RELEASE=3", + "__BUILTIN_AVR_FMUL=1", + "USBCON" + ] + } + ] +} \ No newline at end of file diff --git a/examples/.DS_Store b/examples/.DS_Store index d10bd55..8742020 100644 Binary files a/examples/.DS_Store and b/examples/.DS_Store differ diff --git a/examples/Example1-ECG-BioZ-stream-Openview/Example1-ECG-BioZ-stream-Openview.ino b/examples/Example1-ECG-BioZ-stream-Openview/Example1-ECG-BioZ-stream-Openview.ino index 07bca90..2c13c97 100644 --- a/examples/Example1-ECG-BioZ-stream-Openview/Example1-ECG-BioZ-stream-Openview.ino +++ b/examples/Example1-ECG-BioZ-stream-Openview/Example1-ECG-BioZ-stream-Openview.ino @@ -35,7 +35,7 @@ #include "protocentral_max30001.h" #define MAX30001_CS_PIN 7 -#define MAX30001_DELAY_SAMPLES 8 // Time between consecutive samples +#define MAX30001_DELAY_SAMPLES 8 // Time between consecutive samples #define CES_CMDIF_PKT_START_1 0x0A #define CES_CMDIF_PKT_START_2 0xFA @@ -45,8 +45,8 @@ #define ZERO 0 volatile char DataPacket[DATA_LEN]; -const char DataPacketFooter[2] = { ZERO, CES_CMDIF_PKT_STOP }; -const char DataPacketHeader[5] = { CES_CMDIF_PKT_START_1, CES_CMDIF_PKT_START_2, DATA_LEN, ZERO, CES_CMDIF_TYPE_DATA }; +const char DataPacketFooter[2] = {ZERO, CES_CMDIF_PKT_STOP}; +const char DataPacketHeader[5] = {CES_CMDIF_PKT_START_1, CES_CMDIF_PKT_START_2, DATA_LEN, ZERO, CES_CMDIF_TYPE_DATA}; uint8_t data_len = 0x0C; @@ -55,7 +55,8 @@ MAX30001 max30001(MAX30001_CS_PIN); signed long ecg_data; signed long bioz_data; -void sendData(signed long ecg_sample, signed long bioz_sample, bool _bioZSkipSample) { +void sendData(signed long ecg_sample, signed long bioz_sample, bool _bioZSkipSample) +{ DataPacket[0] = ecg_sample; DataPacket[1] = ecg_sample >> 8; @@ -67,46 +68,55 @@ void sendData(signed long ecg_sample, signed long bioz_sample, bool _bioZSkipSam DataPacket[6] = bioz_sample >> 16; DataPacket[7] = bioz_sample >> 24; - if (_bioZSkipSample == false) { + if (_bioZSkipSample == false) + { DataPacket[8] = 0x00; - } else { + } + else + { DataPacket[8] = 0xFF; } - DataPacket[9] = 0x00; // max30001.heartRate >> 8; + DataPacket[9] = 0x00; // max30001.heartRate >> 8; DataPacket[10] = 0x00; DataPacket[11] = 0x00; // Send packet header (in ProtoCentral OpenView format) - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) + { Serial.write(DataPacketHeader[i]); } // Send the data payload - for (int i = 0; i < DATA_LEN; i++) // transmit the data + for (int i = 0; i < DATA_LEN; i++) // transmit the data { Serial.write(DataPacket[i]); } // Send packet footer (in ProtoCentral OpenView format) - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) + { Serial.write(DataPacketFooter[i]); } } bool BioZSkipSample = false; -void setup() +void setup() { - Serial.begin(57600); // Serial begin + Serial.begin(57600); // Serial begin SPI.begin(); bool ret = max30001.max30001ReadInfo(); - if (ret) { + if (ret) + { Serial.println("MAX 30001 read ID Success"); - } else { - while (!ret) { + } + else + { + while (!ret) + { // stay here untill the issue is fixed. ret = max30001.max30001ReadInfo(); Serial.println("Failed to read ID, please make sure all the pins are connected"); @@ -115,22 +125,25 @@ void setup() } Serial.println("Initialising the chip ..."); - max30001.BeginECGBioZ(); // initialize MAX30001 - // max30001.Begin(); + max30001.BeginECGBioZ(); // initialize MAX30001 + // max30001.Begin(); } -void loop() { +void loop() +{ ecg_data = max30001.getECGSamples(); // max30001.getHRandRR(); - if (BioZSkipSample == false) { + if (BioZSkipSample == false) + { bioz_data = max30001.getBioZSamples(); sendData(ecg_data, bioz_data, BioZSkipSample); BioZSkipSample = true; - } else + } + else { bioz_data = 0x00; sendData(ecg_data, bioz_data, BioZSkipSample); - BioZSkipSample=false; + BioZSkipSample = false; } delay(8); } \ No newline at end of file diff --git a/src/protocentral_max30001.cpp b/src/protocentral_max30001.cpp index b21f33c..59b32ae 100644 --- a/src/protocentral_max30001.cpp +++ b/src/protocentral_max30001.cpp @@ -1,10 +1,10 @@ -// ______ _ _____ _ _ +// ______ _ _____ _ _ // | ___ \ | | / __ \ | | | | // | |_/ / __ ___ | |_ ___ | / \/ ___ _ __ | |_ _ __ __ _| | // | __/ '__/ _ \| __/ _ \| | / _ \ '_ \| __| '__/ _` | | // | | | | | (_) | || (_) | \__/\ __/ | | | |_| | | (_| | | -// \_| |_| \___/ \__\___/ \____/\___|_| |_|\__|_| \__,_|_| - +// \_| |_| \___/ \__\___/ \____/\___|_| |_|\__|_| \__,_|_| + ////////////////////////////////////////////////////////////////////////////////////////// // // Demo code for the MAX30001 breakout board @@ -35,23 +35,24 @@ // ///////////////////////////////////////////////////////////////////////////////////////// -#include +#include #include "protocentral_max30001.h" #define MAX30001_SPI_SPEED 1000000 MAX30001::MAX30001(int cs_pin) { - _cs_pin=cs_pin; + _cs_pin = cs_pin; pinMode(_cs_pin, OUTPUT); - digitalWrite(_cs_pin,HIGH); - + digitalWrite(_cs_pin, HIGH); + ecgSamplesAvailable = 0; } -void MAX30001::_max30001RegWrite (unsigned char WRITE_ADDRESS, unsigned long data) + +void MAX30001::_max30001RegWrite(unsigned char WRITE_ADDRESS, unsigned long data) { - //Combine the register address and the command into one byte: - byte dataToSend = (WRITE_ADDRESS<<1) | WREG; + // Combine the register address and the command into one byte: + byte dataToSend = (WRITE_ADDRESS << 1) | WREG; SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); @@ -59,8 +60,8 @@ void MAX30001::_max30001RegWrite (unsigned char WRITE_ADDRESS, unsigned long dat delay(2); SPI.transfer(dataToSend); - SPI.transfer(data>>16); - SPI.transfer(data>>8); + SPI.transfer(data >> 16); + SPI.transfer(data >> 8); SPI.transfer(data); delay(2); @@ -69,77 +70,89 @@ void MAX30001::_max30001RegWrite (unsigned char WRITE_ADDRESS, unsigned long dat SPI.endTransaction(); } -void MAX30001::_max30001RegRead(uint8_t Reg_address, uint8_t * buff) +void MAX30001::_max30001RegRead24(uint8_t Reg_address, uint32_t *read_data) { uint8_t spiTxBuff; + uint8_t buff[4]; + SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); digitalWrite(_cs_pin, LOW); - spiTxBuff = (Reg_address<<1 ) | RREG; - SPI.transfer(spiTxBuff); //Send register location + spiTxBuff = (Reg_address << 1) | RREG; + SPI.transfer(spiTxBuff); // Send register location - for ( int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { - buff[i] = SPI.transfer(0xff); + buff[i] = SPI.transfer(0xff); } digitalWrite(_cs_pin, HIGH); - - SPI.endTransaction(); -} -void MAX30001::_max30001SwReset(void) -{ - _max30001RegWrite(SW_RST,0x000000); - delay(100); -} + *read_data = (buff[0] << 16) | (buff[1] << 8) | buff[2]; -void MAX30001::_max30001Synch(void) -{ - _max30001RegWrite(SYNCH,0x000000); + SPI.endTransaction(); } -bool MAX30001::max30001ReadInfo(void) +void MAX30001::_max30001RegRead(uint8_t Reg_address, uint8_t *buff) { - uint8_t readBuff[4] ; + uint8_t spiTxBuff; - _max30001RegRead(INFO, readBuff); + SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); - if((readBuff[0]&0xf0) == 0x50 ){ - Serial.print("MAX30001 Detected. Rev ID: "); - Serial.println((readBuff[0]&0xf0)); + digitalWrite(_cs_pin, LOW); - return true; - }else{ + spiTxBuff = (Reg_address << 1) | RREG; + SPI.transfer(spiTxBuff); // Send register location - Serial.println("MAX30001 read info error\n"); - return false; + for (int i = 0; i < 3; i++) + { + buff[i] = SPI.transfer(0xff); } - return false; + digitalWrite(_cs_pin, HIGH); + + SPI.endTransaction(); } -void MAX30001::_max30001ReadData(int num_samples, uint8_t * readBuffer) +void MAX30001::_max30001SwReset(void) { - uint8_t spiTxBuff; + _max30001RegWrite(SW_RST, 0x000000); + delay(100); +} - SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); +void MAX30001::_max30001Synch(void) +{ + _max30001RegWrite(SYNCH, 0x000000); +} - digitalWrite(_cs_pin, LOW); +void MAX30001::_max30001FIFOReset(void) +{ + _max30001RegWrite(FIFO_RST, 0x000000); +} - spiTxBuff = (ECG_FIFO_BURST<<1 ) | RREG; - SPI.transfer(spiTxBuff); //Send register location +bool MAX30001::max30001ReadInfo(void) +{ + uint8_t readBuff[4]; - for ( int i = 0; i < num_samples*3; ++i) + _max30001RegRead(INFO, readBuff); + + if ((readBuff[0] & 0xf0) == 0x50) { - readBuffer[i] = SPI.transfer(0x00); + Serial.print("MAX30001 Detected. Rev ID: "); + Serial.println((readBuff[0] & 0xf0)); + + return true; } + else + { - digitalWrite(_cs_pin, HIGH); + Serial.println("MAX30001 read info error\n"); + return false; + } - SPI.endTransaction(); + return false; } void MAX30001::BeginECGOnly() @@ -148,41 +161,82 @@ void MAX30001::BeginECGOnly() delay(100); _max30001RegWrite(CNFG_GEN, 0x081007); delay(100); - _max30001RegWrite(CNFG_CAL, 0x720000); // 0x700000 + _max30001RegWrite(CNFG_CAL, 0x720000); // 0x700000 delay(100); - _max30001RegWrite(CNFG_EMUX,0x0B0000); + _max30001RegWrite(CNFG_EMUX, 0x0B0000); delay(100); - _max30001RegWrite(CNFG_ECG, 0x825000); // d23 - d22 : 10 for 250sps , 00:500 sps + _max30001RegWrite(CNFG_ECG, 0x825000); // d23 - d22 : 10 for 250sps , 00:500 sps delay(100); - _max30001RegWrite(CNFG_RTOR1,0x3fc600); + _max30001RegWrite(CNFG_RTOR1, 0x3fc600); _max30001Synch(); delay(100); } void MAX30001::BeginECGBioZ() { + max30001_cnfg_bmux_t cnfg_bmux; + max30001_cnfg_bioz_t cnfg_bioz; + _max30001SwReset(); delay(100); - _max30001RegWrite(CNFG_GEN, 0x0C0004); // ECG & BioZ Enabled , FMSTR = 32768 + + _max30001RegWrite(CNFG_GEN, 0xC0004); // ECG & BioZ Enabled , FMSTR = 32768 delay(100); - _max30001RegWrite(CNFG_CAL, 0x720000); // Calibration sources disabled + //_max30001RegWrite(CNFG_CAL, 0x720000); // Calibration sources disabled + + _max30001RegWrite(CNFG_CAL, 0x702000); // Calibration sources disabled delay(100); - _max30001RegWrite(CNFG_ECG, 0x825000); // ECG_RATE: 125 SPS, + //_max30001RegWrite(CNFG_EMUX, 0x0B0000); // Pins internally connection to ECG Channels + _max30001RegWrite(CNFG_EMUX, 0x00); // Pins internally connection to ECG Channels delay(100); - _max30001RegWrite(CNFG_EMUX,0x0B0000); // Pins internally connection to ECG Channels + + //_max30001RegWrite(CNFG_ECG, 0x825000); // ECG_RATE: 125 SPS, + _max30001RegWrite(CNFG_ECG, 0x835000); delay(100); - _max30001RegWrite(CNFG_BIOZ, 0x201433); // BioZ Rate: 64 SPS | Current generator: 32 uA + cnfg_bmux.bit.openp = 0; + cnfg_bmux.bit.openn = 0; + cnfg_bmux.bit.calp_sel = 0x00; // No cal signal on BioZ + cnfg_bmux.bit.caln_sel = 0x00; // No cal signal on BioZ + cnfg_bmux.bit.cg_mode = 0x00; // Unchopped + cnfg_bmux.bit.en_bist=0; + cnfg_bmux.bit.rnom=0x00; + cnfg_bmux.bit.rmod=0x04; + cnfg_bmux.bit.fbist=0; + + _max30001RegWrite(CNFG_BMUX, cnfg_bmux.all); delay(100); - //Set MAX30001G specific BioZ LC + //_max30001RegWrite(CNFG_BMUX, 0x000040); // Pins connected internally to BioZ channels + //delay(100); + + // Set MAX30001G specific BioZ LC _max30001RegWrite(CNFG_BIOZ_LC, 0x800000); // Turn OFF low current mode + delay(100); + + cnfg_bioz.bit.rate = 0; + cnfg_bioz.bit.ahpf = 0b010; + cnfg_bioz.bit.ext_rbias = 0x00; + cnfg_bioz.bit.ln_bioz=1; + cnfg_bioz.bit.gain = 0b10; + cnfg_bioz.bit.dhpf = 0b01; + cnfg_bioz.bit.dlpf = 0x01; + cnfg_bioz.bit.fcgen = 0b100; + cnfg_bioz.bit.cgmon = 0x00; + cnfg_bioz.bit.cgmag = 0b011; + cnfg_bioz.bit.phoff = 0x0000; + + //_max30001RegWrite(CNFG_BIOZ, 0x201433); // BioZ Rate: 64 SPS | Current generator: 32 uA + _max30001RegWrite(CNFG_BIOZ, cnfg_bioz.all); + delay(100); - _max30001RegWrite(CNFG_BMUX,0x000040); // Pins connected internally to BioZ channels + _max30001RegWrite(MNGR_INT, 0x7B0000); // EFIT=16, BFIT=8 delay(100); + //max30001SetInterrupts(EN_EINT | 0x01); // Enable ECG Interrupts + //_max30001RegWrite(CNFG_RTOR1,0x3fc600); _max30001Synch(); delay(100); @@ -194,13 +248,13 @@ void MAX30001::BeginRtoRMode() delay(100); _max30001RegWrite(CNFG_GEN, 0x080004); delay(100); - _max30001RegWrite(CNFG_CAL, 0x720000); // 0x700000 + _max30001RegWrite(CNFG_CAL, 0x720000); // 0x700000 delay(100); - _max30001RegWrite(CNFG_EMUX,0x0B0000); + _max30001RegWrite(CNFG_EMUX, 0x0B0000); delay(100); - _max30001RegWrite(CNFG_ECG, 0x805000); // d23 - d22 : 10 for 250sps , 00:500 sps + _max30001RegWrite(CNFG_ECG, 0x805000); // d23 - d22 : 10 for 250sps , 00:500 sps delay(100); - _max30001RegWrite(CNFG_RTOR1,0x3fc600); + _max30001RegWrite(CNFG_RTOR1, 0x3fc600); delay(100); _max30001RegWrite(EN_INT, 0x000401); delay(100); @@ -208,28 +262,29 @@ void MAX30001::BeginRtoRMode() delay(100); } -//not tested +// not tested void MAX30001::max30001SetsamplingRate(uint16_t samplingRate) { uint8_t regBuff[4] = {0}; _max30001RegRead(CNFG_ECG, regBuff); - switch(samplingRate){ - case SAMPLINGRATE_128: - regBuff[0] = (regBuff[0] | 0x80 ); - break; + switch (samplingRate) + { + case SAMPLINGRATE_128: + regBuff[0] = (regBuff[0] | 0x80); + break; - case SAMPLINGRATE_256: - regBuff[0] = (regBuff[0] | 0x40 ); - break; + case SAMPLINGRATE_256: + regBuff[0] = (regBuff[0] | 0x40); + break; - case SAMPLINGRATE_512: - regBuff[0] = (regBuff[0] | 0x00 ); - break; + case SAMPLINGRATE_512: + regBuff[0] = (regBuff[0] | 0x00); + break; - default : - Serial.println("Invalid sample rate. Please choose between 128, 256 or 512"); - break; + default: + Serial.println("Invalid sample rate. Please choose between 128, 256 or 512"); + break; } unsigned long cnfgEcg; @@ -245,16 +300,16 @@ signed long MAX30001::getECGSamples(void) uint8_t regReadBuff[4]; _max30001RegRead(ECG_FIFO, regReadBuff); - unsigned long data0 = (unsigned long) (regReadBuff[0]); - data0 = data0 <<24; - unsigned long data1 = (unsigned long) (regReadBuff[1]); - data1 = data1 <<16; - unsigned long data2 = (unsigned long) (regReadBuff[2]); - data2 = data2 >>6; + unsigned long data0 = (unsigned long)(regReadBuff[0]); + data0 = data0 << 24; + unsigned long data1 = (unsigned long)(regReadBuff[1]); + data1 = data1 << 16; + unsigned long data2 = (unsigned long)(regReadBuff[2]); + data2 = data2 >> 6; data2 = data2 & 0x03; - unsigned long data = (unsigned long) (data0 | data1 | data2); - ecg_data = (signed long) data; + unsigned long data = (unsigned long)(data0 | data1 | data2); + ecg_data = (signed long)data; return ecg_data; } @@ -262,34 +317,183 @@ signed long MAX30001::getBioZSamples(void) { uint8_t regReadBuff[4]; _max30001RegRead(BIOZ_FIFO, regReadBuff); - - unsigned long data0 = (unsigned long) (regReadBuff[0]); - data0 = data0 <<24; - unsigned long data1 = (unsigned long) (regReadBuff[1]); - data1 = data1 <<16; - unsigned long data2 = (unsigned long) (regReadBuff[2]); - data2 = data2 >>6; + + unsigned long data0 = (unsigned long)(regReadBuff[0]); + data0 = data0 << 24; + unsigned long data1 = (unsigned long)(regReadBuff[1]); + data1 = data1 << 16; + unsigned long data2 = (unsigned long)(regReadBuff[2]); + data2 = data2 >> 6; data2 = data2 & 0x03; - unsigned long data = (unsigned long) (data0 | data1 | data2); - bioz_data = (signed long) (data); + unsigned long data = (unsigned long)(data0 | data1 | data2); + bioz_data = (signed long)(data); return bioz_data; } - void MAX30001::getHRandRR(void) { uint8_t regReadBuff[4]; _max30001RegRead(RTOR, regReadBuff); - unsigned long RTOR_msb = (unsigned long) (regReadBuff[0]); - unsigned char RTOR_lsb = (unsigned char) (regReadBuff[1]); - unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb); - rtor = ((rtor >>2) & 0x3fff) ; + unsigned long RTOR_msb = (unsigned long)(regReadBuff[0]); + unsigned char RTOR_lsb = (unsigned char)(regReadBuff[1]); + unsigned long rtor = (RTOR_msb << 8 | RTOR_lsb); + rtor = ((rtor >> 2) & 0x3fff); - float hr = 60 /((float)rtor*0.0078125); + float hr = 60 / ((float)rtor * 0.0078125); heartRate = (unsigned int)hr; - unsigned int RR = (unsigned int)rtor* (7.8125) ; //8ms + unsigned int RR = (unsigned int)rtor * (7.8125); // 8ms RRinterval = RR; } + +void MAX30001::max30001SetInterrupts(uint32_t interrupts_to_set) +{ + _max30001RegWrite(EN_INT, interrupts_to_set); + delay(100); + //_max30001Synch(); + // delay(100); +} + +int secg_counter = 0; +int sbioz_counter = 0; + +void MAX30001::_max30001ReadECGFIFO(int num_bytes) +{ + uint8_t spiTxBuff; + unsigned long uecgtemp; + signed long secgtemp; + + SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); + + digitalWrite(_cs_pin, LOW); + + spiTxBuff = (ECG_FIFO_BURST << 1) | RREG; + SPI.transfer(spiTxBuff); // Send register location + + for (int i = 0; i < num_bytes; i++) + { + _readBufferECG[i] = SPI.transfer(0x00); + } + + digitalWrite(_cs_pin, HIGH); + + SPI.endTransaction(); + + secg_counter = 0; + unsigned char ecg_etag; + + for (int i = 0; i < num_bytes; i += 3) + { + // Get etag + ecg_etag = ((((unsigned char)_readBufferECG[i + 2]) & 0x38) >> 3); + //Serial.println(ecg_etag, HEX); + + if (ecg_etag == 0x00) //Valid sample + { + // uecgtemp=(unsigned long)((unsigned long)readBuffer[i]<<16 |(unsigned long)readBuffer[i+1]<<8| (unsigned long)(readBuffer[i+2]&0xC0)); + uecgtemp = (unsigned long)(((unsigned long)_readBufferECG[i] << 16 | (unsigned long)_readBufferECG[i + 1] << 8) | (unsigned long)(_readBufferECG[i+2]&0xC0)); + uecgtemp = (unsigned long)(uecgtemp << 8); + + secgtemp = (signed long)uecgtemp; + secgtemp = (signed long)secgtemp >> 8; + + s32ECGData[secg_counter++] = secgtemp; + } + else if (ecg_etag == 0x07) //FIFO Overflow + { + //Serial.println("OVF"); + _max30001FIFOReset(); + } + } + + //Serial.print("F"); + //Serial.println(secg_counter); + + ecgSamplesAvailable = secg_counter ; + secg_counter = 0; + +} + +void MAX30001::_max30001ReadBIOZFIFO(int num_bytes) +{ + uint8_t spiTxBuff; + unsigned long ubioztemp; + signed long sbioztemp; + + SPI.beginTransaction(SPISettings(MAX30001_SPI_SPEED, MSBFIRST, SPI_MODE0)); + + digitalWrite(_cs_pin, LOW); + + spiTxBuff = (BIOZ_FIFO_BURST << 1) | RREG; + SPI.transfer(spiTxBuff); // Send register location + + for (int i = 0; i < num_bytes; i++) + { + _readBufferBIOZ[i] = SPI.transfer(0x00); + } + + digitalWrite(_cs_pin, HIGH); + + SPI.endTransaction(); + + sbioz_counter = 0; + unsigned char bioz_etag; + + for (int i = 0; i < num_bytes; i += 3) + { + // Get etag + bioz_etag = ((((unsigned char)_readBufferBIOZ[i + 2]) & 0x38) >> 3); + //Serial.println(ecg_etag, HEX); + + if (bioz_etag == 0x00) //Valid sample + { + // uecgtemp=(unsigned long)((unsigned long)readBuffer[i]<<16 |(unsigned long)readBuffer[i+1]<<8| (unsigned long)(readBuffer[i+2]&0xC0)); + ubioztemp = (unsigned long)(((unsigned long)_readBufferBIOZ[i] << 16 | (unsigned long)_readBufferBIOZ[i + 1] << 8) | (unsigned long)(_readBufferBIOZ[i+2]&0xC0)); + ubioztemp = (unsigned long)(ubioztemp << 8); + + sbioztemp = (signed long)ubioztemp; + sbioztemp = (signed long)sbioztemp >> 8; + + s32BIOZData[sbioz_counter++] = sbioztemp; + } + else if (bioz_etag == 0x07) //FIFO Overflow + { + //Serial.println("OVF"); + _max30001FIFOReset(); + } + } + + biozSamplesAvailable = sbioz_counter ; + sbioz_counter = 0; +} + +void MAX30001::max30001ServiceAllInterrupts(void) +{ + static uint32_t InitReset = 0; + int fifo_num_bytes = 0; + + max30001_mngr_int_t mngr_int; + + _max30001RegRead24(STATUS, &global_status.all); + + if (global_status.bit.eint == 1) // EINT bit is set. FIFO is full + { + // Read the number of bytes in FIFO (from MNGR_INT register) + _max30001RegRead24(MNGR_INT, &mngr_int.all); + fifo_num_bytes = (mngr_int.bit.e_fit + 1) * 3; + + _max30001ReadECGFIFO(fifo_num_bytes); + } + + if(global_status.bit.bint==1) //BIOZ FIFO is full + { + _max30001RegRead24(MNGR_INT, &mngr_int.all); + fifo_num_bytes = (mngr_int.bit.b_fit + 1) * 3; + + // Read BIOZ FIFO in Burst mode + _max30001ReadBIOZFIFO(fifo_num_bytes); + + } +} diff --git a/src/protocentral_max30001.h b/src/protocentral_max30001.h index 9998db5..31d218d 100644 --- a/src/protocentral_max30001.h +++ b/src/protocentral_max30001.h @@ -1,4 +1,4 @@ -// ______ _ _____ _ _ +// ______ _ _____ _ _ // | ___ \ | | / __ \ | | | | // | |_/ / __ ___ | |_ ___ | / \/ ___ _ __ | |_ _ __ __ _| | // | __/ '__/ _ \| __/ _ \| | / _ \ '_ \| __| '__/ _` | | @@ -21,50 +21,47 @@ // // For information on how to use, visit https://github.com/Protocentral/protocentral-max30001-arduino // +// SOME PARTS OF THIS CODE ARE COPYRIGHT MAXIM INTEFGRATED PRODUCTS, INC. and are used with permission according to the following license: +// ///////////////////////////////////////////////////////////////////////////////////////// +/******************************************************************************* + * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Maxim Integrated + * Products, Inc. shall not be used except as stated in the Maxim Integrated + * Products, Inc. Branding Policy. + * + * The mere transfer of this software does not imply any licenses + * of trade secrets, proprietary technology, copyrights, patents, + * trademarks, maskwork rights, or any other form of intellectual + * property whatsoever. Maxim Integrated Products, Inc. retains all + * ownership rights. + *******************************************************************************/ + #ifndef protocentral_max30001_h #define protocentral_max30001_h #include -typedef enum -{ - SAMPLINGRATE_128 = 128, - SAMPLINGRATE_256 = 256, - SAMPLINGRATE_512 = 512 -} sampRate; - -class MAX30001 -{ -public: - MAX30001(int cs_pin); - unsigned int heartRate; - unsigned int RRinterval; - signed long ecg_data; - signed long bioz_data; - - void BeginECGOnly(); - void BeginECGBioZ(); - void BeginRtoRMode(); - - signed long getECGSamples(void); - signed long getBioZSamples(void); - void getHRandRR(void); - - bool max30001ReadInfo(void); - void max30001SetsamplingRate(uint16_t samplingRate); - -private: - void _max30001ReadData(int num_samples, uint8_t *readBuffer); - void _max30001Synch(void); - void _max30001RegWrite(unsigned char WRITE_ADDRESS, unsigned long data); - void _max30001RegRead(uint8_t Reg_address, uint8_t *buff); - void _max30001SwReset(void); - - int _cs_pin; -}; - #define WREG 0x00 #define RREG 0x01 @@ -82,7 +79,7 @@ class MAX30001 #define CNFG_EMUX 0x14 #define CNFG_ECG 0x15 -#define CNFG_BIOZ_LC 0x1A +#define CNFG_BIOZ_LC 0x1A #define CNFG_BMUX 0x17 #define CNFG_BIOZ 0x18 @@ -102,4 +99,203 @@ class MAX30001 #define CLK_PIN 6 #define RTOR_INTR_MASK 0x04 +enum EN_INT_bits +{ + EN_EINT = 0x800000, + EN_ECG_FIFO_OVF = 0x400000, + EN_ECG_FAST_REC = 0x200000, + EN_DCLOFFINT = 0x100000, + EN_BIOZ_FIFO_INT = 0x80000, + EN_BIOZ_FIFO_OVF = 0x40000, + EN_BIOZ_OVER_RANGE = 0x20000, + EN_BIOZ_UNDER_RANGE = 0x10000, + EN_BIOZ_CG_MON = 0x8000, + + EN_LONINT = 0x800, + EN_RRINT = 0x400, + EN_SAMP = 0x200, + EN_PLLINT = 0x100, + + EN_BCGMP = 0x20, + EN_BCGMN = 0x10, + EN_LDOFF_PH = 0x8, + EN_LDOFF_PL = 0x4, + EN_LDOFF_NH = 0x2, + EN_LDOFF_NL = 0x1 +}; + +typedef union max30001_status_reg +{ + uint32_t all; + + struct + { + uint32_t loff_nl : 1; + uint32_t loff_nh : 1; + uint32_t loff_pl : 1; + uint32_t loff_ph : 1; + + uint32_t bcgmn : 1; + uint32_t bcgmp : 1; + uint32_t reserved1 : 1; + uint32_t reserved2 : 1; + + uint32_t pllint : 1; + uint32_t samp : 1; + uint32_t rrint : 1; + uint32_t lonint : 1; + + uint32_t pedge : 1; + uint32_t povf : 1; + uint32_t pint : 1; + uint32_t bcgmon : 1; + + uint32_t bundr : 1; + uint32_t bover : 1; + uint32_t bovf : 1; + uint32_t bint : 1; + + uint32_t dcloffint : 1; + uint32_t fstint : 1; + uint32_t eovf : 1; + uint32_t eint : 1; + + uint32_t reserved : 8; + + } bit; + +} max30001_status_t; + +/** + * @brief MNGR_INT (0x04) + */ +typedef union max30001_mngr_int_reg +{ + uint32_t all; + + struct + { + uint32_t samp_it : 2; + uint32_t clr_samp : 1; + uint32_t clr_pedge : 1; + uint32_t clr_rrint : 2; + uint32_t clr_fast : 1; + uint32_t reserved1 : 1; + uint32_t reserved2 : 4; + uint32_t reserved3 : 4; + + uint32_t b_fit : 3; + uint32_t e_fit : 5; + + uint32_t reserved : 8; + + } bit; + +} max30001_mngr_int_t; + +/** + * @brief CNFG_BMUX (0x17) + */ +typedef union max30001_cnfg_bmux_reg +{ + uint32_t all; + struct + { + uint32_t fbist : 2; + uint32_t reserved1 : 2; + uint32_t rmod : 3; + uint32_t reserved2 : 1; + uint32_t rnom : 3; + uint32_t en_bist : 1; + uint32_t cg_mode : 2; + uint32_t reserved3 : 2; + uint32_t caln_sel : 2; + uint32_t calp_sel : 2; + uint32_t openn : 1; + uint32_t openp : 1; + uint32_t reserved4 : 2; + uint32_t reserved : 8; + } bit; + +} max30001_cnfg_bmux_t; + +/** + * @brief CNFG_BIOZ (0x18) + */ +typedef union max30001_bioz_reg +{ + uint32_t all; + struct + { + uint32_t phoff : 4; + uint32_t cgmag : 3; + uint32_t cgmon : 1; + uint32_t fcgen : 4; + uint32_t dlpf : 2; + uint32_t dhpf : 2; + uint32_t gain : 2; + uint32_t ln_bioz : 1; + uint32_t ext_rbias : 1; + uint32_t ahpf : 3; + uint32_t rate : 1; + uint32_t reserved : 8; + } bit; + +} max30001_cnfg_bioz_t; + +typedef enum +{ + SAMPLINGRATE_128 = 128, + SAMPLINGRATE_256 = 256, + SAMPLINGRATE_512 = 512 +} sampRate; + +class MAX30001 +{ +public: + MAX30001(int cs_pin); + unsigned int heartRate; + unsigned int RRinterval; + signed long ecg_data; + signed long bioz_data; + + volatile int ecgSamplesAvailable; + volatile int biozSamplesAvailable; + signed long s32ECGData[128]; + signed long s32BIOZData[128]; + + void BeginECGOnly(); + void BeginECGBioZ(); + void BeginRtoRMode(); + + signed long getECGSamples(void); + signed long getBioZSamples(void); + void getHRandRR(void); + + bool max30001ReadInfo(void); + void max30001SetsamplingRate(uint16_t samplingRate); + + void max30001SetInterrupts(uint32_t interrupts); + void max30001ServiceAllInterrupts(); + + void readStatus(void); + +private: + void _max30001ReadECGFIFO(int num_bytes); + void _max30001ReadBIOZFIFO(int num_bytes); + + void _max30001Synch(void); + void _max30001RegWrite(unsigned char WRITE_ADDRESS, unsigned long data); + void _max30001RegRead(uint8_t Reg_address, uint8_t *buff); + void _max30001RegRead24(uint8_t Reg_address, uint32_t *read_data); + + void _max30001SwReset(void); + void _max30001FIFOReset(void); + + max30001_status_t global_status; + int _cs_pin; + volatile unsigned char _readBufferECG[128]; // 4*32 samples + volatile unsigned char _readBufferBIOZ[128]; // 4*32 samples +}; + #endif