#include"bitgestion.h"

//SET N th bit to one 


void throwError( uint16_t error)
{
	printf("\n\rAglorithm.c : An Error has been generated on line : >>%d<<\n\r",error);
	exit(1);
}


void setBitUint8(uint8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value|= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void setBitInt8(int8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value|= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void setBitUint16(uint16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value|= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void setBitInt16(int16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value|= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

//SET N th bit to 0 
void unsetBitUint8(uint8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value&=~(1 << n);  
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void unsetBitInt8(int8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value&=~(1 << n);  
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void unsetBitUint16(uint16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value&=~(1 << n);  
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void unsetBitInt16(int16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value&=~(1 << n);  
	}
	else 
	{
		throwError(__LINE__); 
	}
}

//Toggle N th bit 
void toggleBitUint8(uint8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value^= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void toggleBitInt8(int8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		*value^= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void toggleBitUint16(uint16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value^= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void toggleBitInt16(int16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		*value^= 1 << n; 
	}
	else 
	{
		throwError(__LINE__); 
	}
}

//Get N th bit
uint8_t getBitUint8(uint8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		return (*value>> n) & 1; 
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int8_t getBitInt8(int8_t *value, uint8_t &n)
{
	if (n < 8 && n >=0)
	{
		return (*value>> n) & 1; 
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

uint16_t getBitUint16(uint16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		return (*value>> n) & 1; 
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int16_t getBitInt16(int16_t *value, uint8_t &n)
{
	if (n < 16 && n >=0)
	{
		return (*value>> n) & 1; 
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}



//Change N th bit to x 
//number = (number & ~(1UL << n)) | (x << n);

void changeBitUint8(uint8_t *value, uint8_t &n, uint8_t &x)
{
	if (n < 8 && n >=0)
	{
		*value= (*value& ~(1 << n)) | (x << n);
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void changeBitInt8(int8_t *value, uint8_t &n, uint8_t &x)
{
	if (n < 8 && n >=0)
	{
		*value= (*value& ~(1 << n)) | (x << n);
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void changeBitUint16(uint16_t *value, uint8_t &n, uint8_t &x) 
{
	if (n < 16 && n >=0)
	{
		*value= (*value& ~(1 << n)) | (x << n);
	}
	else 
	{
		throwError(__LINE__); 
	}
}

void changeBitInt16(int16_t *value, uint8_t &n, uint8_t &x)
{
	if (n < 16 && n >=0)
	{
		*value= (*value& ~(1 << n)) | (x << n);
	}
	else 
	{
		throwError(__LINE__); 
	}
}




//GET N numer of least significant bits
uint8_t get_n_bits_lsb_uint8( uint8_t *value, uint8_t &bits)
{
	if (bits < 8 && bits >=0)
	{
		return *value& ((1 << bits)-1);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int8_t get_n_bits_lsb_int8(int8_t *value, uint8_t &bits)
{
	if (bits < 8 && bits >=0)
	{
		return *value& ((1 << bits)-1);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

uint16_t get_n_bits_lsb_uint16( uint16_t *value, uint8_t &bits)
{
	if (bits < 8 && bits >=0)
	{
		return *value& ((1 << bits)-1);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int16_t get_n_bits_lsb_int16( int16_t *value, uint8_t &bits)
{
	if (bits < 16 && bits >=0)
	{
		return *value& ((1 << bits)-1);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}


//Get N number of most signigiant bit.
uint8_t get_n_bits_msb_uint8( uint8_t *value, uint8_t &bits)
{
	if (bits < 8 && bits >=0)
	{
		return *value>> (8-bits);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int8_t get_n_bits_msb_int8(int8_t *value, uint8_t &bits)
{
	if (bits < 8 && bits >=0)
	{
		*value=	*value>> (8-bits);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

uint16_t get_n_bits_msb_uint16( uint16_t *value, uint8_t &bits)
{
	if (bits < 16 && bits >=0)
	{
		return *value>> (16-bits);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int16_t get_n_bits_msb_int16( int16_t *value, uint8_t &bits)
{
	if (bits < 16 && bits >=0)
	{
		return *value>> (16-bits);	
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

// Get Bits range from startBit to stopBit and return them shifted.  
uint8_t get_bits_range_uint8( uint8_t *value, uint8_t &startBit, uint8_t &stopBit)
{
	if (startBit < 8 && startBit >=0)
	{
		if(stopBit < 8 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				uint8_t mask = 0;
				uint8_t i = 0; 
				for(i = startBit; i <= stopBit; i++ )
        		{
                	mask |= (1 << i);
        		}
        		return ((*value& mask) >> startBit); 
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

int8_t get_bits_range_int8( int8_t *value, uint8_t &startBit, uint8_t &stopBit)
{
	if (startBit < 8 && startBit >=0)
	{
		if(stopBit < 8 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				uint8_t mask = 0;
				uint8_t i = 0; 
				for(i = startBit; i <= stopBit; i++ )
        		{
                	mask |= (1 << i);
        		}
        		return (*value& mask) >> startBit; 
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}

uint16_t get_bits_range_uint16( uint16_t *value, uint8_t &startBit, uint8_t &stopBit)
{
	if (startBit < 16 && startBit >=0)
	{
		if(stopBit < 16 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				uint16_t mask = 0;
				uint8_t i = 0; 
				for(i = startBit; i <= stopBit; i++ )
        		{
                	mask |= (1 << i);
        		}
        		return (*value& mask) >> startBit; 
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}



int16_t get_bits_range_int16( int16_t *value, uint8_t &startBit, uint8_t &stopBit)
{
	if (startBit < 16 && startBit >=0)
	{
		if(stopBit < 16 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				int16_t mask = 0;
				uint8_t i = 0; 
				for(i = startBit; i <= stopBit; i++ )
        		{
                	mask |= (1 << i);
        		}
        		return (*value& mask) >> startBit; 
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
	return 0; 
}


void set_bits_range_uint8(uint8_t *value, uint8_t &startBit, uint8_t &stopBit, uint8_t &replace)
{ 
	if (startBit < 8 && startBit >=0)
	{
		if(stopBit < 8 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				uint8_t mask = 0;
				uint8_t i = 0; 
				mask = (replace >> (stopBit - startBit +1)); 
				
				if(mask == 0)
				{
					for(i = startBit; i <= stopBit; i++ )
					{
						mask |= (1 << i);
					}
					*value= (*value & ~mask) | replace << startBit; 
				}
				else 
				{
					throwError(__LINE__); 
				}
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
}
void set_bits_range_uint16(uint16_t *value, uint8_t &startBit, uint8_t &stopBit, uint16_t &replace)
{ 
	if (startBit < 16 && startBit >=0)
	{
		if(stopBit < 16 && stopBit >=0)
		{
			if(startBit < stopBit)
			{
				uint16_t mask = 1;
				uint8_t i = 0; 
			
				mask = (replace >> (stopBit - startBit +1)); 
				
				if(mask == 0)
				{
					for(i = startBit; i <= stopBit; i++ )
					{
						mask |= (1 << i);
					}
					*value= (*value & ~mask) | replace << startBit; 
				}
				else 
				{
					throwError(__LINE__); 
				}
			}
			else 
			{
				throwError(__LINE__); 
			}
		}	
		else 
		{
			throwError(__LINE__); 
		}
	}
	else 
	{
		throwError(__LINE__); 
	}
}
