How to detect if the bus is free/released by slave using HAL I2C BitCloud API functions?

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have huge difficulties setting up a proper I2C master-driven connection to a slave BNO055 sensor. I have tried using the plain registers as suggested in many previous posts but to no avail and the debugging the application was quite awful. 

Anyway, my application has many states in the TaskHandler (as switch cases) and almost all have some read/write function calls to BNO055 sensor. I have managed to get the connection working by separating every read/write in their separate states. However, since I want to minimize the number of states and make the code less gibberish and clearer I would like to combine the logically same application states.
The HAL open, read/write and close functions are located in readBno055 and writeBno055. When trying to combine two calls of these functions in the same application state, there isn't enough time for the I2C packet to be closed by the callback function before the second call for (example) writeBno055 fails. I suppose delaying the application to wait for this callback by using _delay_ms is not good. My question is, is it even possible to have multiple read/write operations in the same switch case of the TaskHandler? The developer guide for BitCloud 3.3.0 regarding these HAL I2C function is a bit misleading and on the sequence diagram it even has an error. Below my code of app.c: 

 

/**************************************************************************//**
  \file app.c
  \brief App that reads sensor values of BNO055 9-axis sensor.
  \author tozamimoza
******************************************************************************/


#include <appTimer.h>
#include <zdo.h>
#include <app.h>
#include <sysTaskManager.h>
#include <usartManager.h>
#include <i2cPacket.h>
#include <bspLeds.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>

bool debugMode; 
bool isPacketClosed=false; 
bool avoidReset=false; 
bool isReadingQuat= false; 
static AppState_t appstate = APP_INIT;
// timers 
static HAL_AppTimer_t initDelayTimer; 
static HAL_AppTimer_t quaterTimer;
static HAL_AppTimer_t resetDelayTimer; 
static HAL_AppTimer_t calibTimer; 
static HAL_AppTimer_t eulerTimer; 
// timer initializations 

static void initQuaterTimer(void);
static void initInitDelayTimer(void);
static void initResetDelayTimer(void); 
static void initCalibTimer(void); 
static void initEulerTimer(void);

// timer callbacks
static void	quaterTimerFired(void);
static void initDelayTimerFired(void);
static void resetDelayTimerFired(void);
static void calibTimerFired(void); 
static void eulerTimerFired(void); 

void printLineToUSART(char*);
void printTextToUSART(uint8_t*);
// help function for concatenating strings (used in printToUSART functions)
char* concat(const char *s1, const char *s2);


uint8_t readQuatCtr=0; 

uint8_t readOneByteData[1];
uint8_t writeTwoBytesData[2];
uint8_t writeOneByteData[1];
uint8_t readData[1]={0x00};
uint8_t readDataQ[8];
uint8_t readDataC[1]={0x00};
uint8_t readEightBytesData[8];
uint8_t readEuelerData[6]; 

uint8_t output[] = "0xXX";
uint8_t outputStr[] = "XXX";

int16_t quat_w, quat_x, quat_y, quat_z;

uint8_t tempZ[] = "000000"; 
uint8_t tempY[] = "000000"; 
uint8_t tempX[] = "000000"; 
uint8_t tempW[] = "000000"; 

const double scale = (1.0 / (1<<14));

static void writeDone(bool result);
static void readDone(bool result);
static inline bool checkIfPacketIsClosed(void); 

static HAL_I2cDescriptor_t i2cdescriptor={
	
	.tty = TWI_CHANNEL_0,
	.clockRate = I2C_CLOCK_RATE_125,
	.id = BNO055_I2C_ADDRESS,
	
};

/**
 * \brief Method for writing values to a BNO055 register. It should be also used for selecting registers for read.
 * 
 * \param numOfBytes number of bytes to write. If 1, last argument of this function can be set to an arbitrary value and will not be used.
 * \param regAddr register address 
 * \param val value to write
 * 
 * \return int control value for success/fail. -1 is fail of opening/writing an I2C packet, -2 is for invalid numOfBytes argument
 */
