#include "willepr.h"

//--------------------------------
//           SPI AT25080
//--------------------------------
class spi25{
    private:
	    unsigned long rd,wr;
	    unsigned char mclock_in(void);
	    void mclock_out(unsigned long bit);
    public:
	    unsigned char wren,wrdi,rdsr,wrsr;
	    unsigned int  data,status;
	    unsigned char protect14,protect12,protectAL;

	    void init_code(void);
	    unsigned char spi_data(void);
	    void spi_command(unsigned char w);
	    unsigned char spi_read(unsigned long adres);
	    void spi_write(unsigned long adres,unsigned char data);
}AT25xxx;

void spi25::init_code(void) {
	wren = 0x60;		// 0000 x110
	wrdi = 0x40;		// 0000 x100
	rdsr = 0x05;		// 0000 x101 iiii iiii
	wrsr = 0x01;		// 0000 x001 ssss ssss
	rd   = 0x030000;	// 0000 x011 aaaa aaaa aaaa aaaa iiii iiii
	wr   = 0x02000000;	// 0000 x010 aaaa aaaa aaaa aaaa dddd dddd

	protect14 = 0x04;
	protect12 = 0x08;
	protectAL = 0x0C;
}

unsigned char spi25::mclock_in(void)			// DW: added void
{
	 unsigned char b;

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

void spi25::mclock_out(unsigned long bit)		 // DW: ANSIfied
{
	 bit? outlo:outhi;asadres;
	 ms_delay(2); adrhi;asadres;
	 ms_delay(2); outhi;asadres;
	 ms_delay(2); adrlo;asadres;
}

unsigned char spi25::spi_data(void)			// DW: added void
{
	unsigned char w =0;
	int b;
	adrlo;asadres;
	for (b=7;b>=0;b-- )
		w = w |( mclock_in()<<b);
	adrlo;asadres;
	return w;
}

void spi25::spi_command(unsigned char w) // DW: added void
{
	 int b, di;
	 for ( b=7; b>=0;--b ) {
		di=(w>>b) & 0x01;
		mclock_out(di);
	 }
}

unsigned char spi25::spi_read(unsigned long adres){

	   unsigned char ch;
	   int n;
	   unsigned long adres2,r;

	   if( aantal > 0x200) {
		   r = 0x800000;
		   adres = rd|adres;
		   for(n=24;n>0;n--){
			   mclock_out(adres&r);
			   r = r>>1;
		   }
	    }
	    else {
		   r = 0x8000;
		   adres2 = (adres<<3) & 0x0800;
		   adres = adres&0xff;
		   adres = (rd>>8)|adres|adres2;
		   for(n=16;n>0;n--){
			   mclock_out(adres&r);
			   r = r>>1;
		   }
	    }

	   ch = spi_data();
}

void spi25::spi_write(unsigned long adres,unsigned char data){

	   int n;
	   unsigned long adres2,r;
	   if (aantal > 0x200) {  //AT25080...25256
		   adres = wr|(adres<<8)|data;
		   r = 0x80000000;
		   for(n=32;n>0;n--){
			   mclock_out(adres&r);
			   r = r>>1;
		   }
	    }

	    else  {      //AT25010...AT25040
		   adres2 = (adres<<3) & 0x0800;
		   adres = adres & 0xff;
		   adres = (wr>>8)|(adres<<8)|adres2|data;
		   r = 0x800000;
		   for(n=24;n>0;n--){
			   mclock_out(adres&r);
			   r = r>>1;
		   }
	    }
}

//-----------------------------------------
void read_25C(void){

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

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

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

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

		cs_lo;ms_delay(2);
		g = AT25xxx.spi_read(i);
		ms_delay(2);cs_hi
		rombuf[XMSCurrent(i,1)]=g;
		if(e==t){ tcu_wprintf(&window4,"þ");e=0; }
		e++;
	}
	tcu_close_window(&window4);
	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 prog_25C(void){			// DW: added void

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

	show_action("Programming chip");

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

	if(grot>aantal)grot=aantal;
	for(i=0;i<grot;i++){
		cs_lo;ms_delay(2);
		AT25xxx.spi_command(AT25xxx.wren);
		ms_delay(2);cs_hi;ms_delay(1);

		g=*(rombuf+XMSCurrent(i,0));
		cs_lo;ms_delay(2);	    // DW: Made this XMS-aware
		AT25xxx.spi_write(i,g);     // 0000 x010
		ms_delay(2);cs_hi;
		if(e==t){tcu_wprintf(&window4,"þ");e=0;	}
		e++;wt=0;
		ms_delay(11000);	    //delay 10 mS

	}
S:      cs_lo;ms_delay(2);
	AT25xxx.spi_command(AT25xxx.wrdi);
	ms_delay(2);cs_hi;
	tcu_close_window(&window4);
	power_down();
	reset_timer(); tcu_warnbeep(); setup_timer(0xb0);
	read;assert; 		//ARW: duplication but left for clarity
}

void verify_25C(void){

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

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

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

	if(grot>=aantal)grot=aantal-1;
	for(i=0;i<=grot;i++){
		cs_lo;ms_delay(2);
		g = AT25xxx.spi_read(i);
		ms_delay(2);cs_hi;ms_delay(5);
		if( g!=*(rombuf+XMSCurrent(i,0))){
			 show_error(i,st,g);
			 goto EXIT_25C;
		}
		if(e==t){
			tcu_wprintf(&window4,"þ");
			e=0;
		}
		e++;
	}
	reset_timer(); tcu_warnbeep(); setup_timer(0xb0);

EXIT_25C:
	tcu_close_window(&window4);
	power_down();
	outhi;asadres;
	read;assert;
}

//------------------- end AT25xxx ---------------------
