A collection of Analog Devices drivers for the mbed platform

For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all

Files at this revision

API Documentation at this revision

Comitter:
Adrian Suciu
Date:
Mon Oct 24 18:15:23 2016 +0300
Parent:
29:c693bdaac786
Child:
31:511c6ff17de3
Commit message:
Added example and library for the CN0398

Changed in this revision

examples/cn0398_example/Makefile Show annotated file Show diff for this revision Revisions of this file
examples/cn0398_example/main.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/AD7124/AD7124.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/AD7124/AD7124.h Show annotated file Show diff for this revision Revisions of this file
libraries/AD7124/AD7124_regs.h Show annotated file Show diff for this revision Revisions of this file
libraries/CN0398/CN0398.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/CN0398/CN0398.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cn0398_example/Makefile	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,97 @@
+# This file was automagically generated by mbed.org. For more information, 
+# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
+
+ifeq ($(OS), Windows_NT)
+  # insert Windows path to arm-none-eabi toolchain
+  GCC_BIN = C:/Program\ Files\ \(x86\)/GNU\ Tools\ ARM\ Embedded/5.2\ 2015q4/bin/
+else
+  # insert Linux path to arm-none-eabi toolchain
+  GCC_BIN = ~/workspace/tools/gcc-arm-none-eabi-5_3-2016q1/bin/
+endif
+
+PROJECT = CN0398-MBED
+ADI_LIBRARIES_PATH = ../../libraries
+MBED_LIBRARIES_PATH = ../../mbed
+OBJECTS = ./main.o $(ADI_LIBRARIES_PATH)/AD7124/AD7124.o $(ADI_LIBRARIES_PATH)/CN0398/CN0398.o 
+SYS_OBJECTS = $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ramfunc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/board.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/cmsis_nvic.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/hal_tick.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/mbed_overrides.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/retarget.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/startup_stm32f411xe.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_adc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_adc_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_can.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_cec.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_cortex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_crc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_cryp.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_cryp_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dac.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dac_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dcmi.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dcmi_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dma.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dma2d.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dma_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_dsi.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_eth.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_flash_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_fmpi2c_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_fmpi2c.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_msp_template.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_gpio.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_hash.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_hash_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_hcd.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_i2c.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_i2c_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_i2s.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_i2s_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_irda.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_iwdg.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_lptim.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_ltdc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_ltdc_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_smartcard.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_nand.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_nor.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_pccard.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_pcd.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_pcd_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_pwr.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_pwr_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_qspi.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_rcc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_rcc_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_rng.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_rtc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_rtc_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_sai.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_sai_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_sd.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_sdram.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_spdifrx.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_spi.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_sram.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_tim.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_tim_ex.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_uart.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_usart.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_hal_wwdg.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_ll_fmc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_ll_fsmc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_ll_sdmmc.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/stm32f4xx_ll_usb.o $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/system_stm32f4xx.o 
+INCLUDE_PATHS = -I. -I$(MBED_LIBRARIES_PATH) -I$(ADI_LIBRARIES_PATH) -I$(ADI_LIBRARIES_PATH)/AD7124 -I$(ADI_LIBRARIES_PATH)/CN0398 -I$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE -I$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TARGET_STM -I$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TARGET_STM/TARGET_STM32F4 -I$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F411RE -I$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM 
+LIBRARY_PATHS = -L$(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM 
+LIBRARIES = -lmbed 
+LINKER_SCRIPT = $(MBED_LIBRARIES_PATH)/TARGET_NUCLEO_F411RE/TOOLCHAIN_GCC_ARM/STM32F411XE.ld
+
+############################################################################### 
+AS      = $(GCC_BIN)arm-none-eabi-as
+CC      = $(GCC_BIN)arm-none-eabi-gcc
+CPP     = $(GCC_BIN)arm-none-eabi-g++
+LD      = $(GCC_BIN)arm-none-eabi-gcc
+OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
+OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
+SIZE    = $(GCC_BIN)arm-none-eabi-size 
+
+ifeq ($(HARDFP),1)
+	FLOAT_ABI = hard
+else
+	FLOAT_ABI = softfp
+endif
+
+
+CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI) 
+CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
+CC_SYMBOLS = -DTARGET_RTOS_M4_M7 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTARGET_NUCLEO_F411RE -D__CORTEX_M4 -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DMBED_BUILD_TIMESTAMP=1458639619.11 -DTARGET_M4 -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -DTARGET_FF_MORPHO -DTOOLCHAIN_GCC -DTARGET_STM32F411RE -DARM_MATH_CM4 
+
+LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
+LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
+
+
+ifeq ($(DEBUG), 1)
+  CC_FLAGS += -DDEBUG -g3
+else
+  CC_FLAGS += -DNDEBUG -g3
+endif
+
+.PHONY: all clean lst size
+
+all: $(PROJECT).bin $(PROJECT).hex size
+
+
+clean:
+	rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
+
+
+.asm.o:
+	$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
+.s.o:
+	$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
+.S.o:
+	$(CC) $(CPU) -c -x assembler-with-cpp -o $@ $<
+
+.c.o:
+	$(CC)  $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99   $(INCLUDE_PATHS) -o $@ $<
+
+.cpp.o:
+	$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $@ $<
+
+
+
+$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
+	$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $@ $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
+
+
+$(PROJECT).bin: $(PROJECT).elf
+	$(OBJCOPY) -O binary $< $@
+
+$(PROJECT).hex: $(PROJECT).elf
+	@$(OBJCOPY) -O ihex $< $@
+
+$(PROJECT).lst: $(PROJECT).elf
+	@$(OBJDUMP) -Sdh $< > $@
+
+lst: $(PROJECT).lst
+
+size: $(PROJECT).elf
+	$(SIZE) $(PROJECT).elf
+
+DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
+-include $(DEPS)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/cn0398_example/main.cpp	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,165 @@
+/**
+ *   @file     main.cpp
+ *   @brief    Main file for the CN0398-example project
+ *   @author   Analog Devices Inc.
+ *
+ * For support please go to:
+ * Github: https://github.com/analogdevicesinc/mbed-adi
+ * Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers
+ * Product: www.analog.com/EVAL-CN0398-ARDZ
+ * More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
+
+ ********************************************************************************
+ * Copyright 2016(c) Analog Devices, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Analog Devices, Inc. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *  - The use of this software may or may not infringe the patent rights
+ *    of one or more patent holders.  This license does not release you
+ *    from the requirement that you obtain separate licenses from these
+ *    patent holders to use this software.
+ *  - Use of the software either in source or binary form, must be run
+ *    on or directly connected to an Analog Devices Inc. component.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************/
+#include "mbed.h"
+#include "CN0398.h"
+
+Serial pc(SERIAL_TX, SERIAL_RX);
+
+/**
+ * @brief: Prints calibration solutions
+ */
+void print_calibration_solutions()
+{
+    pc.printf("0. ACETATE\n1. BORATE\n2. CAOH2\n3. CARBONATE\n4. CITRATE\n5. HCL\n6. OXALATE\n7. PHOSPHATE0\n8. PHOSPHATE1\n9. PHOSPHATE2\nA. PHTHALATE\nB. TARTRATE\nC. TRIS\nD. pH4\nE. pH 10");
+}
+
+/**
+ * @brief: flushes the serial interface.
+ */
+void flush_serial()
+{
+    wait_ms(10); // wait for all data to come through
+    while (pc.readable())  pc.getc();
+}
+
+int main()
+{
+    pc.baud(115200);
+    CN0398 cn0398(D10, D4);
+    cn0398.reset();
+    cn0398.setup();
+    cn0398.init();
+    wait_ms(500);
+    pc.printf("Done\r\n");
+
+    pc.printf("Do you want to perform calibration [y/N] ? ");
+    char response = pc.getc();
+    flush_serial();
+    if(response == 'y' || response == 'Y') {
+        pc.printf("Do you want to calibrate offset voltage [y/N] ? ");
+        response = pc.getc();
+        flush_serial();
+        if(response == 'y' || response == 'Y') {
+            pc.printf("Calibration step 0. Short the pH probe and press any key to calibrate.\r\n");
+            pc.getc();
+            flush_serial();
+            cn0398.calibrate_ph_offset();
+        }
+        print_calibration_solutions();
+
+        bool response_ok = false;
+        while(response_ok == false) {
+            pc.printf("\nInput calibration solution used for first step [1-9][a-e] \n");
+            char response = pc.getc();
+            flush_serial();
+            if(response >= '0' && response <= '9')	{
+                response_ok = true;
+                cn0398.solution0 = response - '0';
+            } else if(response >= 'A' && response <= 'E') {
+                response_ok = true;
+                cn0398.solution0 = response - 'A' + 10;
+            } else if(response >= 'a' && response <= 'e') {
+                response_ok = true;
+                cn0398.solution0 = response - 'a' + 10;
+            } else {
+                response_ok = false;
+            }
+        }
+        pc.printf("%s solution selected. pH of the solution @ 25 degrees = %f \n", solutions[cn0398.solution0], ph_temp_lut[cn0398.solution0][11]);
+        float temperature = cn0398.read_rtd();
+        pc.printf("Calibration step 1. Place pH probe in first calibration solution and press any key to start calibration.\r\n");
+        pc.getc();
+        flush_serial();
+        cn0398.calibrate_ph_pt0(temperature);
+
+        response_ok = false;
+        while(response_ok == false) {
+            pc.printf("Input calibration solution used for second step [1-9][a-e] \n");
+            char response = pc.getc();
+            flush_serial();
+            if(response >= '0' && response <= '9')	{
+                response_ok = true;
+                cn0398.solution1 = response - '0';
+            } else if(response >= 'A' && response <= 'E') {
+                response_ok = true;
+                cn0398.solution1 = response - 'A' + 10;
+            } else if(response >= 'a' && response <= 'e') {
+                response_ok = true;
+                cn0398.solution1 = response - 'a' + 10;
+            } else {
+                response_ok = false;
+            }
+        }
+        pc.printf("%s solution selected. pH of the solution @ 25 degrees = %f \n", solutions[cn0398.solution1], ph_temp_lut[cn0398.solution1][11]);
+        pc.printf("Calibration step 2. Place pH probe in second calibration solution and press any key to start calibration.\r\n");
+        pc.getc();
+        flush_serial();
+        cn0398.calibrate_ph_pt1(temperature);
+
+    } else {
+        cn0398.use_nernst = true;
+        pc.printf("Do you want to load default calibration. If not, the Nernst equation will be used [y/N] ? ");
+        char response = pc.getc();
+        flush_serial();
+        if(response == 'y' || response == 'Y') {
+            cn0398.use_nernst = false;
+        }
+    }
+
+
+    while(1) {
+        float temperature = cn0398.read_rtd();
+        pc.printf("Temperature: %f\r\n", temperature);
+        pc.printf("pH: %f\r\n", cn0398.read_ph(temperature));
+#ifdef MOISTURE_SENSOR_PRESENT
+        pc.printf("Moisture: %f\r\n", cn0398.read_moist());
+#endif
+        pc.printf("\r\n");
+        wait_ms(1000);
+    }
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/AD7124/AD7124.cpp	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,597 @@
+/**
+*   @file     AD7124.cpp
+*   @brief    Source file for AD7124 ADC
+*   @author   Analog Devices Inc.
+*
+* For support please go to:
+* Github: https://github.com/analogdevicesinc/mbed-adi
+* Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers
+* Product: http://www.analog.com/ad7124
+* More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
+
+********************************************************************************
+* Copyright 2016(c) Analog Devices, Inc.
+*
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in
+*    the documentation and/or other materials provided with the
+*    distribution.
+*  - Neither the name of Analog Devices, Inc. nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*  - The use of this software may or may not infringe the patent rights
+*    of one or more patent holders.  This license does not release you
+*    from the requirement that you obtain separate licenses from these
+*    patent holders to use this software.
+*  - Use of the software either in source or binary form, must be run
+*    on or directly connected to an Analog Devices Inc. component.
+*
+* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************/
+
+#include <stdint.h>
+#include "mbed.h"
+#include "AD7124.h"
+
+/**
+ * @brief AD7790 constructor, sets CS pin and SPI format
+ * @param CS - (optional)chip select of the AD7790
+ * @param MOSI - (optional)pin of the SPI interface
+ * @param MISO - (optional)pin of the SPI interface
+ * @param SCK  - (optional)pin of the SPI interface
+ */
+AD7124::AD7124(PinName CS,
+               PinName MOSI,
+               PinName MISO,
+               PinName SCK) :
+    miso(MISO), ad7124(MOSI, MISO, SCK), cs(CS)
+{
+    cs = true; // cs is active low
+    ad7124.format(8, _SPI_MODE);
+    this->regs = ad7124_regs;
+    this->useCRC = false;
+}
+
+/**
+ * @brief Set AD7790 SPI frequency
+ * @param hz - SPI bus frequency in hz
+ * @return none
+ */
+void AD7124::frequency(int hz)
+{
+    ad7124.frequency(hz);
+}
+
+/**
+ * @brief Resets the AD7790
+ * @return none
+ */
+/*void AD7124::reset()
+{
+    ad7124.format(8, _SPI_MODE);
+    cs = false;
+    wait_us(_DELAY_TIMING);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    ad7124.write(_RESET);
+    wait_us(_DELAY_TIMING);
+    cs = true;
+    //_continous_conversion = true;
+}*/
+/**
+ * @brief Reads a register of the AD7790
+ * @param  address - address of the register
+ * @return value of the register
+ */
+uint16_t AD7124::read_reg(uint8_t address)
+{
+    uint16_t data = address << 8;
+    data |= _DUMMY_BYTE;
+    data |= _READ_FLAG;
+    return	write_spi(data);
+}
+
+/**
+ * @brief Writes a register of the AD7790
+ * @param address - address of the register
+ * @param reg_val - value to be written
+ * @return none
+ *
+ */
+void AD7124::write_reg(uint8_t address, uint8_t reg_val)
+{
+    uint16_t spi_data = address << 8;
+    spi_data |= reg_val;
+    write_spi(spi_data);
+}
+
+/**
+ * @brief Writes 16bit data to the AD7790 SPI interface
+ * @param reg_val to be written
+ * @return data returned by the AD7790
+ */
+uint16_t AD7124::write_spi(uint16_t reg_val)
+{
+    uint16_t data_result;
+    uint8_t upper_byte = (reg_val >> 8) & 0xFF;
+    uint8_t lower_byte = reg_val & 0xFF;
+    ad7124.format(8, _SPI_MODE);
+    cs = false;
+    data_result  =  (ad7124.write(upper_byte) << 8);
+    data_result |=   ad7124.write(lower_byte);
+    cs = true;
+    return data_result;
+}
+
+
+
+/***************************************************************************//**
+* @brief Reads the value of the specified register without checking if the
+*        device is ready to accept user requests.
+*
+* @param device - The handler of the instance of the driver.
+* @param pReg - Pointer to the register structure holding info about the
+*               register to be read. The read value is stored inside the
+*               register structure.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::NoCheckReadRegister(ad7124_st_reg* pReg)
+{
+    int32_t ret       = 0;
+    uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    uint8_t i         = 0;
+    uint8_t check8    = 0;
+    uint8_t msgBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+
+    check8 = useCRC;
+
+    /* Build the Command word */
+    buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+                AD7124_COMM_REG_RA(pReg->addr);
+
+    /* Read data from the device */
+    ret = SPI_Read(buffer,
+                   ((useCRC != AD7124_DISABLE_CRC) ? pReg->size + 1
+                    : pReg->size) + 1);
+    if(ret < 0)
+        return ret;
+
+    /* Check the CRC */
+    if(check8 == AD7124_USE_CRC) {
+        msgBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+                    AD7124_COMM_REG_RA(pReg->addr);
+        for(i = 1; i < pReg->size + 2; ++i) {
+            msgBuf[i] = buffer[i];
+        }
+        check8 = ComputeCRC8(msgBuf, pReg->size + 2);
+    }
+
+    if(check8 != 0) {
+        /* ReadRegister checksum failed. */
+        return COMM_ERR;
+    }
+
+    /* Build the result */
+    pReg->value = 0;
+    for(i = 1; i < pReg->size + 1; i++) {
+        pReg->value <<= 8;
+        pReg->value += buffer[i];
+    }
+
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Writes the value of the specified register without checking if the
+*        device is ready to accept user requests.
+*
+* @param device - The handler of the instance of the driver.
+* @param reg - Register structure holding info about the register to be written
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::NoCheckWriteRegister(ad7124_st_reg reg)
+{
+    int32_t ret      = 0;
+    int32_t regValue = 0;
+    uint8_t wrBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    uint8_t i        = 0;
+    uint8_t crc8     = 0;
+
+
+    /* Build the Command word */
+    wrBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR |
+               AD7124_COMM_REG_RA(reg.addr);
+
+    /* Fill the write buffer */
+    regValue = reg.value;
+    for(i = 0; i < reg.size; i++) {
+        wrBuf[reg.size - i] = regValue & 0xFF;
+        regValue >>= 8;
+    }
+
+    /* Compute the CRC */
+    if(useCRC != AD7124_DISABLE_CRC) {
+        crc8 = ComputeCRC8(wrBuf, reg.size + 1);
+        wrBuf[reg.size + 1] = crc8;
+    }
+
+    /* Write data to the device */
+    ret = SPI_Write(wrBuf,
+                    (useCRC != AD7124_DISABLE_CRC) ? reg.size + 2
+                    : reg.size + 1);
+
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Reads the value of the specified register only when the device is ready
+*        to accept user requests. If the device ready flag is deactivated the
+*        read operation will be executed without checking the device state.
+*
+* @param device - The handler of the instance of the driver.
+* @param pReg - Pointer to the register structure holding info about the
+*               register to be read. The read value is stored inside the
+*               register structure.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::ReadRegister(ad7124_st_reg* pReg)
+{
+    int32_t ret;
+
+    if (pReg->addr != ERR_REG && check_ready) {
+        ret = WaitForSpiReady(spi_rdy_poll_cnt);
+        if (ret < 0)
+            return ret;
+    }
+    ret = NoCheckReadRegister(pReg);
+
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Writes the value of the specified register only when the device is
+*        ready to accept user requests. If the device ready flag is deactivated
+*        the write operation will be executed without checking the device state.
+*
+* @param device - The handler of the instance of the driver.
+* @param reg - Register structure holding info about the register to be written
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::WriteRegister(ad7124_st_reg pReg)
+{
+    int32_t ret;
+
+    if (check_ready) {
+        ret = WaitForSpiReady(spi_rdy_poll_cnt);
+        if (ret < 0)
+            return ret;
+    }
+    ret = NoCheckWriteRegister(pReg);
+
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Reads and returns the value of a device register. The read value is
+*        also stored in software register list of the device.
+*
+* @param device - The handler of the instance of the driver.
+* @param reg - Which register to read from.
+* @param pError - Pointer to the location where to store the error code if an
+*                 error occurs. Stores 0 for success or negative error code.
+*                 Does not store anything if pErorr = NULL;
+*
+* @return Returns the value read from the specified register.
+*******************************************************************************/
+uint32_t AD7124::ReadDeviceRegister(enum ad7124_registers reg)
+{
+    ReadRegister(&regs[reg]);
+    return (regs[reg].value);
+}
+
+/***************************************************************************//**
+* @brief Writes the specified value to a device register. The value to be
+*        written is also stored in the software register list of the device.
+*
+* @param device - The handler of the instance of the driver.
+* @param reg - Which register to write to.
+* @param value - The value to be written to the reigster of the device.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::WriteDeviceRegister(enum ad7124_registers reg, uint32_t value)
+{
+    regs[reg].value = value;
+    return(WriteRegister(regs[reg]));
+}
+
+/***************************************************************************//**
+* @brief Resets the device.
+*
+* @param device - The handler of the instance of the driver.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::Reset()
+{
+    int32_t ret = 0;
+    uint8_t wrBuf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+    ret = SPI_Write( wrBuf, 8);
+
+
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Waits until the device can accept read and write user actions.
+*
+* @param device - The handler of the instance of the driver.
+* @param timeout - Count representing the number of polls to be done until the
+*                  function returns.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::WaitForSpiReady(uint32_t timeout)
+{
+    ad7124_st_reg *regs;
+    int32_t ret;
+    int8_t ready = 0;
+
+    regs = this->regs;
+
+    while(!ready && --timeout) {
+        /* Read the value of the Error Register */
+        ret = ReadRegister(&regs[AD7124_Error]);
+        if(ret < 0)
+            return ret;
+
+        /* Check the SPI IGNORE Error bit in the Error Register */
+        ready = (regs[AD7124_Error].value &
+                 AD7124_ERR_REG_SPI_IGNORE_ERR) == 0;
+    }
+
+    return timeout ? 0 : TIMEOUT;
+}
+
+/***************************************************************************//**
+* @brief Waits until a new conversion result is available.
+*
+* @param device - The handler of the instance of the driver.
+* @param timeout - Count representing the number of polls to be done until the
+*                  function returns if no new data is available.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::WaitForConvReady(uint32_t timeout)
+{
+    ad7124_st_reg *regs;
+    int32_t ret;
+    int8_t ready = 0;
+
+    regs = this->regs;
+
+    while(!ready && --timeout) {
+        /* Read the value of the Status Register */
+        ret = ReadRegister(&regs[AD7124_Status]);
+        if(ret < 0)
+            return ret;
+
+        /* Check the RDY bit in the Status Register */
+        ready = (regs[AD7124_Status].value &
+                 AD7124_STATUS_REG_RDY) == 0;
+        wait_ms(1);
+    }
+
+    return timeout ? 0 : TIMEOUT;
+}
+
+bool AD7124::get_miso()
+{
+    return miso.read();
+}
+
+/***************************************************************************//**
+* @brief Reads the conversion result from the device.
+*
+* @param device - The handler of the instance of the driver.
+* @param pData - Pointer to store the read data.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::ReadData( int32_t* pData)
+{
+    int32_t ret       = 0;
+    uint8_t check8    = 0;
+    uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    uint8_t i         = 0;
+    uint8_t msgBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    ad7124_st_reg *pReg;
+
+    if( !pData)
+        return INVALID_VAL;
+
+    pReg = &regs[AD7124_Data];
+
+    /* Build the Command word */
+    buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+                AD7124_COMM_REG_RA(pReg->addr);
+
+
+    /* Read data from the device */
+    ret = SPI_Read(buffer,
+                   ((useCRC != AD7124_DISABLE_CRC) ? pReg->size + 1
+                    : pReg->size) + 2);
+
+    if(ret < 0)
+        return ret;
+
+    /* Check the CRC */
+    if(check8 == AD7124_USE_CRC) {
+        msgBuf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+                    AD7124_COMM_REG_RA(pReg->addr);
+        for(i = 1; i < pReg->size + 2; ++i) {
+            msgBuf[i] = buffer[i];
+        }
+        check8 = ComputeCRC8(msgBuf, pReg->size + 3);
+    }
+
+    if(check8 != 0) {
+        /* ReadRegister checksum failed. */
+        return COMM_ERR;
+    }
+
+    /* Build the result */
+    *pData = 0;
+    for(i = 1; i < pReg->size + 2; i++) {
+        *pData <<= 8;
+        *pData += buffer[i];
+    }
+    wait_ms(500);
+    return ret;
+}
+
+/***************************************************************************//**
+* @brief Computes the CRC checksum for a data buffer.
+*
+* @param pBuf - Data buffer
+* @param bufSize - Data buffer size in bytes
+*
+* @return Returns the computed CRC checksum.
+*******************************************************************************/
+uint8_t AD7124::ComputeCRC8(uint8_t * pBuf, uint8_t bufSize)
+{
+    uint8_t i   = 0;
+    uint8_t crc = 0;
+
+    while(bufSize) {
+        for(i = 0x80; i != 0; i >>= 1) {
+            if(((crc & 0x80) != 0) != ((*pBuf & i) != 0)) { /* MSB of CRC register XOR input Bit from Data */
+                crc <<= 1;
+                crc ^= AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
+            } else {
+                crc <<= 1;
+            }
+        }
+        pBuf++;
+        bufSize--;
+    }
+    return crc;
+}
+
+
+/***************************************************************************//**
+* @brief Updates the device SPI interface settings.
+*
+* @param device - The handler of the instance of the driver.
+*
+* @return None.
+*******************************************************************************/
+void AD7124::UpdateDevSpiSettings()
+{
+    ad7124_st_reg *regs;
+
+    regs = this->regs;
+
+    if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN) {
+        check_ready = 1;
+    } else {
+        check_ready = 0;
+    }
+}
+
+/***************************************************************************//**
+* @brief Initializes the AD7124.
+*
+* @param device - The handler of the instance of the driver.
+* @param slave_select - The Slave Chip Select Id to be passed to the SPI calls.
+* @param regs - The list of registers of the device (initialized or not) to be
+*               added to the instance of the driver.
+*
+* @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t AD7124::Setup()
+{
+    int32_t ret;
+    uint8_t regNr;
+
+
+    spi_rdy_poll_cnt = 25000;
+
+    /* Initialize the SPI communication. */
+    /*ret = SPI_Init(0, 2500000, 1, 0);
+    if (ret < 0)
+        return ret;*/
+
+    /*  Reset the device interface.*/
+    ret = Reset();
+    if (ret < 0)
+        return ret;
+
+    check_ready = 1;
+
+    /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */
+    for(regNr = static_cast<uint8_t>(AD7124_Status); (regNr < static_cast<uint8_t>(AD7124_Offset_0)) && !(ret < 0);
+            regNr++) {
+        if (regs[regNr].rw == AD7124_RW) {
+            ret = WriteRegister(regs[regNr]);
+            if (ret < 0)
+                break;
+        }
+
+        /* Get CRC State and device SPI interface settings */
+        if (regNr == AD7124_Error_En) {
+            UpdateDevSpiSettings();
+        }
+    }
+
+    return ret;
+}
+
+uint8_t AD7124::SPI_Read(uint8_t *data, uint8_t bytes_number)
+{
+    cs = false;
+    for(uint8_t byte = 0; byte < bytes_number; byte++) {
+        data[byte] = ad7124.write(data[byte]);
+    }
+    cs = true;
+    return bytes_number;
+}
+
+uint8_t AD7124::SPI_Write(uint8_t *data, uint8_t bytes_number)
+{
+    cs = false;
+    for(uint8_t byte = 0; byte < bytes_number; byte++) {
+        ad7124.write(data[byte]);
+    }
+
+    cs = true;
+    return bytes_number;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/AD7124/AD7124.h	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,492 @@
+/**
+*   @file     AD7124.h
+*   @brief    Header file for AD7790 ADC
+*   @author   Analog Devices Inc.
+*
+* For support please go to:
+* Github: https://github.com/analogdevicesinc/mbed-adi
+* Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers
+* Product: http://www.analog.com/AD7124
+* More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
+
+********************************************************************************
+* Copyright 2016(c) Analog Devices, Inc.
+*
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in
+*    the documentation and/or other materials provided with the
+*    distribution.
+*  - Neither the name of Analog Devices, Inc. nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*  - The use of this software may or may not infringe the patent rights
+*    of one or more patent holders.  This license does not release you
+*    from the requirement that you obtain separate licenses from these
+*    patent holders to use this software.
+*  - Use of the software either in source or binary form, must be run
+*    on or directly connected to an Analog Devices Inc. component.
+*
+* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+********************************************************************************/
+
+#ifndef AD7790_H
+#define AD7790_H
+
+#include "mbed.h"
+#include "AD7124_regs.h"
+
+/**
+ * Comment this line if you want to turn off the debug mode.
+ * The debug mode will send a message if an exception occurs within AD7790 driver
+ */
+
+#define AD7124_DEBUG_MODE
+
+/**
+ * @brief Analog Devices AD7790 SPI 16-bit Buffered Sigma-Delta ADC
+ */
+class AD7124
+{
+public:
+    enum ad7124_registers {
+        AD7124_Status = 0x00,
+        AD7124_ADC_Control,
+        AD7124_Data,
+        AD7124_IOCon1,
+        AD7124_IOCon2,
+        AD7124_ID,
+        AD7124_Error,
+        AD7124_Error_En,
+        AD7124_Mclk_Count,
+        AD7124_Channel_0,
+        AD7124_Channel_1,
+        AD7124_Channel_2,
+        AD7124_Channel_3,
+        AD7124_Channel_4,
+        AD7124_Channel_5,
+        AD7124_Channel_6,
+        AD7124_Channel_7,
+        AD7124_Channel_8,
+        AD7124_Channel_9,
+        AD7124_Channel_10,
+        AD7124_Channel_11,
+        AD7124_Channel_12,
+        AD7124_Channel_13,
+        AD7124_Channel_14,
+        AD7124_Channel_15,
+        AD7124_Config_0,
+        AD7124_Config_1,
+        AD7124_Config_2,
+        AD7124_Config_3,
+        AD7124_Config_4,
+        AD7124_Config_5,
+        AD7124_Config_6,
+        AD7124_Config_7,
+        AD7124_Filter_0,
+        AD7124_Filter_1,
+        AD7124_Filter_2,
+        AD7124_Filter_3,
+        AD7124_Filter_4,
+        AD7124_Filter_5,
+        AD7124_Filter_6,
+        AD7124_Filter_7,
+        AD7124_Offset_0,
+        AD7124_Offset_1,
+        AD7124_Offset_2,
+        AD7124_Offset_3,
+        AD7124_Offset_4,
+        AD7124_Offset_5,
+        AD7124_Offset_6,
+        AD7124_Offset_7,
+        AD7124_Gain_0,
+        AD7124_Gain_1,
+        AD7124_Gain_2,
+        AD7124_Gain_3,
+        AD7124_Gain_4,
+        AD7124_Gain_5,
+        AD7124_Gain_6,
+        AD7124_Gain_7,
+        AD7124_REG_NO
+    };
+private:
+    enum {
+        AD7124_RW = 1,   /* Read and Write */
+        AD7124_R  = 2,   /* Read only */
+        AD7124_W  = 3,   /* Write only */
+    } ad7124_reg_access;
+
+    /*! Device register info */
+    typedef struct _ad7124_st_reg {
+        int32_t addr;
+        int32_t value;
+        int32_t size;
+        int32_t rw;
+    } ad7124_st_reg;
+
+
+    /*! Array holding the info for the ad7124 registers - address, initial value,
+    size and access type. */
+    ad7124_st_reg ad7124_regs[57] = {
+        {0x00, 0x00,   1, 2}, /* AD7124_Status */
+        {0x01, 0x0000, 2, 1}, /* AD7124_ADC_Control */
+        {0x02, 0x0000, 3, 2}, /* AD7124_Data */
+        {0x03, 0x0000, 3, 1}, /* AD7124_IOCon1 */
+        {0x04, 0x0000, 2, 1}, /* AD7124_IOCon2 */
+        {0x05, 0x12,   1, 2}, /* AD7124_ID */
+        {0x06, 0x0000, 3, 2}, /* AD7124_Error */
+        {0x07, 0x0400, 3, 1}, /* AD7124_Error_En */
+        {0x08, 0x00,   1, 2}, /* AD7124_Mclk_Count */
+        {0x09, 0x8001, 2, 1}, /* AD7124_Channel_0 */
+        {0x0A, 0x0001, 2, 1}, /* AD7124_Channel_1 */
+        {0x0B, 0x0001, 2, 1}, /* AD7124_Channel_2 */
+        {0x0C, 0x0001, 2, 1}, /* AD7124_Channel_3 */
+        {0x0D, 0x0001, 2, 1}, /* AD7124_Channel_4 */
+        {0x0E, 0x0001, 2, 1}, /* AD7124_Channel_5 */
+        {0x0F, 0x0001, 2, 1}, /* AD7124_Channel_6 */
+        {0x10, 0x0001, 2, 1}, /* AD7124_Channel_7 */
+        {0x11, 0x0001, 2, 1}, /* AD7124_Channel_8 */
+        {0x12, 0x0001, 2, 1}, /* AD7124_Channel_9 */
+        {0x13, 0x0001, 2, 1}, /* AD7124_Channel_10 */
+        {0x14, 0x0001, 2, 1}, /* AD7124_Channel_11 */
+        {0x15, 0x0001, 2, 1}, /* AD7124_Channel_12 */
+        {0x16, 0x0001, 2, 1}, /* AD7124_Channel_13 */
+        {0x17, 0x0001, 2, 1}, /* AD7124_Channel_14 */
+        {0x18, 0x0001, 2, 1}, /* AD7124_Channel_15 */
+        {0x19, 0x0860, 2, 1}, /* AD7124_Config_0 */
+        {0x1A, 0x0860, 2, 1}, /* AD7124_Config_1 */
+        {0x1B, 0x0860, 2, 1}, /* AD7124_Config_2 */
+        {0x1C, 0x0860, 2, 1}, /* AD7124_Config_3 */
+        {0x1D, 0x0860, 2, 1}, /* AD7124_Config_4 */
+        {0x1E, 0x0860, 2, 1}, /* AD7124_Config_5 */
+        {0x1F, 0x0860, 2, 1}, /* AD7124_Config_6 */
+        {0x20, 0x0860, 2, 1}, /* AD7124_Config_7 */
+        {0x21, 0x060180, 3, 1}, /* AD7124_Filter_0 */
+        {0x22, 0x060180, 3, 1}, /* AD7124_Filter_1 */
+        {0x23, 0x060180, 3, 1}, /* AD7124_Filter_2 */
+        {0x24, 0x060180, 3, 1}, /* AD7124_Filter_3 */
+        {0x25, 0x060180, 3, 1}, /* AD7124_Filter_4 */
+        {0x26, 0x060180, 3, 1}, /* AD7124_Filter_5 */
+        {0x27, 0x060180, 3, 1}, /* AD7124_Filter_6 */
+        {0x28, 0x060180, 3, 1}, /* AD7124_Filter_7 */
+        {0x29, 0x800000, 3, 1}, /* AD7124_Offset_0 */
+        {0x2A, 0x800000, 3, 1}, /* AD7124_Offset_1 */
+        {0x2B, 0x800000, 3, 1}, /* AD7124_Offset_2 */
+        {0x2C, 0x800000, 3, 1}, /* AD7124_Offset_3 */
+        {0x2D, 0x800000, 3, 1}, /* AD7124_Offset_4 */
+        {0x2E, 0x800000, 3, 1}, /* AD7124_Offset_5 */
+        {0x2F, 0x800000, 3, 1}, /* AD7124_Offset_6 */
+        {0x30, 0x800000, 3, 1}, /* AD7124_Offset_7 */
+        {0x31, 0x500000, 3, 1}, /* AD7124_Gain_0 */
+        {0x32, 0x500000, 3, 1}, /* AD7124_Gain_1 */
+        {0x33, 0x500000, 3, 1}, /* AD7124_Gain_2 */
+        {0x34, 0x500000, 3, 1}, /* AD7124_Gain_3 */
+        {0x35, 0x500000, 3, 1}, /* AD7124_Gain_4 */
+        {0x36, 0x500000, 3, 1}, /* AD7124_Gain_5 */
+        {0x37, 0x500000, 3, 1}, /* AD7124_Gain_6 */
+        {0x38, 0x500000, 3, 1}, /* AD7124_Gain_7 */
+    };
+
+
+    /* AD7124 Register Map */
+    enum AD7124_reg_map  {
+        COMM_REG     = 0x00,
+        STATUS_REG   = 0x00,
+        ADC_CTRL_REG = 0x01,
+        DATA_REG     = 0x02,
+        IO_CTRL1_REG = 0x03,
+        IO_CTRL2_REG = 0x04,
+        ID_REG       = 0x05,
+        ERR_REG      = 0x06,
+        ERREN_REG    = 0x07,
+        CH0_MAP_REG  = 0x09,
+        CH1_MAP_REG  = 0x0A,
+        CH2_MAP_REG  = 0x0B,
+        CH3_MAP_REG  = 0x0C,
+        CH4_MAP_REG  = 0x0D,
+        CH5_MAP_REG  = 0x0E,
+        CH6_MAP_REG  = 0x0F,
+        CH7_MAP_REG  = 0x10,
+        CH8_MAP_REG  = 0x11,
+        CH9_MAP_REG  = 0x12,
+        CH10_MAP_REG = 0x13,
+        CH11_MAP_REG = 0x14,
+        CH12_MAP_REG = 0x15,
+        CH13_MAP_REG = 0x16,
+        CH14_MAP_REG = 0x17,
+        CH15_MAP_REG = 0x18,
+        CFG0_REG     = 0x19,
+        CFG1_REG     = 0x1A,
+        CFG2_REG     = 0x1B,
+        CFG3_REG     = 0x1C,
+        CFG4_REG     = 0x1D,
+        CFG5_REG     = 0x1E,
+        CFG6_REG     = 0x1F,
+        CFG7_REG     = 0x20,
+        FILT0_REG    = 0x21,
+        FILT1_REG    = 0x22,
+        FILT2_REG    = 0x23,
+        FILT3_REG    = 0x24,
+        FILT4_REG    = 0x25,
+        FILT5_REG    = 0x26,
+        FILT6_REG    = 0x27,
+        FILT7_REG    = 0x28,
+        OFFS0_REG    = 0x29,
+        OFFS1_REG    = 0x2A,
+        OFFS2_REG    = 0x2B,
+        OFFS3_REG    = 0x2C,
+        OFFS4_REG    = 0x2D,
+        OFFS5_REG    = 0x2E,
+        OFFS6_REG    = 0x2F,
+        OFFS7_REG    = 0x30,
+        GAIN0_REG    = 0x31,
+        GAIN1_REG    = 0x32,
+        GAIN2_REG    = 0x33,
+        GAIN3_REG    = 0x34,
+        GAIN4_REG    = 0x35,
+        GAIN5_REG    = 0x36,
+        GAIN6_REG    = 0x37,
+        GAIN7_REG    = 0x38,
+    };
+
+    /* Communication Register bits */
+#define AD7124_COMM_REG_WEN    (0 << 7)
+#define AD7124_COMM_REG_WR     (0 << 6)
+#define AD7124_COMM_REG_RD     (1 << 6)
+#define AD7124_COMM_REG_RA(x)  ((x) & 0x3F)
+
+    /* Status Register bits */
+#define AD7124_STATUS_REG_RDY          (1 << 7)
+#define AD7124_STATUS_REG_ERROR_FLAG   (1 << 6)
+#define AD7124_STATUS_REG_POR_FLAG     (1 << 4)
+#define AD7124_STATUS_REG_CH_ACTIVE(x) ((x) & 0xF)
+
+    /* ADC_Control Register bits */
+#define AD7124_ADC_CTRL_REG_DOUT_RDY_DEL   (1 << 12)
+#define AD7124_ADC_CTRL_REG_CONT_READ      (1 << 11)
+#define AD7124_ADC_CTRL_REG_DATA_STATUS    (1 << 10)
+#define AD7124_ADC_CTRL_REG_CS_EN          (1 << 9)
+#define AD7124_ADC_CTRL_REG_REF_EN         (1 << 8)
+#define AD7124_ADC_CTRL_REG_POWER_MODE(x)  (((x) & 0x3) << 6)
+#define AD7124_ADC_CTRL_REG_MODE(x)        (((x) & 0xF) << 2)
+#define AD7124_ADC_CTRL_REG_CLK_SEL(x)    (((x) & 0x3) << 0)
+
+    /* IO_Control_1 Register bits */
+#define AD7124_IO_CTRL1_REG_GPIO_DAT2     (1 << 23)
+#define AD7124_IO_CTRL1_REG_GPIO_DAT1     (1 << 22)
+#define AD7124_IO_CTRL1_REG_GPIO_CTRL2    (1 << 19)
+#define AD7124_IO_CTRL1_REG_GPIO_CTRL1    (1 << 18)
+#define AD7124_IO_CTRL1_REG_PDSW          (1 << 15)
+#define AD7124_IO_CTRL1_REG_IOUT1(x)      (((x) & 0x7) << 11)
+#define AD7124_IO_CTRL1_REG_IOUT0(x)      (((x) & 0x7) << 8)
+#define AD7124_IO_CTRL1_REG_IOUT_CH1(x)   (((x) & 0xF) << 4)
+#define AD7124_IO_CTRL1_REG_IOUT_CH0(x)   (((x) & 0xF) << 0)
+
+    /*IO_Control_1 AD7124-8 specific bits */
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT4     (1 << 23)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT3     (1 << 22)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT2     (1 << 21)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT1     (1 << 20)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL4    (1 << 19)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL3    (1 << 18)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL2    (1 << 17)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL1    (1 << 16)
+
+    /* IO_Control_2 Register bits */
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS7   (1 << 15)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS6   (1 << 14)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS5   (1 << 11)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS4   (1 << 10)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS3   (1 << 5)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS2   (1 << 4)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS1   (1 << 1)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS0   (1)
+
+    /*IO_Control_2 AD7124-8 specific bits */
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS15  (1 << 15)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS14  (1 << 14)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS13  (1 << 13)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS12  (1 << 12)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS11  (1 << 11)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS10  (1 << 10)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS9   (1 << 9)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS8   (1 << 8)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7   (1 << 7)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS6   (1 << 6)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS5   (1 << 5)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS4   (1 << 4)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS3   (1 << 3)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS2   (1 << 2)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS1   (1 << 1)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS0   (1 << 0)
+
+    /* ID Register bits */
+#define AD7124_ID_REG_DEVICE_ID(x)   (((x) & 0xF) << 4)
+#define AD7124_ID_REG_SILICON_REV(x) (((x) & 0xF) << 0)
+
+    /* Error Register bits */
+#define AD7124_ERR_REG_LDO_CAP_ERR        (1 << 19)
+#define AD7124_ERR_REG_ADC_CAL_ERR        (1 << 18)
+#define AD7124_ERR_REG_ADC_CONV_ERR       (1 << 17)
+#define AD7124_ERR_REG_ADC_SAT_ERR        (1 << 16)
+#define AD7124_ERR_REG_AINP_OV_ERR        (1 << 15)
+#define AD7124_ERR_REG_AINP_UV_ERR        (1 << 14)
+#define AD7124_ERR_REG_AINM_OV_ERR        (1 << 13)
+#define AD7124_ERR_REG_AINM_UV_ERR        (1 << 12)
+#define AD7124_ERR_REG_REF_DET_ERR        (1 << 11)
+#define AD7124_ERR_REG_DLDO_PSM_ERR       (1 << 9)
+#define AD7124_ERR_REG_ALDO_PSM_ERR       (1 << 7)
+#define AD7124_ERR_REG_SPI_IGNORE_ERR     (1 << 6)
+#define AD7124_ERR_REG_SPI_SLCK_CNT_ERR   (1 << 5)
+#define AD7124_ERR_REG_SPI_READ_ERR       (1 << 4)
+#define AD7124_ERR_REG_SPI_WRITE_ERR      (1 << 3)
+#define AD7124_ERR_REG_SPI_CRC_ERR        (1 << 2)
+#define AD7124_ERR_REG_MM_CRC_ERR         (1 << 1)
+
+    /* Error_En Register bits */
+#define AD7124_ERREN_REG_MCLK_CNT_EN           (1 << 22)
+#define AD7124_ERREN_REG_LDO_CAP_CHK_TEST_EN   (1 << 21)
+#define AD7124_ERREN_REG_LDO_CAP_CHK(x)        (((x) & 0x3) << 19)
+#define AD7124_ERREN_REG_ADC_CAL_ERR_EN        (1 << 18)
+#define AD7124_ERREN_REG_ADC_CONV_ERR_EN       (1 << 17)
+#define AD7124_ERREN_REG_ADC_SAT_ERR_EN        (1 << 16)
+#define AD7124_ERREN_REG_AINP_OV_ERR_EN        (1 << 15)
+#define AD7124_ERREN_REG_AINP_UV_ERR_EN        (1 << 14)
+#define AD7124_ERREN_REG_AINM_OV_ERR_EN        (1 << 13)
+#define AD7124_ERREN_REG_AINM_UV_ERR_EN        (1 << 12)
+#define AD7124_ERREN_REG_REF_DET_ERR_EN        (1 << 11)
+#define AD7124_ERREN_REG_DLDO_PSM_TRIP_TEST_EN (1 << 10)
+#define AD7124_ERREN_REG_DLDO_PSM_ERR_ERR      (1 << 9)
+#define AD7124_ERREN_REG_ALDO_PSM_TRIP_TEST_EN (1 << 8)
+#define AD7124_ERREN_REG_ALDO_PSM_ERR_EN       (1 << 7)
+#define AD7124_ERREN_REG_SPI_IGNORE_ERR_EN     (1 << 6)
+#define AD7124_ERREN_REG_SPI_SCLK_CNT_ERR_EN   (1 << 5)
+#define AD7124_ERREN_REG_SPI_READ_ERR_EN       (1 << 4)
+#define AD7124_ERREN_REG_SPI_WRITE_ERR_EN      (1 << 3)
+#define AD7124_ERREN_REG_SPI_CRC_ERR_EN        (1 << 2)
+#define AD7124_ERREN_REG_MM_CRC_ERR_EN         (1 << 1)
+
+    /* Channel Registers 0-15 bits */
+#define AD7124_CH_MAP_REG_CH_ENABLE    (1 << 15)
+#define AD7124_CH_MAP_REG_SETUP(x)     (((x) & 0x7) << 12)
+#define AD7124_CH_MAP_REG_AINP(x)      (((x) & 0x1F) << 5)
+#define AD7124_CH_MAP_REG_AINM(x)      (((x) & 0x1F) << 0)
+
+    /* Configuration Registers 0-7 bits */
+#define AD7124_CFG_REG_BIPOLAR     (1 << 11)
+#define AD7124_CFG_REG_BURNOUT(x)  (((x) & 0x3) << 9)
+#define AD7124_CFG_REG_REF_BUFP    (1 << 8)
+#define AD7124_CFG_REG_REF_BUFM    (1 << 7)
+#define AD7124_CFG_REG_AIN_BUFP    (1 << 6)
+#define AD7124_CFG_REG_AINN_BUFM   (1 << 5)
+#define AD7124_CFG_REG_REF_SEL(x)  ((x) & 0x3) << 3
+#define AD7124_CFG_REG_PGA(x)      (((x) & 0x7) << 0)
+
+    /* Filter Register 0-7 bits */
+#define AD7124_FILT_REG_FILTER(x)        ((uint32_t)((x) & 0x7) << 21)
+#define AD7124_FILT_REG_REJ60             ((uint32_t)1 << 20)
+#define AD7124_FILT_REG_POST_FILTER(x)    ((uint32_t)((x) & 0x7) << 17)
+#define AD7124_FILT_REG_SINGLE_CYCLE      ((uint32_t)1 << 16)
+#define AD7124_FILT_REG_FS(x)             ((uint32_t)((x) & 0x7FF) << 0)
+
+public:
+
+    /** SPI configuration & constructor */
+    AD7124( PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+    void frequency(int hz);
+
+    /** Low level SPI bus comm methods */
+    void reset(void);
+
+    void write_reg(uint8_t regAddress, uint8_t regValue);
+    uint16_t write_spi(uint16_t data);
+    uint16_t read_reg (uint8_t regAddress);
+    bool get_miso();
+
+
+    int32_t Reset();
+    /* Reads and returns the value of a device register. */
+    uint32_t ReadDeviceRegister(enum ad7124_registers reg);
+
+    /* Writes the specified value to a device register. */
+    int32_t WriteDeviceRegister(enum ad7124_registers reg, uint32_t value);
+
+    /*! Reads the value of the specified register. */
+    int32_t ReadRegister(ad7124_st_reg* pReg);
+
+    /*! Writes the value of the specified register. */
+    int32_t WriteRegister(ad7124_st_reg reg);
+
+    /*! Reads the value of the specified register without a device state check. */
+    int32_t NoCheckReadRegister(ad7124_st_reg* pReg);
+
+    /*! Writes the value of the specified register without a device state check. */
+    int32_t NoCheckWriteRegister(ad7124_st_reg reg);
+
+    /*! Waits until the device can accept read and write user actions. */
+    int32_t WaitForSpiReady(uint32_t timeout);
+
+    /*! Waits until a new conversion result is available. */
+    int32_t WaitForConvReady(uint32_t timeout);
+
+    /*! Reads the conversion result from the device. */
+    int32_t ReadData(int32_t* pData);
+
+    /*! Computes the CRC checksum for a data buffer. */
+    uint8_t ComputeCRC8(uint8_t* pBuf, uint8_t bufSize);
+
+    /*! Updates the device SPI interface settings. */
+    void UpdateDevSpiSettings();
+
+    /*! Initializes the AD7124. */
+    int32_t Setup();
+
+    uint8_t SPI_Read(uint8_t *data, uint8_t bytes_number);
+    uint8_t SPI_Write(uint8_t *data, uint8_t bytes_number);
+
+    DigitalIn miso;///< DigitalIn must be initialized before SPI to prevent pin MUX overwrite
+    SPI ad7124;    ///< SPI instance of the AD7790
+    DigitalOut cs; ///< DigitalOut instance for the chipselect of the AD7790
+
+private:
+
+
+    ad7124_st_reg *regs; // reg map 38 bytes ?
+    uint8_t useCRC; // boolean ?
+    int check_ready; // ?
+    int spi_rdy_poll_cnt; // timer ?
+
+    const static uint8_t _SPI_MODE = 0x03;
+    const static uint8_t _RESET = 0xFF;
+    const static uint8_t _DUMMY_BYTE = 0xFF;
+    const static uint16_t _READ_FLAG = 0x4000;
+    const static uint8_t _DELAY_TIMING = 0x02;
+
+#define AD7124_CRC8_POLYNOMIAL_REPRESENTATION 0x07 /* x8 + x2 + x + 1 */
+#define AD7124_DISABLE_CRC 0
+#define AD7124_USE_CRC 1
+#define AD7124_READ_DATA 2
+
+#define INVALID_VAL -1 /* Invalid argument */
+#define COMM_ERR    -2 /* Communication error on receive */
+#define TIMEOUT     -3 /* A timeout has occured */
+
+};
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/CN0398/CN0398.cpp	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,379 @@
+#include "CN0398.h"
+#include "AD7124.h"
+#include <mbed.h>
+
+#define RREF (5000.0)
+#define TEMP_GAIN (16.0)
+#define PT100_RESISTANCE_TO_TEMP(x) ((x-100.0)/(0.385))
+#define _2_23 (1<<23)
+
+#define CALIBRATION_NR_OF_SAMPLES (5)
+
+extern Serial pc;
+
+#define ms_delay (1)
+
+CN0398::CN0398(PinName cs, PinName adp7118enable) : ad7124(cs), ADP7118Enable(adp7118enable), offset_voltage(default_offset_voltage)
+{
+    calibration_ph[0][0] = default_calibration_ph[0][0];
+    calibration_ph[0][1] = default_calibration_ph[0][1];
+    calibration_ph[1][0] = default_calibration_ph[1][0];
+    calibration_ph[1][1] = default_calibration_ph[1][1];
+    solution0 = 0;
+    solution1 = 0;
+}
+
+void CN0398::calibrate_ph_pt0(float temperature)
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+    volt = volt / CALIBRATION_NR_OF_SAMPLES;
+    if(temperature < 0) {
+        calibration_ph[0][0] = ph_temp_lut[solution0][0];
+    } else {
+        for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) {
+            if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) {
+                calibration_ph[0][0] = ph_temp_lut[solution0][i];
+                break;
+            }
+        }
+    }
+    calibration_ph[0][1] = volt;
+    pc.printf("Calibration solution 1 ph: %f with sensor voltage of %f\r\n", calibration_ph[0][0], volt);
+}
+void CN0398::calibrate_ph_pt1(float temperature)
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+
+    volt = volt / CALIBRATION_NR_OF_SAMPLES;
+    if(temperature < 0) {
+        calibration_ph[1][0] = ph_temp_lut[solution1][0];
+    } else {
+        for(uint8_t i = 1; i < NUMBER_OF_TEMPERATURE_ENTRIES; i++) {
+            if(temperature > ph_temperatures[i - 1] && temperature <= ph_temperatures[i]) {
+                calibration_ph[1][0] = ph_temp_lut[solution1][i];
+                break;
+            }
+        }
+    }
+    calibration_ph[1][1] = volt;
+    pc.printf("Calibration solution 2 ph: %f with sensor voltage of %f\r\n", calibration_ph[1][0], volt);
+}
+
+void CN0398::calibrate_ph_offset()
+{
+    float volt = 0;
+    for(int i = 0; i < CALIBRATION_NR_OF_SAMPLES; i++) {
+        set_digital_output(P2, true);
+        int32_t data = read_channel(0);
+        set_digital_output(P2, false);
+        volt += data_to_voltage_bipolar(data >> 8, 1, 3.3);
+    }
+    offset_voltage = volt / CALIBRATION_NR_OF_SAMPLES;
+    pc.printf("Offset voltage is: %f \r\n", volt);
+}
+
+
+float CN0398::read_rtd()
+{
+    float temperature = 25.0;
+#ifdef TEMPERATURE_SENSOR_PRESENT
+    int32_t data = read_channel(2);
+    data = (data >> 8) & 0x00ffffff;
+    float resistance = ((static_cast<float>(data) - _2_23) * RREF) / (TEMP_GAIN * _2_23);
+#ifdef USE_LINEAR_TEMP_EQ
+    temperature = PT100_RESISTANCE_TO_TEMP(resistance);
+#else
+
+#define A (3.9083*pow(10,-3))
+#define B (-5.775*pow(10,-7))
+    /*if(resistance < 100.0)
+        temperature = -242.02 + 2.228 * resistance + (2.5859 * pow(10, -3)) * pow(resistance, 2) - (48260 * pow(10, -6)) * pow(resistance, 3) - (2.8183 * pow(10, -3)) * pow(resistance, 4) + (1.5243 * pow(10, -10)) * pow(resistance, 5);
+    else*/
+    temperature = ((-A + sqrt(double(pow(A, 2) - 4 * B * (1 - resistance / 100.0))) ) / (2 * B));
+#endif
+#endif
+    return temperature;
+
+}
+
+int32_t CN0398::read_channel(uint8_t ch)
+{
+    int32_t data;
+    enable_channel(ch);
+    start_single_conversion();
+
+    if (ad7124.WaitForConvReady(10000) == -3) {
+        pc.printf("TIMEOUT");
+        return -1;
+    }
+    ad7124.ReadData(&data);
+    disable_channel(ch);
+    return data;
+
+}
+float CN0398::read_ph(float temperature)
+{
+    float ph = 0;
+#ifdef PH_SENSOR_PRESENT
+    set_digital_output(P2, true);
+    int32_t data = read_channel(0);
+    set_digital_output(P2, false);
+    float volt = data_to_voltage_bipolar(data >> 8, 1, 3.3);
+#ifdef DEBUG_MODE
+    pc.printf("pH sensor voltage - %f\n", volt);
+#endif
+
+    if(use_nernst) {
+        ph  = -((volt - ZERO_POINT_TOLERANCE) / ((2.303 * AVOGADRO * (temperature + KELVIN_OFFSET)) / FARADAY_CONSTANT) ) + PH_ISO;
+    } else {
+        float m =  (calibration_ph[1][0] - calibration_ph[0][0]) / (calibration_ph[1][1] - calibration_ph[0][1]);
+        ph = m * (volt - calibration_ph[1][1] + offset_voltage) + calibration_ph[1][0];
+    }
+#endif
+    return ph;
+}
+float CN0398::read_moist()
+{
+    float moisture = 0;
+#ifdef MOISTURE_SENSOR_PRESENT
+    ADP7118Enable = true;
+    set_digital_output(P3, true);
+    wait_ms(SENSOR_SETTLING_TIME);
+    int32_t data = read_channel(1);
+    ADP7118Enable = false;
+    set_digital_output(P3, false);
+
+    data = (data >> 8) & 0x00ffffff;
+    float volt = data_to_voltage(data, 1, 3.3);
+#ifdef USE_MANUFACTURER_MOISTURE_EQ
+    if(volt <= 1.1) {
+        moisture = 10 * volt - 1;
+    } else if(volt > 1.1 && volt <= 1.3) {
+        moisture = 25 * volt - 17.5;
+    } else if(volt > 1.3 && volt <= 1.82) {
+        moisture = 48.08 * volt - 47.5;
+    } else if(volt > 1.82) {
+        moisture = 26.32 * volt - 7.89;
+    }
+#else
+    moisture = -1.18467 + 21.5371 * volt - 110.996 * (pow(volt, 2)) + 397.025 * (pow(volt, 3)) - 666.986 * (pow(volt, 4)) + 569.236 * (pow(volt, 5)) - 246.005 * (pow(volt, 6)) + 49.4867 * (pow(volt, 7)) - 3.37077 * (pow(volt, 8));
+#endif
+    if(moisture > 100) moisture = 100;
+    if(moisture < 0 ) moisture = 0;
+#endif
+    return moisture;
+}
+
+float CN0398::data_to_voltage_bipolar(uint32_t data, uint8_t gain, float VREF)
+{
+    data = data & 0xFFFFFF;
+    return ((data / static_cast<float>(0xFFFFFF / 2)) - 1) * (VREF / gain);
+}
+
+float CN0398::data_to_voltage(uint32_t data, uint8_t gain, float VREF)
+{
+    data = data & 0xFFFFFF;
+    return (data / static_cast<float>(0xFFFFFF)) * (VREF / gain);
+}
+
+void CN0398::enable_channel(int channel)
+{
+    AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue |= (uint32_t) AD7124_CH_MAP_REG_CH_ENABLE;  //Enable channel0
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+void CN0398::disable_channel(int channel)
+{
+    AD7124::ad7124_registers regNr = static_cast<AD7124::ad7124_registers> (AD7124::AD7124_Channel_0 + channel); //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= (~(uint32_t) AD7124_CH_MAP_REG_CH_ENABLE);  //Enable channel0
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+/*
+void CN0398::enable_current_source0(int current_source_channel)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH0(0xF));
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(current_source_channel);// set IOUT0 current to 500uA
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+void CN0398::enable_current_source1(int current_source_channel)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~(AD7124_IO_CTRL1_REG_IOUT_CH1(0xF));
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(current_source_channel);// set IOUT0 current to 500uA
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}*/
+
+void CN0398::set_digital_output(ad_digital_output_t p, bool state)
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_IOCon1; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    if(state)
+        setValue |= ((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p);
+    else
+        setValue &= (~((AD7124_8_IO_CTRL1_REG_GPIO_DAT1) << p));
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+
+void CN0398::start_single_conversion()
+{
+    AD7124::ad7124_registers regNr = AD7124::AD7124_ADC_Control; //Select ADC_Control register
+    uint32_t setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue &= 0xFFC3;
+    setValue |= 0x04;               //single conversion;
+    setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS;
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC*/
+    wait_ms(ms_delay * 10);
+}
+
+void CN0398::reset()
+{
+    ad7124.frequency(500000);
+    ad7124.Reset();
+    pc.printf("Reseted AD7124\r\n");
+    wait_ms(1000);
+}
+
+void CN0398::setup()
+{
+    ad7124.Setup();
+}
+
+void CN0398::init()
+{
+    uint32_t setValue;
+    enum AD7124::ad7124_registers regNr;
+
+    /* Set Config_0 0x19*/
+    regNr = AD7124::AD7124_Config_0;               //Select Config_0 register - pH
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4
+    setValue |= AD7124_CFG_REG_REF_SEL(0); //REFIN1(+)/REFIN1(−).
+    setValue |= AD7124_CFG_REG_PGA(0);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Config_0 0x1A*/
+    regNr = AD7124::AD7124_Config_1;               //Select Config_1 register - Moisture
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue &= ~AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4*/
+    setValue |= AD7124_CFG_REG_REF_SEL(0); // REFIN1(+)/REFIN1(−).
+    setValue |= AD7124_CFG_REG_PGA(0);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Config_0 0x1B*/
+    regNr = AD7124::AD7124_Config_2;               //Select Config_2 register - temp
+    setValue = 0;//ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_CFG_REG_BIPOLAR;     //Select bipolar operation
+    setValue |= AD7124_CFG_REG_BURNOUT(0);  //Burnout current source off
+    setValue |= AD7124_CFG_REG_REF_BUFP;
+    setValue |= AD7124_CFG_REG_REF_BUFM;
+    setValue |= AD7124_CFG_REG_AIN_BUFP;    //Buffer AIN5
+    setValue |= AD7124_CFG_REG_AINN_BUFM;   //Buffer AIN4
+    setValue |= AD7124_CFG_REG_REF_SEL(1); //REFIN2(+)/REFIN2(-).
+    setValue |= AD7124_CFG_REG_PGA(4); // gain 16
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set Channel_0 register 0x09*/
+    regNr = AD7124::AD7124_Channel_0;  // pH reading
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(0);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(6);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(7);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    regNr = AD7124::AD7124_Channel_1; // Moisture
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(1);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(8);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(19);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    regNr = AD7124::AD7124_Channel_2; // RTD - gain 16
+    setValue = 0;
+    setValue |= AD7124_CH_MAP_REG_SETUP(2);             // Select setup0
+    setValue |= AD7124_CH_MAP_REG_AINP(9);         // Set AIN4 as positive input
+    setValue |= AD7124_CH_MAP_REG_AINM(10);         // Set AIN5 as negative input
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);   // Write data to ADC
+
+    /* Set IO_Control_1 0x03 */
+    regNr = AD7124::AD7124_IOCon1;               //Select IO_Control_1 register
+    //setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue = 0;
+    setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL2; // enable AIN3 as digital output
+    setValue |= AD7124_8_IO_CTRL1_REG_GPIO_CTRL3; // enable AIN4 as digital output
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH0(11); // source ain11
+    setValue |= AD7124_IO_CTRL1_REG_IOUT_CH1(12); // source ain12
+    setValue |= AD7124_IO_CTRL1_REG_IOUT0(0x4);// set IOUT0 current to 500uA
+    setValue |= AD7124_IO_CTRL1_REG_IOUT1(0x4);// set IOUT0 current to 500uA*/
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC
+
+    // Set IO_Control_2
+    regNr = AD7124::AD7124_IOCon2;               //Select IO_Control_2 register
+    setValue = 0;
+    setValue |= AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7; // enable AIN3 as digital output
+    setValue &= 0xFFFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);// Write data to ADC
+
+
+    /* Set ADC_Control 0x01 */
+    regNr = AD7124::AD7124_ADC_Control;            //Select ADC_Control register
+    setValue = ad7124.ReadDeviceRegister(regNr);
+    setValue |= AD7124_ADC_CTRL_REG_DATA_STATUS; // set data status bit in order to check on which channel the conversion is
+    setValue &= 0xFFC3; // remove prev mode bits
+    setValue |= AD7124_ADC_CTRL_REG_MODE(2);
+    setValue &= 0xFFFF;
+    ad7124.WriteDeviceRegister(regNr, setValue);    // Write data to ADC
+    wait_ms(ms_delay);
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/CN0398/CN0398.h	Mon Oct 24 18:15:23 2016 +0300
@@ -0,0 +1,235 @@
+#ifndef _CN0398_H_
+#define _CN0398_H_
+#include "AD7124.h"
+
+/**
+ * @brief Calibration solutions enum
+ */
+enum {
+    ACETATE,
+    BORATE,
+    CAOH2,
+    CARBONATE,
+    CITRATE,
+    HCL,
+    OXALATE,
+    PHOSPHATE0,
+    PHOSPHATE1,
+    PHOSPHATE2,
+    PHTHALATE,
+    TARTRATE,
+    TRIS,
+    PH4,
+    PH10,
+    NUMBER_OF_SOLUTIONS
+};
+
+/**
+ * @brief Calibration solutions strings
+ */
+const char solutions[NUMBER_OF_SOLUTIONS][20] = {
+    "ACETATE",
+    "BORATE",
+    "CAOH2",
+    "CARBONATE",
+    "CITRATE",
+    "HCL",
+    "OXALATE",
+    "PHOSPHATE0",
+    "PHOSPHATE1",
+    "PHOSPHATE2",
+    "PHTHALATE",
+    "TARTRATE",
+    "TRIS",
+    "PH4",
+    "PH10"
+};
+#define NUMBER_OF_TEMPERATURE_ENTRIES 31
+
+// *INDENT-OFF*
+/**
+ * @brief Calibration temperatures
+ */
+const uint8_t ph_temperatures[NUMBER_OF_TEMPERATURE_ENTRIES] =
+{
+		0 ,		5 ,		10,		15,		18,		19,		20,		21,		22,		23,		24,		25,
+		26,		27,		28,		29,		30,		35,		37,		40,		45,		50,		55,		60,
+		65,		70,		75,		80,		85,		90,		95,
+};
+
+/**
+ * @brief Calibration solutions temperature to ph look-up tables
+ */
+const float ph_temp_lut[NUMBER_OF_SOLUTIONS][NUMBER_OF_TEMPERATURE_ENTRIES]
+{
+/* ACETATE    */ {4.667, 4.66, 4.655, 4.652, 4.651, 4.651, 4.65, 4.65, 4.65, 4.65, 4.65, 4.65, 4.65, 4.651, 4.651, 4.651, 4.652, 4.655, 4.656, 4.659, 4.666, 4.673, 4.683, 4.694, 4.706, 4.72, 4.736, 4.753, 4.772, 4.793, 4.815},
+/* BORATE     */ {9.464, 9.395, 9.332, 9.276, 9.245, 9.235, 9.225, 9.216, 9.207, 9.197, 9.189, 9.18, 9.171, 9.163, 9.155, 9.147, 9.139, 9.102, 9.088, 9.068, 9.038, 9.01, 8.985, 8.962, 8.941, 8.921, 8.902, 8.884, 8.867, 8.85, 8.833},
+/* CAOH2      */ {13.424, 13.207, 13.003, 12.81, 12.699, 12.663, 12.627, 12.592, 12.557, 12.522, 12.488, 12.454, 12.42, 12.387, 12.354, 12.322, 12.289, 12.133, 12.072, 11.984, 11.841, 11.705, 11.574, 11.449	},
+/* CARBONATE  */ {10.317, 10.245, 10.179, 10.118, 10.084, 10.073, 10.062, 10.052, 10.042, 10.032, 10.022, 10.012, 10.002, 9.993, 9.984, 9.975, 9.966, 9.925, 9.91, 9.889, 9.857, 9.828},
+/* CITRATE    */ {3.863, 3.84, 3.82, 3.803, 3.793, 3.791, 3.788, 3.785, 3.783, 3.78, 3.778, 3.776, 3.774, 3.772, 3.77, 3.768, 3.766, 3.759, 3.756, 3.754, 3.75, 3.749},
+/* HCL        */ {1.082, 1.085, 1.087, 1.089, 1.09, 1.091, 1.091, 1.092, 1.092, 1.093, 1.093, 1.094, 1.094, 1.094, 1.095, 1.095, 1.096, 1.098, 1.099, 1.101, 1.103, 1.106, 1.108, 1.111, 1.113, 1.116, 1.119, 1.121, 1.124, 1.127, 1.13},
+/* OXALATE    */ {1.666, 1.668, 1.67, 1.672, 1.674, 1.675, 1.675, 1.676, 1.677, 1.678, 1.678, 1.679, 1.68, 1.681, 1.681, 1.682, 1.683, 1.688, 1.69, 1.694, 1.7, 1.707, 1.715, 1.723, 1.732, 1.743, 1.754, 1.765, 1.778, 1.792, 1.806},
+/* PHOSPHATE0 */ {6.984, 6.951, 6.923, 6.9, 6.888, 6.884, 6.881, 6.877, 6.874, 6.871, 6.868, 6.865, 6.862, 6.86, 6.857, 6.855, 6.853, 6.844, 6.841, 6.838, 6.834, 6.833, 6.833, 6.836, 6.84, 6.845, 6.852, 6.859, 6.867, 6.876, 6.886},
+/* PHOSPHATE1 */ {7.118, 7.087, 7.059, 7.036, 7.024, 7.02, 7.016, 7.013, 7.009, 7.006, 7.003, 7, 6.997, 6.994, 6.992, 6.989, 6.987, 6.977, 6.974, 6.97, 6.965, 6.964, 6.965, 6.968, 6.974, 6.982, 6.992, 7.004, 7.018, 7.034, 7.052},
+/* PHOSPHATE2 */ {7.534, 7.5, 7.472, 7.448, 7.436, 7.432, 7.429, 7.425, 7.422, 7.419, 7.416, 7.413, 7.41, 7.407, 7.405, 7.402, 7.4, 7.389, 7.386, 7.38, 7.373, 7.367},
+/* PHTHALATE  */ {4, 3.998, 3.997, 3.998, 3.999, 4, 4.001, 4.001, 4.002, 4.003, 4.004, 4.005, 4.006, 4.007, 4.008, 4.009, 4.011, 4.018, 4.022, 4.027, 4.038, 4.05, 4.064, 4.08, 4.097, 4.116, 4.137, 4.159, 4.183, 4.208, 4.235},
+/* TARTRATE   */ {3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.557, 3.556, 3.555, 3.554, 3.553, 3.552, 3.549, 3.548, 3.547, 3.547, 3.549, 3.554, 3.56, 3.569, 3.58, 3.593, 3.61, 3.628, 3.65, 3.675},
+/* TRIS       */ {8.471, 8.303, 8.142, 7.988, 7.899, 7.869, 7.84, 7.812, 7.783, 7.755, 7.727, 7.699, 7.671, 7.644, 7.617, 7.59, 7.563, 7.433, 7.382, 7.307, 7.186, 7.07},
+/* PH4        */ {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+/* PH10       */ {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
+};
+// *INDENT-ON*
+
+#define TEMPERATURE_SENSOR_PRESENT
+#define MOISTURE_SENSOR_PRESENT
+#define PH_SENSOR_PRESENT
+
+//#define USE_LINEAR_TEMP_EQ
+//#define USE_MANUFACTURER_MOISTURE_EQ
+
+
+#define ZERO_POINT_TOLERANCE (0.003)
+#define PH_ISO (7)
+#define AVOGADRO (8.314)
+#define FARADAY_CONSTANT (96485.0)
+#define KELVIN_OFFSET (273.1)
+
+
+
+
+/**
+ * @brief the CN0398 shield class
+ */
+class CN0398
+{
+private:
+public:
+    /**
+     * @brief CN0398 constructor
+     * @param cs - CN0398 external ADC chip select pin
+     * @param swctrl0 - CN0398 ADP7118 enable pin
+     */
+    CN0398(PinName cs, PinName swctrl0);
+
+    /**
+     * @brief reads the temperature sensor
+     * @return temperature
+     */
+    float read_rtd();
+    /**
+     * @brief reads the pH sensor
+     * @param temperature(optional) - environment temperature
+     * @return reading of the pH sensor corrected with temperature(if provided)
+     */
+    float read_ph(float temperature = 25.0);
+
+    /**
+     * @brief reads the moisture sensor
+     * @return reading of the moisture sensor
+     */
+    float read_moist();
+
+    typedef enum {
+        P1 = 0,
+        P2 = 1,
+        P3 = 2,
+        P4 = 3
+    } ad_digital_output_t;
+
+    /**
+     * @brief reads the ADC channel
+     * @param ch channel to be read
+     * @return ADC reading in counts
+     */
+    int32_t read_channel(uint8_t ch);
+
+    /**
+     * @brief converts counts to voltage - unipolar conversion
+     * @param data in counts
+     * @param gain(optional) - default 1
+     * @param VREF(optional) - default 2.5 - reference voltage
+     * @return voltage
+     */
+    float data_to_voltage(uint32_t data, uint8_t gain = 1, float VREF = 2.5);
+
+    /**
+    * @brief converts counts to voltage - bipolar conversion
+    * @param data in counts
+    * @param gain(optional) - default 1
+    * @param VREF(optional) - default 2.5 - reference voltage
+    * @return voltage
+    */
+    float data_to_voltage_bipolar(uint32_t data, uint8_t gain = 1, float VREF = 2.5);
+
+    /**
+     *	@brief enables an ADC channel
+     *	@param channel - channel to be enabled
+     */
+    void enable_channel(int channel);
+    /**
+      *	@brief disables an ADC channel
+      *	@param channel - channel to be disabled
+      */
+    void disable_channel(int channel);
+
+    /**
+     * @brief performs pt 0 calibration. ph probe should be in calibration solution before calling this method
+     * @param temp - environment temperature
+     */
+    void calibrate_ph_pt0(float temperature = 25.0);
+
+    /**
+    * @brief performs pt 1 calibration. ph probe should be in calibration solution before calling this method
+    * @param temp - environment temperature
+    */
+    void calibrate_ph_pt1(float temperature = 25.0);
+
+    /**
+     * @brief performs offset calibration. pH probes should be shorted before calling this method
+     *
+     */
+    void calibrate_ph_offset();
+
+    /* void enable_current_source0(int current_source_channel);
+     void enable_current_source1(int current_source_channel);*/
+
+    /**
+     * @brief toggles the digital outputs on or off
+     * @param p - digital output
+     * @param state - state of the output
+     */
+    void set_digital_output(ad_digital_output_t p, bool state);
+
+    /**
+     * @brief triggers ADC start of single conversion
+     */
+    void start_single_conversion();
+
+    /**
+     * @brief resets the digital interface of the ADC
+     */
+    void reset();
+
+    /**
+     * @brief initializes the ADC
+     */
+    void setup();
+
+    /**
+     *  @brief configures the ADC for the CN0398 application
+     */
+    void init();
+
+    AD7124 ad7124;
+    DigitalOut ADP7118Enable;
+
+    bool use_nernst = false;
+    const float default_offset_voltage = 0;
+    const uint16_t SENSOR_SETTLING_TIME = 400; /*in ms*/
+    float offset_voltage;
+    float default_calibration_ph[2][2] = {{4, 0.169534}, {10,  -0.134135}};
+    float calibration_ph[2][2];
+    uint8_t solution0, solution1;
+
+};
+#endif