/*
 * Sport Kit Companion v1.0
 * Author: Nghia Nguyen
 */
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_adc16.h"
#include "fsl_i2c.h"
#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
//========== ADC =================================================================
#define DEMO_ADC16_BASE ADC0
#define DEMO_ADC16_CHANNEL_GROUP 0U
#define ADC_CH0 8U			//
#define ADC_CH1 9U			// Light sensor
#define ADC_CH2 15U
//#define ADC_CH3 4U
//========== I2C =================================================================
#define ACCEL_I2C_CLK_SRC I2C3_CLK_SRC
#define I2C_BAUDRATE 400000U
#define FXOS8700_WHOAMI 0xC7U
#define MMA8451_WHOAMI 0x1AU
#define ACCEL_STATUS 0x00U
#define ACCEL_XYZ_DATA_CFG 0x0EU
#define ACCEL_CTRL_REG1 0x2AU
/* FXOS8700 and MMA8451 have the same who_am_i register address. */
#define ACCEL_WHOAMI_REG 0x0DU
#define ACCEL_READ_TIMES 2
/*
 * @ ADC0 Channels (SE0-31)
 * 23: DAC0_OUT
 * 8: PTB0 - Arduino A0
 * 9: PTB1 - Arduino A1
 * 15:PTC1 - Arduino A2
 * 4b:PTC2 - Arduino A3
 * 12:PTB2
 * 13: PTB3
 *
 * @ Resolution: 12bits
 *
 */
/*******************************************************************************
 * Prototypes
 ******************************************************************************/
void delayms(uint16_t milisecs);
static bool I2C_ReadAccelWhoAmI(void);
static bool I2C_initLidar(void);
static bool I2C_WriteAccelReg(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t value);
static bool I2C_ReadAccelRegs(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize);
/*******************************************************************************
 * Variables
 ******************************************************************************/
uint16_t adc_raw;
uint16_t count=0;
uint16_t distance;
uint8_t lidar_buff[2];
/*  FXOS8700 and MMA8451 device address */
const uint8_t g_accel_address[] = {0x1CU, 0x1DU, 0x1EU, 0x1FU};
/* Lidar lite device address: 0x62 */
const uint8_t lidar_address = 0x62U;
i2c_master_handle_t g_m_handle;
uint8_t g_accel_addr_found = 0x00;
volatile bool completionFlag = false;
volatile bool nakFlag = false;
/*******************************************************************************
 * Code
 ******************************************************************************/
