#include <ezusb.h>
#include <ezregs.h>

#include "AD7739.h"

#include "timer.h"
#include "led.h"

/**
 * AD7739
 *
 * === Connection ===
 * EzUSB           AD7739
 *  PB4(OUT)   <=>  SCLK
 *  PB5(IN)    <=>  DOUT
 *  PB6(OUT)   <=>  DIN
 *  PC2/-INT0  <=>  -RDY
 */

#define clk_up()     (OUTB |= 0x10)
#define clk_down()   (OUTB &= ~0x10)
#define out_up()     (OUTB |= 0x40)
#define out_down()   (OUTB &= ~0x40)
#define is_in_up()   (PINSB & 0x20)
#define is_int0_up() (PINSC & 0x04)


void ad7739_out_write(u8 b)
{
	u8 mask = 0x80;
	do{
		clk_down();
		(b & mask) ? out_up() : out_down();
		clk_up();
	}while(mask >>= 1);
	out_up();
}

u8 ad7739_in_read(void)
{
	u8 temp = 0;
	u8 mask = 0x80;
	out_down();
	do{
		clk_down();
		if(is_in_up()) temp |= mask;
		clk_up();
	}while(mask >>= 1);
	out_up();
	return temp;
}

void ad7739_init(void)
{
	int ch;
  
	PORTBCFG &= 0x8F;
	OEB |= 0x50;
	OEC &= ~(0x04);

	// Caliblation
	PORTCCFG &= ~0x04;	
	ad7739_out_write(AD7739_WRITE_OP(AD7739_ADDR_MODE));
	ad7739_out_write(0x80);  // ADC Zero-Scale 
	while(is_int0_up());
	ad7739_out_write(AD7739_WRITE_OP(AD7739_ADDR_MODE));
	ad7739_out_write(0xA0);  // ADC Full-Scale
	while(is_int0_up());

	// continuous
	for(ch = 0; ch < 8; ch++){
		ad7739_out_write(AD7739_WRITE_OP(AD7739_CHANNEL(AD7739_ADDR_C_SET, ch)));
		ad7739_out_write(0x0C);
  }
	ad7739_out_write(AD7739_WRITE_OP(AD7739_ADDR_IO));
	ad7739_out_write(0x38);

	// Interrupt config
	PORTCCFG |= 0x04;
	IT0 = 1; // INT0 edge sense
	EX0 = 1; // INT0 enable
	
	clk_up();
	out_up();
}

void ad7739_start(void)
{
	// single
	/*
	ad7739_out_write(AD7739_WRITE_OP(AD7739_CHANNEL(AD7739_ADDR_MODE, 0)));
	ad7739_out_write(0x42);
	*/

	// continuous
	ad7739_out_write(AD7739_WRITE_OP(AD7739_ADDR_MODE));
	ad7739_out_write(0x26);
}

void ad7739_stop(void)
{
	// single
	/* return; */

	// continous
	ad7739_out_write(AD7739_WRITE_OP(AD7739_ADDR_MODE));
	ad7739_out_write(0x02);
}

void ISR_EXTR0(void) interrupt INT0_VECT
{
	int ch, count;
	static int loop = 0;

  //IE0 = 0; // Auto Clear TCON.1(IE0) Flag

	ad7739_stop();

	// single
	/*
	ad7739_out_write(AD7739_READ_OP(AD7739_CHANNEL(AD7739_ADDR_C_DATA, 0)));
	b = ad7739_in_read();
	b = ad7739_in_read();
	b = ad7739_in_read();
	*/
	
	// continous
	if( !(EPIO[IN2BUF_ID].cntrl & bmEPBUSY) ){	// Is the IN2BUF available,
    count = 0;
    IN2BUF[count++] = (global_ms >> 24) & 0xFF;
    IN2BUF[count++] = (global_ms >> 16) & 0xFF;
    IN2BUF[count++] = (global_ms >> 8) & 0xFF;
    IN2BUF[count++] = global_ms & 0xFF;
    for(ch = 0; ch < 8; ch++){
      ad7739_out_write(AD7739_READ_OP(AD7739_CHANNEL(AD7739_ADDR_C_DATA, ch)));
      IN2BUF[count++] = ad7739_in_read();
      IN2BUF[count++] = ad7739_in_read();
      IN2BUF[count++] = ad7739_in_read();
    }
    EPIO[IN2BUF_ID].bytes = count;
	}
	
	if(++loop == 100){
		led1_toggle();
		loop = 0;
	}
}