int writeBno055(uint8_t numOfBytes, uint8_t regAddr, uint8_t val){
	if(-1 == HAL_OpenI2cPacket(&i2cdescriptor)){
		printLineToUSART(ERROR_I2C_OPEN);
		printLineToUSART("Error in writeBno055!");
		
		appstate=APP_NOTHING;
		SYS_PostTask(APL_TASK_ID);
		return -1;
	}else{
		// set isPacketClosed to false since it's open
		isPacketClosed=false;
	}
	
	if (numOfBytes==1)
	{
		writeOneByteData[0]=regAddr;
		i2cdescriptor.f = writeDone;
		i2cdescriptor.data = writeOneByteData;
		i2cdescriptor.length = 1;
		
	}else if(numOfBytes==2){
		
		writeTwoBytesData[0]= regAddr;
		writeTwoBytesData[1]= val;
		i2cdescriptor.f = writeDone;
		i2cdescriptor.data = writeTwoBytesData;
		i2cdescriptor.length = 2;
		
	}else{
		// invalid numOfBytes argument
		return -2;
	}
	
	if(-1 == HAL_WriteI2cPacket(&i2cdescriptor)){
		printLineToUSART(ERROR_I2C_WRITE);
		printLineToUSART(" IN WRITE FUNCTION FOR BNO055!"); 
		appstate = APP_NOTHING; 
		SYS_PostTask(APL_TASK_ID);
		
		return -1;
	}
	// the packet is closed in the callback function writeDone
	return 0; 
}

/**
 * \brief Reads values from already selected register (with previous write function). 
 * 
 * \param numOfBytes specifies how much bytes of data are to be read starting from the previously selected register address.
 * \param readData pointer to an array for read data to be stored.
 * 
 * \return int control integer
 */
int readBno055(uint8_t numOfBytes, uint8_t* readData){
	// ------------------------------------------------ READ --------------------------------------------------------
	
	if(-1 == HAL_OpenI2cPacket(&i2cdescriptor)){
		
		printLineToUSART(ERROR_I2C_OPEN);
		
		printLineToUSART("Error in readBno055!");
		return -1;
	}else{
		// set isPacketClosed to false since it's open
		isPacketClosed=false;
	}
	
	i2cdescriptor.f = readDone;
	i2cdescriptor.data = readData;
	i2cdescriptor.length = numOfBytes;
	
	
	if(-1 == HAL_ReadI2cPacket(&i2cdescriptor)){
		
		printLineToUSART(ERROR_I2C_READ);
		
		printLineToUSART("Error in readBno055!");
		appstate = APP_NOTHING;
		SYS_PostTask(APL_TASK_ID); 
		return -1;
	}
	return 0; 
	
}

/**
 * \brief Prints a line to UART interface in the same way as appWriteDataToUsart function but more convenient. 
 * 
 * \param text text to be printed 
 * 
 * \return void
 */
void printLineToUSART(char* text){
	 
	const char suffix[]="\n\r"; 
	char* result=concat(text, suffix);
	
	uint8_t* uintArr = (uint8_t*)result; 
	uint8_t len = strlen(uintArr); 
	
	appWriteDataToUsart(uintArr,len);
	
	free(result); 
	
}
/**
 * \brief Prints text to UART interface in the same way as appWriteDataToUsart function but more convenient. 
 * 
 * \param text text to be printed 
 * 
 * \return void
 */
void printTextToUSART(uint8_t* text){
	
	
	uint8_t len = strlen(text); 
	
	appWriteDataToUsart(text,len);
}

/**
 * \brief Function for concatenating two strings. 
 * 
 * \param s1 argument 1 to be concatenated 
 * \param s2 argument 2 to be concatenated 
 * 
 * \return char* concatenated string result. 
 */
char* concat(const char *s1, const char *s2)
{
	char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
	// in real code you would check for errors in malloc here
	strcpy(result, s1);
	strcat(result, s2);
	return result;
}

