#include <stdio.h>


#define applyMask(mask, bit) do { \
	if(tmp & mask) { \
		tmp &= mask; \
		shift |= bit; \
	} \
	else { \
		tmp &= ~mask; \
	} \
	} while (0);

// convert 12bit to 8
unsigned char encode(unsigned short sample)
{
	unsigned short tmp;
	unsigned char out, shift = 0;
	

	sample -= 0x800; // убираем начальное смещение
	
	out = (sample & 0x800) >> 4; // получаем знак числа

	// инвертируем если необходимо
	if(out) { 
		sample = ~sample;
	}
	

	// Ищем старший установленный бит 
	// (можно заменить на более оптимальную встроенную инструкцию)
	tmp = sample >> 4;
	applyMask(0x78, 4);
	applyMask(0x66, 2);
	applyMask(0x55, 1);

	// Добавляем экспоненту
	out |= shift << 4;
	
	// Добавляем мантиссу
	out |= (sample >> (shift ? --shift : 0)) & 0xF;

	return out;
	
}

unsigned short decode(unsigned char sample)
{
	unsigned short out, shift;
	
	shift = (sample >> 4) & 7;
	out = (sample & 0xF) | (shift ? --shift, 0x10 : 0);
	out <<= shift;
	
	if(shift) {
		out |= out >> 5;
	}


	if(sample & 0x80) {
		out = ~out;
	}

	return out + 0x800;
}

int main(void) {

	unsigned short a[] = {0, 0x40, 0xFF0, 0xFFF, 0x81F, 0x82D, 0x59f, 0x7CF, 0x200, 0x936, 0x7ff};
	unsigned char encoded;

	int i = 0;
	
	for(i=0; i < (sizeof(a)/sizeof(a[0])); i++) {
		
		encoded = encode(a[i]);
		
		printf("\noriginal = 0x%X"
		"\nencoded = 0x%X"
		"\ndecoded = 0x%X\n", a[i], encoded, decode(encoded));
		
	}

	



	// your code goes here
	return 0;
}
