#include "willepr.h"

//--------------------------------
//           Microwire
//--------------------------------
class m93c46{
    public:
	    unsigned int rd,wr,ewen,ewds,erase,eral,wral;
	    unsigned int adres,data,count_bit,bit16;
	    void init_code(void);
	    void shift_L(int shift);
	    void shift_R(int shift);
	    int mclock_in(void);
	    int min_word(void);
	    void mclock_out(int bit);
	    void mout_word(unsigned char w);
	    void send_instruction(int instr);
}m93Cxx;

void m93c46::init_code(void) {
	  // 8bit
     rd  = 0x0300;	// 0011 0aaa aaaa
     wr = 0x0280;	// 0010 1aaa aaaa
     ewen  = 0x0260;	// 0010 011x xxxx
     ewds  = 0x0200;	// 0010 000x xxxx
     erase = 0x0380;	// 0011 1aaa aaaa
     eral  = 0x0240;	// 0010 010x xxxx
     wral  = 0x0220;	// 0010 001x xxxx
     count_bit = 10;
     adres =  7;
     data  =  8;
     bit16 =  1;
}

void m93c46::shift_L(int shift) {
	  // 8bit
     rd    = rd<<shift;		// 0011 0aaa aaaa
     wr    = wr<<shift;		// 0010 1aaa aaaa
     ewen  = ewen<<shift;	// 0010 011x xxxx
     ewds  = ewds<<shift;	// 0010 000x xxxx
     erase = erase<<shift;	// 0011 1aaa aaaa
     eral  = eral<<shift;	// 0010 010x xxxx
     wral  = wral<<shift;	// 0010 001x xxxx
     count_bit = 10+shift;
     adres =  7+shift;
}

void m93c46::shift_R(int shift) {
	  // 8bit
     rd    = rd>>shift;		// 0011 0aaa aaaa
     wr    = wr>>shift;		// 0010 1aaa aaaa
     ewen  = ewen>>shift;	// 0010 011x xxxx
     ewds  = ewds>>shift;	// 0010 000x xxxx
     erase = erase>>shift;	// 0011 1aaa aaaa
     eral  = eral>>shift;	// 0010 010x xxxx
     wral  = wral>>shift;	// 0010 001x xxxx
     count_bit = 10-shift;
     adres =  7-shift;
}

int m93c46::mclock_in(void)			// DW: added void
{
	 int b;

	 ms_delay(2);
	 adrhi;asadres;
	 ms_delay(2);
	 b = einbit? 0: 1;
	 ms_delay(2);
	 adrlo;asadres;
	 return b;
}

int m93c46::min_word(void)			// DW: added void
{
	int b, w=0;
	 adrlo;asadres;
	for (b=7;b>=0;b-- )
	w =w |( mclock_in()<<b);
	  adrlo;asadres;
	return w;
}

void m93c46::mclock_out(int bit)			// DW: ANSIfied
{
	 bit? outlo:outhi;asadres;
	 ms_delay(2);
	 adrhi;asadres;
	 ms_delay(2);
	 outhi;asadres;
	  ms_delay(2);
	 adrlo; asadres;

}
void m93c46::mout_word(unsigned char w)			// DW: added void
{
	 int b, di;

	 for ( b=7; b>=0;--b )
	 {di=(w>>b) & 0x01;
		 mclock_out(di);}
}

void m93c46::send_instruction(int instr){

	   int n, di;
	   for(n=m93Cxx.count_bit-1;n>=0; n--){
		   di=(instr>>n) & 0x01;
		   mclock_out(di);
	   }
}
//------------ end class m93C -------------------
void verify_93(void){

	unsigned int e=0, t=aantal/52, i,a=0,instr;
	unsigned char g;

	write;assert;
	show_action("Verify Chip",BLUE);

	outhi,adrlo;pgrlo;asadres;assert;
	powon;assert;
	ms_delay(30000);

	if(grot>=aantal)grot=aantal-1;
	for(i=0;i<=grot;i++){

		cs_hi;
		ms_delay(1);
		instr= m93Cxx.rd | (i/m93Cxx.bit16);
		m93Cxx.send_instruction(instr);
		ms_delay(10);

		g=m93Cxx.min_word();
		if( g!=*(rombuf+XMSCurrent(i,0))){		// DW: Made this XMS-aware
			 show_error(i,st,g);
			 goto EXIT_93C;
		}
		if(m93Cxx.bit16 == 2){
			i++;
			g=m93Cxx.min_word();
			if( g!=*(rombuf+XMSCurrent(i,0))){		// DW: Made this XMS-aware
				show_error(i,st,g);
				goto EXIT_93C;
			}
		}
		cs_lo;
		if(e==t){
			tcu_wprintf(&window4,"þ");
			e=0;
		}
		e++;
	}
	reset_timer(); tcu_warnbeep(); setup_timer(0xb0);

EXIT_93C:
	tcu_close_window(&window4);
	cs_lo;
	power_down();
	outhi;asadres;
	//powoff,
	read;assert; 		//ARW: duplication but left for clarity
}