void APL_TaskHandler(void){
	switch(appstate){
		case APP_INIT:
			
			debugMode=true; 
			avoidReset=true; 
			isReadingQuat=false; 
			appInitUsartManager();
			
			if(debugMode){
				printLineToUSART("---------------------------");
				printLineToUSART("STATE: APP_INIT");
			}
			
			//appWriteDataToUsart((uint8_t*)"STATE_APP_INIT\n\r",sizeof("STATE_APP_INIT\n\r")-1);
			//Timer init 
			initQuaterTimer();
			initInitDelayTimer(); 
			initResetDelayTimer();
			initCalibTimer();
			initEulerTimer(); 
			
			appstate = APP_READ_BATTERY; 
			SYS_PostTask(APL_TASK_ID); 
			
			break;
		case APP_READ_BATTERY:
			
			
			appstate = APP_RESET_BNO055;
			SYS_PostTask(APL_TASK_ID);
		break;
				
		case APP_NOTHING : 
			if(debugMode){
				printLineToUSART("----------------------------");
				printLineToUSART("STATE: APP_NOTHING"); 	
			}
			break;
			
			
		case APP_RESET_BNO055: 
		
			if(!avoidReset){
			
				if(debugMode){
					printLineToUSART("---------------------------------");
					printLineToUSART("STATE: APP_RESET_BNO055");
				}
				if(-1==writeBno055(2, SYS_TRIGGER_ADDRESS, RST_SYS)){
					printLineToUSART(ERROR_SET_SYS_RESET);
					appstate=APP_SET_OP_MODE_NDOF;
					SYS_PostTask(APL_TASK_ID);
				}
		
				HAL_StartAppTimer(&resetDelayTimer); 
				appstate=APP_NOTHING; 
				SYS_PostTask(APL_TASK_ID); 
			}
			else{
				if(debugMode){ 
					printLineToUSART("---------------------------------");
					printLineToUSART("STATE: APP_RESET_BNO055");
					printLineToUSART("Reset AVOIDED!"); 
					
					
				}
				
				appstate=APP_SET_ID_REG;
				SYS_PostTask(APL_TASK_ID);
			}
		break; 	
		case APP_SET_ID_REG: 
			if (debugMode)
			{
				printLineToUSART("---------------------------------");
				printLineToUSART("STATE: APP_SET_ID_REG");
			}
			if(-1 == writeBno055(1, BNO055_ID_REG, 0x00)){
				printLineToUSART(ERROR_I2C_WRITE);
			}
			
			appstate=APP_READ_ID_REG;
			SYS_PostTask(APL_TASK_ID);
		break; 
		case APP_READ_ID_REG:
		if (debugMode)
		{
			printLineToUSART("---------------------------------");
			printLineToUSART("STATE: APP_SET_ID_REG");
		}
		readBno055(1, readOneByteData);
			
		if (readOneByteData!=BNO055_ID)
		{
			printLineToUSART("Not the same ID!");
		}
		
		
		appstate=APP_SET_OP_MODE_CONFIG;
		SYS_PostTask(APL_TASK_ID);
		break;
		//NDOF MODE Siehe Datenblatt
		case APP_SET_OP_MODE_NDOF:
			
			if(debugMode){
				printLineToUSART("---------------------------------");
				printLineToUSART("STATE: APP_SET_OP_MODE_NDOF");
			}
			
			//appWriteDataToUsart((uint8_t*)"STATE_APP_SET_NDOF\n\r",sizeof("STATE_APP_SET_NDOF\n\r")-1);
			
			if(-1 == writeBno055(2, OPR_MODE_ADDRESS, BNO055_OPERATION_MODE_NDOF)){
				printLineToUSART(ERROR_I2C_WRITE);
				printLineToUSART(" It is caused in APP_SET_OP_MODE_NDOF.");
				appstate=APP_SET_OP_MODE_NDOF;
				SYS_PostTask(APL_TASK_ID);
			}
			
			appstate = APP_SET_CALIBRATION_REG;
			SYS_PostTask(APL_TASK_ID);
			
			break;	
			
		case APP_SET_OP_MODE_CONFIG:
			if(debugMode){
				printLineToUSART("---------------------------------");
				printLineToUSART("STATE: APP_SET_OP_MODE_CONFIG");
			}
			
			if(-1==writeBno055(2, OPR_MODE_ADDRESS, BNO055_OPERATION_MODE_CONFIG)){
				printLineToUSART(ERROR_SET_MODE_CONF); printLineToUSART("Caused in OP MODE CONFIG!");
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}
			appstate=APP_SET_PAGEID;
			SYS_PostTask(APL_TASK_ID);
			break;
			/* This is done automatically at start-up!
		case APP_SET_POWER_MODE_NORMAL:
			if(debugMode){
				printLineToUSART("---------------------------------");
				printLineToUSART("STATE: APP_SET_POWER_MODE_NORMAL");
			}
			if(-1 == writeBno055(2, BNO055_PWR_MODE_REG, PWR_MODE_NORMAL)){
				printLineToUSART(ERROR_SET_PWR_NORMAL);
			}
			
			appstate = APP_SET_PAGEID;
			SYS_PostTask(APL_TASK_ID);
			
			break;
			*/
		//Page ID wird auf 0 gesetzt um den Sensor zu nutzen
		case APP_SET_PAGEID:
			if(debugMode){
				printLineToUSART("---------------------------");
				printLineToUSART("STATE: APP_SET_PAGEID");
			}
			
			if(-1 == writeBno055(2, PAGE_ID_ADDRESS, PAGE0)){
				printLineToUSART(ERROR_I2C_WRITE); 
				appstate=APP_NOTHING; 
				SYS_PostTask(APL_TASK_ID); 
			}
			
			appstate = APP_SET_SYS_TRIGGER_REG;
			SYS_PostTask(APL_TASK_ID); 
			break;
		// SYS_TRIGGER auf CLK_SEL	
		case APP_SET_SYS_TRIGGER_REG:
			if(debugMode){
				printLineToUSART("-------------------------------------");
				printLineToUSART("STATE: APP_SET_SYS_TRIGGER_REG");
			}
			
			if(-1 == writeBno055(2, SYS_TRIGGER_ADDRESS, CLK_SEL)){
				printLineToUSART(ERROR_SEL_REG_SYS_TRIGGER);
				printLineToUSART("IN SET SYS TRIGGER REG STATE!");
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}
			
			appstate = APP_SET_OP_MODE_NDOF;
			SYS_PostTask(APL_TASK_ID);
			break;	
			
		
		
	
		//Register für kalibrierung laden	
		case APP_SET_CALIBRATION_REG:
			
			if(debugMode){
				printLineToUSART("------------------------------");
				printLineToUSART("STATE: APP_SET_CALIBRATION_REG");
			}
			
			// select calibration register
			if(-1 == writeBno055(1, CALIB_STAT_ADDR, 0x00)){
				printLineToUSART(ERROR_SEL_REG_CAL);
				printLineToUSART("Caused in SET CALIB REG!");
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}
			appstate = APP_READ_CALIBRATION_REG;
			SYS_PostTask(APL_TASK_ID);
			break;
			
		//kalibrierung aUSLESEN UND IN READDATAC SPEICHERN	
		case APP_READ_CALIBRATION_REG:	
			if (debugMode){
				printLineToUSART("--------------------------------");
				printLineToUSART("STATE: APP_READ_CALIBRATION_REG");
			}
				
			if (-1==readBno055(1, readDataC))
			{
				printLineToUSART(ERROR_I2C_READ);
				printLineToUSART("Caused by READ CALIB REG STATE!");
				HAL_StartAppTimer(&calibTimer);
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}else{
				if(readDataC[0]!=0xFF){
					printLineToUSART("Not ready yet. Calibrating...");
					printTextToUSART("Value: "); 
					
					uint8_to_hexstr(output,sizeof(output),readDataC[0],2);
					printTextToUSART(output);
					printTextToUSART(" ");
					
					uint32_to_str(outputStr,sizeof(outputStr),readDataC[0],0,3);
					printTextToUSART(outputStr);
					printLineToUSART(" ");
					
					HAL_StartAppTimer(&calibTimer);
					appstate = APP_NOTHING; 
					SYS_PostTask(APL_TASK_ID);
				}
				// calibrated, proceed
				else{
				
					if (isReadingQuat)
					{
						appstate = APP_SET_QUATERNION_REG;
					}else{
						appstate = APP_SET_EULER_REG; 					
					}
					
					SYS_PostTask(APL_TASK_ID);
				}
				 
			}
			
			/*
			if(-1 == HAL_OpenI2cPacket(&i2cdescriptor)){
				
				appWriteDataToUsart((uint8_t*)"APP_READ_CALIBRATION_REG Fail\r\n",sizeof("APP_READ_CALIBRATION_REG")-1);
			}
			
			//appWriteDataToUsart((uint8_t*)"APP_READ_CALIBRATION_REG\n\r",sizeof("APP_READ_CALIBRATION_REG\n\r")-1);
			i2cdescriptor.f = readDone;
			i2cdescriptor.data = readDataC;
			i2cdescriptor.length = 1;
			
			
			if(-1 == HAL_ReadI2cPacket(&i2cdescriptor)){
				
				appWriteDataToUsart((uint8_t*)"Read Fail\r\n",sizeof("Read Fail\r\n")-1);
			}
			*/
			break;
		case APP_SET_EULER_REG:
			if(debugMode){ 
				printLineToUSART("------------------------------");
				printLineToUSART("STATE: APP_SET_EULER_REG"); 
			}
		
			if(-1 == writeBno055(1, EUL_HEADING_LSB, 0x00)){
				printLineToUSART(ERROR_SEL_REG_EULER);
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}	
			
			appstate = APP_READ_EULER;
			SYS_PostTask(APL_TASK_ID);
			
			break;
		//Register W für die Quaterionen laden
		case APP_SET_QUATERNION_REG:
			if(debugMode){ 
				printLineToUSART("------------------------------");
				printLineToUSART("STATE: APP_SET_QUAT_REG"); 
			}
		
			if(-1 == writeBno055(1, QUATERNION_DATA_W_LSB_ADDR, 0x00)){
				printLineToUSART(ERROR_SEL_REG_QUA);
				appstate=APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);
			}	
			HAL_StartAppTimer(&quaterTimer);
			appstate=APP_NOTHING; 
			SYS_PostTask(APL_TASK_ID); 
			
			break;
		case APP_READ_EULER:
			
			if(debugMode){
				printLineToUSART("--------------------------------");
				printLineToUSART("STATE: APP_READ_EULER");
			}
			
			readBno055(6, readEuelerData);
			//printLineToUSART("is READ");
			
			// display read results 
			
			{
				char buffer[30]; 
				uint16_t heading = readEuelerData[0] << 8 | readEuelerData[1]; 
				uint16_t roll = readEuelerData[2] << 8 | readEuelerData[3];
				uint16_t pitch = readEuelerData[4] << 8 | readEuelerData[5]; 
				
				printTextToUSART(itoa(heading,buffer,10));
				printTextToUSART(" / "); 
				printTextToUSART(itoa(roll,buffer,10));
				printTextToUSART(" / ");
				printLineToUSART(itoa(pitch,buffer,10));
				
			}
			
			HAL_StartAppTimer(&eulerTimer);
			appstate = APP_NOTHING;
			SYS_PostTask(APL_TASK_ID);
			
		break;
			
			
		//Quaterionen auslesen	W,X,Y,Z wegen length 8 direkt die andeeren Register von X,Y,Z mitauslesen 
		case APP_READ_QUATERNION:
			
			if(debugMode){
				printLineToUSART("--------------------------------");
				printLineToUSART("STATE: APP_READ_QUATERNION");
			}
			
			
			readBno055(8, readDataQ); 
			//printLineToUSART("is READ"); 
			
			appstate = APP_STORE_QUATERNION;
			SYS_PostTask(APL_TASK_ID);
			
			break;
		
			
		case APP_STORE_QUATERNION:
			
			if(debugMode){
				printLineToUSART("--------------------------------");
				printLineToUSART("STATE: APP_STORE_QUATERNION");
			}
			
			quat_w = (((uint16_t)readDataQ[1]) << 8) | ((uint16_t)readDataQ[0]);
			quat_w = scale * quat_w;
			
			quat_x = (((uint16_t)readDataQ[3]) << 8) | ((uint16_t)readDataQ[2]);
			quat_x = scale * quat_x;
			
			quat_y = (((uint16_t)readDataQ[5]) << 8) | ((uint16_t)readDataQ[4]);
			quat_y = scale * quat_y;
			
			quat_z = (((uint16_t)readDataQ[7]) << 8) | ((uint16_t)readDataQ[6]);
			quat_z = scale * quat_z;
			/*
			//wenn nicht fertig kalibriert
			if(readDataC[0] != 0xFF){
				
				//printTextToUSART("Calibration reg val: "); 
				
				uint8_to_hexstr(output,sizeof(output),readDataC[0],2);
				printTextToUSART(output); 
				printTextToUSART(" ");
				
				uint32_to_str(outputStr,sizeof(outputStr),readDataC[0],0,3);
				printTextToUSART(outputStr); 
				printLineToUSART(" "); 
				
				//HAL_StartAppTimer(&calibTimer); 
				_delay_ms(100); 
				appstate = APP_SET_CALIBRATION_REG;
				SYS_PostTask(APL_TASK_ID); 
			}
			*/
			//wenn fertig kalibriert
			//else{
				{
				char* buffer[4]; 
				
				
			
				//printLineToUSART((char*)readDataQ); 
				int32_to_str(tempW,sizeof(tempW), quat_w, 0, 6);
				
				//printTextToUSART(tempW);
				printTextToUSART(itoa(quat_w, buffer, 10));
				printTextToUSART(" ");
				
				int32_to_str(tempX,sizeof(tempX), quat_x, 0, 6);
				
				printTextToUSART(itoa(quat_x, buffer, 10)); 
				printTextToUSART(" ");
				
				int32_to_str(tempY,sizeof(tempY), quat_y, 0, 6);
				 
				printTextToUSART(tempY); 
				printTextToUSART(" ");
				//appWriteDataToUsart(tempY,sizeof(tempY));
				
				int32_to_str(tempZ,sizeof(tempZ), quat_z, 0, 6);
				//appWriteDataToUsart(tempZ,sizeof(tempZ));
				printTextToUSART(tempZ);
				printLineToUSART(" ");
				
				//appWriteDataToUsart((uint8_t*)"else\n\r",sizeof("else\n\r")-1);
				 
				
				HAL_StartAppTimer(&quaterTimer);
				
				appstate = APP_NOTHING;
				SYS_PostTask(APL_TASK_ID);	
				}
			//}
			
			break;
			
		
	}
	
}