void delayms(uint16_t milisecs)
{
	// 8000000 ~= 1sec
	volatile uint32_t i = 0;
	for (i = 0; i < milisecs*8000; ++i)
	{
		__asm("NOP"); /* delay */
	}
}
static void i2c_master_callback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData)
{
	/* Signal transfer success when received success status. */
	if (status == kStatus_Success)
	{
		completionFlag = true;
	}
	/* Signal transfer success when received success status. */
	if (status == kStatus_I2C_Nak)
	{
		nakFlag = true;
	}
}
static bool I2C_ReadAccelWhoAmI(void)
{
	/*
    How to read the device who_am_I value ?
    Start + Device_address_Write , who_am_I_register;
    Repeart_Start + Device_address_Read , who_am_I_value.
	 */
	uint8_t who_am_i_reg = ACCEL_WHOAMI_REG;
	uint8_t who_am_i_value = 0x00;
	uint8_t accel_addr_array_size = 0x00;
	bool find_device = false;
	uint8_t i = 0;
	uint32_t sourceClock = 0;
	i2c_master_config_t masterConfig;
	/*
	 * masterConfig.baudRate_Bps = 100000U;
	 * masterConfig.enableHighDrive = false;
	 * masterConfig.enableStopHold = false;
	 * masterConfig.glitchFilterWidth = 0U;
	 * masterConfig.enableMaster = true;
	 */
	I2C_MasterGetDefaultConfig(&masterConfig);
	masterConfig.baudRate_Bps = I2C_BAUDRATE;
	sourceClock = CLOCK_GetFreq(ACCEL_I2C_CLK_SRC);
	I2C_MasterInit(BOARD_ACCEL_I2C_BASEADDR, &masterConfig, sourceClock);
	i2c_master_transfer_t masterXfer;
	memset(&masterXfer, 0, sizeof(masterXfer));
	masterXfer.slaveAddress = g_accel_address[0];
	masterXfer.direction = kI2C_Write;
	masterXfer.subaddress = 0;
	masterXfer.subaddressSize = 0;
	masterXfer.data = &who_am_i_reg;
	masterXfer.dataSize = 1;
	masterXfer.flags = kI2C_TransferNoStopFlag;
	accel_addr_array_size = sizeof(g_accel_address) / sizeof(g_accel_address[0]);
	for (i = 0; i < accel_addr_array_size; i++)
	{
		masterXfer.slaveAddress = g_accel_address[i];
		I2C_MasterTransferNonBlocking(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, &masterXfer);
		/*  wait for transfer completed. */
		while ((!nakFlag) && (!completionFlag))
		{
		}
		nakFlag = false;
		if (completionFlag == true)
		{
			completionFlag = false;
			find_device = true;
			g_accel_addr_found = masterXfer.slaveAddress;
			break;
		}
	}
	if (find_device == true)
	{
		masterXfer.direction = kI2C_Read;
		masterXfer.subaddress = 0;
		masterXfer.subaddressSize = 0;
		masterXfer.data = &who_am_i_value;
		masterXfer.dataSize = 1;
		masterXfer.flags = kI2C_TransferRepeatedStartFlag;
		I2C_MasterTransferNonBlocking(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, &masterXfer);
		/*  wait for transfer completed. */
		while ((!nakFlag) && (!completionFlag))
		{
		}
		nakFlag = false;
		if (completionFlag == true)
		{
			completionFlag = false;
			return true;
		}
		else
		{
			PRINTF("Not a successful i2c communication \r\n");
		}
	}
	return false;
}
static bool I2C_initLidar(void)
{
	uint32_t sourceClock = 0;
	i2c_master_config_t masterConfig;
	/*
	 * masterConfig.baudRate_Bps = 100000U;
	 * masterConfig.enableHighDrive = false;
	 * masterConfig.enableStopHold = false;
	 * masterConfig.glitchFilterWidth = 0U;
	 * masterConfig.enableMaster = true;
	 */
	I2C_MasterGetDefaultConfig(&masterConfig);
	masterConfig.baudRate_Bps = I2C_BAUDRATE;
	sourceClock = CLOCK_GetFreq(ACCEL_I2C_CLK_SRC);
	I2C_MasterInit(BOARD_ACCEL_I2C_BASEADDR, &masterConfig, sourceClock);
	return true;
}
static bool I2C_WriteAccelReg(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t value)
{
	i2c_master_transfer_t masterXfer;
	memset(&masterXfer, 0, sizeof(masterXfer));
	masterXfer.slaveAddress = device_addr;
	masterXfer.direction = kI2C_Write;
	masterXfer.subaddress = reg_addr;
	masterXfer.subaddressSize = 1;
	masterXfer.data = &value;
	masterXfer.dataSize = 1;
	masterXfer.flags = kI2C_TransferDefaultFlag;
	/*  direction=write : start+device_write;cmdbuff;xBuff; */
	/*  direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
	I2C_MasterTransferNonBlocking(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, &masterXfer);
	/*  wait for transfer completed. */
	while ((!nakFlag) && (!completionFlag))
	{
	}
	nakFlag = false;
	if (completionFlag == true)
	{
		completionFlag = false;
		return true;
	}
	else
	{
		return false;
	}
}
static bool I2C_ReadAccelRegs(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize)
{
	i2c_master_transfer_t masterXfer;
	memset(&masterXfer, 0, sizeof(masterXfer));
	masterXfer.slaveAddress = device_addr;
	masterXfer.direction = kI2C_Read;
	masterXfer.subaddress = reg_addr;
	masterXfer.subaddressSize = 1;
	masterXfer.data = rxBuff;
	masterXfer.dataSize = rxSize;
	masterXfer.flags = kI2C_TransferDefaultFlag;
	/*  direction=write : start+device_write;cmdbuff;xBuff; */
	/*  direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */
	I2C_MasterTransferNonBlocking(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, &masterXfer);
	/*  wait for transfer completed. */
	while ((!nakFlag) && (!completionFlag))
	{
	}
	nakFlag = false;
	if (completionFlag == true)
	{
		completionFlag = false;
		return true;
	}
	else
	{
		return false;
	}
}
/*!
 * @brief Main function
 */
