Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all
Revision 30:990ce210e8c2, committed 2016-10-24
- 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
--- /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(®s[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(®s[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(®s[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 = ®s[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
CN0357 - Toxic gas measurement
CN0216 - Weight Scale