// TIMER INITIALIZATION FUNCTIONS
static void initInitDelayTimer(void)
{
	initDelayTimer.interval = INIT_DELAY; 
	initDelayTimer.mode = TIMER_ONE_SHOT_MODE;
	initDelayTimer.callback = initDelayTimerFired;
}

static void initResetDelayTimer(void){
	resetDelayTimer.interval = RESET_DELAY;
	resetDelayTimer.mode = TIMER_ONE_SHOT_MODE;
	resetDelayTimer.callback = resetDelayTimerFired;
}
static void initCalibTimer(void){
	calibTimer.interval=CALIB_READ_INTERVAL; 
	calibTimer.mode = TIMER_ONE_SHOT_MODE;
	calibTimer.callback = calibTimerFired;
}

static void initQuaterTimer(void){
	quaterTimer.interval = QUAT_READ_INTERVAL; // Timer interval
	quaterTimer.mode = TIMER_ONE_SHOT_MODE; // Timer-Mode
	quaterTimer.callback = quaterTimerFired; // Callback function
	
}
static void initEulerTimer(void){
	eulerTimer.interval = EULER_READ_INTERVAL; // Timer interval
	eulerTimer.mode = TIMER_ONE_SHOT_MODE; // Timer-Mode
	eulerTimer.callback = eulerTimerFired; // Callback function
	
}
// TIMER CALLBACKS
void calibTimerFired(void){
	appstate = APP_READ_CALIBRATION_REG;
	SYS_PostTask(APL_TASK_ID);
}
void resetDelayTimerFired(void){
	
	appstate = APP_SET_OP_MODE_CONFIG;
	SYS_PostTask(APL_TASK_ID);
}
void initDelayTimerFired(void){
	appstate = APP_SET_PAGEID; 
	SYS_PostTask(APL_TASK_ID);
}