int main(void)
{
	adc16_config_t adc16ConfigStruct;
	adc16_channel_config_t adc16ChannelConfigStruct;
	bool isThereAccel = false;
	BOARD_InitPins();
	BOARD_BootClockRUN();
	BOARD_InitDebugConsole();
	PRINTF("\r\nFreedom Sport Companion Demonstration:\r\n");
	PRINTF("- Read sound sensor to detect motion\r\n");
	PRINTF("- Use Lidar Lite to measure distance\r\n");
	PRINTF("- Monitor Heartbeat \r\n");
	/*
	 * adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
	 * adc16ConfigStruct.clockSource = kADC16_ClockSourceAsynchronousClock;
	 * adc16ConfigStruct.enableAsynchronousClock = true;
	 * adc16ConfigStruct.clockDivider = kADC16_ClockDivider8;
	 * adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit;
	 * adc16ConfigStruct.longSampleMode = kADC16_LongSampleDisabled;
	 * adc16ConfigStruct.enableHighSpeed = false;
	 * adc16ConfigStruct.enableLowPower = false;
	 * adc16ConfigStruct.enableContinuousConversion = false;
	 */
	ADC16_GetDefaultConfig(&adc16ConfigStruct);
	ADC16_Init(DEMO_ADC16_BASE, &adc16ConfigStruct);
	ADC16_EnableHardwareTrigger(DEMO_ADC16_BASE, false); /* Make sure the software trigger is used. */
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
	if (kStatus_Success == ADC16_DoAutoCalibration(DEMO_ADC16_BASE))
	{
		PRINTF("ADC16_DoAutoCalibration() Done.\r\n");
	}
	else
	{
		PRINTF("ADC16_DoAutoCalibration() Failed.\r\n");
	}
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
	PRINTF("Press any key to get user channel's ADC value ...\r\n");
	adc16ChannelConfigStruct.channelNumber = ADC_CH0;
	adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = false;
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
	adc16ChannelConfigStruct.enableDifferentialConversion = false;
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
	GETCHAR();
	while (1)
	{
		I2C_MasterTransferCreateHandle(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, i2c_master_callback, NULL);
		isThereAccel = I2C_ReadAccelWhoAmI();
		/*  read the accel xyz value if there is accel device on board */
		if (true == isThereAccel)
		{
			uint8_t databyte = 0;
			uint8_t write_reg = 0;
			uint8_t readBuff[7];
			int16_t x, y, z;
			uint8_t status0_value = 0;
			uint32_t i = 0U;
			/*  please refer to the "example FXOS8700CQ Driver Code" in FXOS8700 datasheet. */
			/*  write 0000 0000 = 0x00 to accelerometer control register 1 */
			/*  standby */
			/*  [7-1] = 0000 000 */
			/*  [0]: active=0 */
			write_reg = ACCEL_CTRL_REG1;
			databyte = 0;
			I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, g_accel_addr_found, write_reg, databyte);
			/*  write 0000 0001= 0x01 to XYZ_DATA_CFG register */
			/*  [7]: reserved */
			/*  [6]: reserved */
			/*  [5]: reserved */
			/*  [4]: hpf_out=0 */
			/*  [3]: reserved */
			/*  [2]: reserved */
			/*  [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB */
			/*  databyte = 0x01; */
			write_reg = ACCEL_XYZ_DATA_CFG;
			databyte = 0x01;
			I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, g_accel_addr_found, write_reg, databyte);
			/*  write 0000 1101 = 0x0D to accelerometer control register 1 */
			/*  [7-6]: aslp_rate=00 */
			/*  [5-3]: dr=001 for 200Hz data rate (when in hybrid mode) */
			/*  [2]: lnoise=1 for low noise mode */
			/*  [1]: f_read=0 for normal 16 bit reads */
			/*  [0]: active=1 to take the part out of standby and enable sampling */
			/*   databyte = 0x0D; */
			write_reg = ACCEL_CTRL_REG1;
			databyte = 0x0d;
			I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, g_accel_addr_found, write_reg, databyte);
			for (i = 0; i < ACCEL_READ_TIMES; i++)
			{
				status0_value = 0;
				/*  wait for new data are ready. */
				while (status0_value != 0xff)
				{
					I2C_ReadAccelRegs(BOARD_ACCEL_I2C_BASEADDR, g_accel_addr_found, ACCEL_STATUS, &status0_value, 1);
				}
				/*  Multiple-byte Read from STATUS (0x00) register */
				I2C_ReadAccelRegs(BOARD_ACCEL_I2C_BASEADDR, g_accel_addr_found, ACCEL_STATUS, readBuff, 7);
				status0_value = readBuff[0];
				x = ((int16_t)(((readBuff[1] * 256U) | readBuff[2]))) / 4U;
				y = ((int16_t)(((readBuff[3] * 256U) | readBuff[4]))) / 4U;
				z = ((int16_t)(((readBuff[5] * 256U) | readBuff[6]))) / 4U;
				PRINTF("I2C: x = %5d , y = %5d , z = %5d \r\n", x, y, z);
			}
		}
		/*
		 * read Lidar lite
		 */
		I2C_initLidar();
		//		I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x00, 0x04);
		I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x45, 0xC8);	//10Hz
		I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x04, 0x21);
		I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x11, 0xFF); //continuos
		I2C_WriteAccelReg(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x00, 0x04);	//start
		delayms(500);
		/*  Multiple-byte Read from distance register */
		I2C_ReadAccelRegs(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x8f, lidar_buff, 2);
		//		I2C_ReadAccelRegs(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x0f, &lidar_buff[0], 1);
		//		I2C_ReadAccelRegs(BOARD_ACCEL_I2C_BASEADDR, lidar_address, 0x10, &lidar_buff[1], 1);
		distance = (lidar_buff[0] << 8) + lidar_buff[1];
		PRINTF("distance: %4d \r\n",lidar_buff[0],lidar_buff[1],distance);
		/*
             When in software trigger mode, each conversion would be launched once calling the "ADC16_ChannelConfigure()"
             function, which works like writing a conversion command and executing it. For another channel's conversion,
             just to change the "channelNumber" field in channel's configuration structure, and call the
             "ADC16_ChannelConfigure() again.
		 */
		/*
		 * Get ADC value and print counter in console
		 */
		// CH0: potentiometer
		adc16ChannelConfigStruct.channelNumber = ADC_CH0;
		ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
		while (0U == (kADC16_ChannelConversionDoneFlag &
				ADC16_GetChannelStatusFlags(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP)))
		{}
		adc_raw = ADC16_GetChannelConversionValue(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP);
		if(adc_raw > 40000){
			count++;
			PRINTF("Counter: %d\r\n",count);
			delayms(200);
			// Clear counter
			if(count == 20)
				count=0;
		}
		else{
			PRINTF("ADCval0: %4d   ",adc_raw);
		}
		// CH1: sound sensor
		adc16ChannelConfigStruct.channelNumber = ADC_CH1;
		ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
		while (0U == (kADC16_ChannelConversionDoneFlag &
				ADC16_GetChannelStatusFlags(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP)))
		{}
		adc_raw = ADC16_GetChannelConversionValue(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP);
		PRINTF("ADCval1: %4d   ",adc_raw);
		// CH2: light sensor
		adc16ChannelConfigStruct.channelNumber = ADC_CH2;
		ADC16_SetChannelConfig(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
		while (0U == (kADC16_ChannelConversionDoneFlag &
				ADC16_GetChannelStatusFlags(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP)))
		{}
		adc_raw = ADC16_GetChannelConversionValue(DEMO_ADC16_BASE, DEMO_ADC16_CHANNEL_GROUP);
		PRINTF("ADCval2: %4d\r\n",adc_raw);
		delayms(50);
	}
}
Comments
Please log in or sign up to comment.