--file hex_bin_hex.VHD.
--This program reads hex data, converts to binary, and reconverts to hex.
--Flushed output should match input file. fc in.bmp out.txt should yield no differences.
--The input to this program is an ASCII file, and its name is in.bmp.
--It must exist in the same directory as this source code.
--The name of the output file is out.txt.
--The input and output format follows this format:
--The header consists of the first 4 rows:
--BM		reserved word
--00		reserved
--rows		
--cols
--The pixels grey levels follow the header. Each line contains one row
--of pixels, and each byte(two characters) represent the gray level of a pixel.
--For example:
--BM
--00
--20
--20
--FFAA009BCDEF0707096600011111000101010101
--1111000100111111000101001111001111000100
--11110001011011110
entity main_body is generic(data_bus:integer:=8); end;
library std;
use std.textio.all;
architecture behavioral of main_body is
	subtype data is bit_vector(data_bus downto 1);
	type hex is ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
	--redefine if lower case letters are desired
	function char2hex(inchar:character) return hex is
			variable x:integer;
	begin
		case inchar is
			when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => x:=character'pos(inchar)-48;
			when 'A'|'B'|'C'|'D'|'E'|'F' => x:=character'pos(inchar) - 55;
			when others => x := 0;--return 0h when invalid character
		end case;
		return hex'val(x);
	end;
	function hex2char(inchar:hex) return character is
			variable x:integer;
	begin
		case inchar is
			when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => x:=hex'pos(inchar)+48;
			when 'A'|'B'|'C'|'D'|'E'|'F' => x:=hex'pos(inchar) + 55;
			when others => x := 48;--return '0' when invalid character
		end case;
		return character'val(x);
	end;
	procedure int2log(coming:in integer;leaving:inout bit_vector) is
			variable bv : bit_vector(leaving'length downto 1) := (others => '0');
			variable pos : integer := 0;
			variable tmpval : integer := coming;
	begin
			for i in 1 to leaving'length loop
				pos := pos + 1;
				if (tmpval mod 2) = 1 then bv(i) := '1';
				end if;
				tmpval := tmpval / 2;
				exit when tmpval = 0;
			end loop;
			leaving:=bv;
	end;
	function logic2int(coming:in bit_vector) return integer is
	--conversion of array of logic values (bit vector) to an integer
			variable work:integer:=0;
	begin
			for i in coming'range loop
				work:=work*2;
				if coming(i)='1' then work:=work+1; end if;
			end loop;
			return work;
	end logic2int;
	file myfile:text is "in.bmp";
	file outfile:text is out "out.txt";
begin
	test: process
			variable eol:boolean;
			variable pelchar:string(1 to 2);
			variable a:data;
			variable pelbyte:hex;
			variable hibyte,lobyte,No,rows,cols:integer;
			variable ilin,tempout:line;
			variable header:string(1 to 4);
	begin
		--reading the header
		readline(myfile,ilin);read(ilin,header,eol);write(tempout,header);
		read(ilin,header,eol);
		rows:=10*(character'pos(header(1))-character'pos('0'))+(character'pos(header(2))-character'pos('0'));
		cols:=10*(character'pos(header(3))-character'pos('0'))+(character'pos(header(4))-character'pos('0'));
		write(tempout,header);
		writeline(outfile,tempout);
		--processing the pixels
		while not endfile(myfile) loop	--read one byte at a time.
			readline(myfile,ilin);
			read(ilin,pelchar,eol);
			while eol loop	--exhaust line
				pelbyte:=char2hex(pelchar(1));hibyte:=hex'pos(pelbyte);
				pelbyte:=char2hex(pelchar(2));lobyte:=hex'pos(pelbyte);
				No:=16*hibyte+lobyte;
				int2log(No,a);
				No:=logic2int(a);
				pelbyte:=hex'val(No/16);
				pelchar(1):=hex2char(pelbyte);
				pelbyte:=hex'val(No mod 16);
				pelchar(2):=hex2char(pelbyte);
				write(tempout,pelchar);
				read(ilin,pelchar,eol);
			end loop;
			eol:=true;
			writeline(outfile,tempout);
		end loop;
		wait;
	end process;
end behavioral;