/**
 * \brief Timer callback function for the timer representing an interval between quaternion reads. 
 Application state is changed to read state for quaternions. 
 * 
 * 
 * \return void
 */
static void	quaterTimerFired(){
	
	appstate = APP_READ_QUATERNION;
	SYS_PostTask(APL_TASK_ID);
}

static void	eulerTimerFired(){
	
	appstate = APP_READ_EULER;
	SYS_PostTask(APL_TASK_ID);
}
static inline bool checkIfPacketIsClosed(void){
		return isPacketClosed; 
}

/**
 * \brief Callback function for I2C descriptor (write). 
 * 
 * \param result a boolean indicating a successful/unsuccessful write operation
 * 
 * \return void
 */
static void writeDone(bool result){
	if(result == false){
		printLineToUSART(ERROR_I2C_WRITE);
		appstate = APP_NOTHING;
	}else{
		// succesful write, now close the packet
		if(-1 == HAL_CloseI2cPacket(&i2cdescriptor)){
			printLineToUSART(ERROR_I2C_CLOSE); 
			appstate = APP_NOTHING;
		}else{
			// set isPacketClosed to true
			isPacketClosed=true;
		}	
	}
	SYS_PostTask(APL_TASK_ID);
}

/**
 * \brief Callback function for I2C descriptor (read). 
 * 
 * \param result a boolean indicating a successful/unsuccessful read operation
 * 
 * \return void
 */