void read_93(void){

	unsigned int e=0, t=aantal/52, i,a=0,instr;
	unsigned char g;

	write;assert;
	show_action("reading chip",BLACK);

	outhi,adrlo;pgrlo;asadres;assert;
	powon;assert;
	ms_delay(20000);

	for(i=0;i<aantal;i++){

		cs_hi;
		ms_delay(1);
		instr= m93Cxx.rd | (i/m93Cxx.bit16);
		m93Cxx.send_instruction(instr);

			ms_delay(10);

		g=m93Cxx.min_word();
		rombuf[XMSCurrent(i,1)]=g;
		if(m93Cxx.bit16 == 2){i++;
			g=m93Cxx.min_word();
			rombuf[XMSCurrent(i,1)]=g;}
		cs_lo;
		if(e==t){
			tcu_wprintf(&window4,"þ");
			e=0;
		}
		e++;
	}

	tcu_close_window(&window4);
	cs_lo;
	power_down();
	reset_timer(); tcu_warnbeep(); setup_timer(0xb0);

	outhi;asadres;
	//powoff,
	read;assert; 		//ARW: duplication but left for clarity

	grot=aantal;
	strcpy(statbuf,"Chip dump");winstat();
}

void erase_93(void)  // erases all bytes
{
   int instr;int wt=0;
	//   powon;assert;
	//   ms_delay(30000);
   pgrhi;assert;
   m93Cxx.send_instruction(m93Cxx.erase);           //0001 0010
   cs_lo;
   ms_delay(5);
   cs_hi;
   while(!einbit){ms_delay(1000);wt++;if(wt==50)break;}
   cs_lo;
   reset_timer(); tcu_warnbeep(); setup_timer(0xb0);

}

void prog_93(void){			// DW: added void

	unsigned int e=0, t=aantal/52, i;
	int w=0;int wt=0;
	int g,k;

	if(grot>aantal)grot=aantal;
	write;assert;
	show_action("programming chip");

	outhi,adrlo;pgrlo;asadres;assert;
	powon;assert;
	ms_delay(30000);
	cs_hi;
	m93Cxx.send_instruction(m93Cxx.ewen);       //0001 0011
	cs_lo;
	erase_93();
	ms_delay(3000);
	cs_hi;
	m93Cxx.send_instruction(m93Cxx.ewen);
	cs_lo;
	ms_delay(3000);
	for(i=0;i<grot;i++){
		g=*(rombuf+XMSCurrent(i,0));
		cs_hi;		// DW: Made this XMS-aware
		m93Cxx.send_instruction(m93Cxx.wr | (i/m93Cxx.bit16) );   // 0001 0100
		m93Cxx.mout_word(g);
		if(m93Cxx.bit16 == 2){i++;
			g=*(rombuf+XMSCurrent(i,0));
			m93Cxx.mout_word(g); }

		cs_lo;ms_delay(5);cs_hi;
		ms_delay(12000);
		cs_lo;

		if(e==t){
			tcu_wprintf(&window4,"þ");
			e=0;
		}
		e++;wt=0;
	}
S:
	m93Cxx.send_instruction(m93Cxx.ewds);
	tcu_close_window(&window4);
	cs_lo;
	power_down();
	reset_timer(); tcu_warnbeep(); setup_timer(0xb0);
	read;assert; 		//ARW: duplication but left for clarity
}
//------------------- end 93C,93LC ---------------------