static void readDone(bool result){
	if(result == false){
		printLineToUSART(ERROR_I2C_READ);
		appstate = APP_NOTHING;
	}else{
		// succesful read, now close the packet
		if(-1 == HAL_CloseI2cPacket(&i2cdescriptor)){
			
			printLineToUSART(ERROR_I2C_CLOSE);
			appstate = APP_NOTHING;
		}else{
			// set isPacketClosed to true
			isPacketClosed=true;
		}
	}
	SYS_PostTask(APL_TASK_ID);
}


/*******************************************************************************
  \brief The function is called by the stack to notify the application about 
  various network-related events. See detailed description in API Reference.
  
  Mandatory function: must be present in any application.
  \param[in] nwkParams - contains notification type and additional data varying
             an event
  \return none
*******************************************************************************/
void ZDO_MgmtNwkUpdateNotf(ZDO_MgmtNwkUpdateNotf_t *nwkParams)
{
  nwkParams = nwkParams;  // Unused parameter warning prevention
}

/*******************************************************************************
  \brief The function is called by the stack when the node wakes up by timer.
  
  When the device starts after hardware reset the stack posts an application
  task (via SYS_PostTask()) once, giving control to the application, while
  upon wake up the stack only calls this indication function. So, to provide 
  control to the application on wake up, change the application state and post
  an application task via SYS_PostTask(APL_TASK_ID) from this function.
  Mandatory function: must be present in any application.
  
  \return none
*******************************************************************************/
void ZDO_WakeUpInd(void)
{
}

#ifdef _BINDING_
/***********************************************************************************
  \brief The function is called by the stack to notify the application that a 
  binding request has been received from a remote node.
  
  Mandatory function: must be present in any application.
  \param[in] bindInd - information about the bound device
  \return none
 ***********************************************************************************/
void ZDO_BindIndication(ZDO_BindInd_t *bindInd)
{
  (void)bindInd;
}

/***********************************************************************************
  \brief The function is called by the stack to notify the application that a 
  binding request has been received from a remote node.
  Mandatory function: must be present in any application.
  
  \param[in] unbindInd - information about the unbound device
  \return none
 ***********************************************************************************/
void ZDO_UnbindIndication(ZDO_UnbindInd_t *unbindInd)
{
  (void)unbindInd;
}
#endif //_BINDING_

/**********************************************************************//**
  \brief The entry point of the program. This function should not be
  changed by the user without necessity and must always include an
  invocation of the SYS_SysInit() function and an infinite loop with
  SYS_RunTask() function called on each step.
  \return none
**************************************************************************/
int main(void)
{
  //Initialization of the System Environment
  SYS_SysInit();

  //The infinite loop maintaing task management
  for(;;)
  {
    //Each time this function is called, the task
    //scheduler processes the next task posted by one
    //of the BitCloud components or the application
    SYS_RunTask();
  }
}

//eof app.c