/*
 * main.c
 *
 * The entry point for the firmware.
 * To compile
 * add the include path of the fx2 stuff e.g. "C:\Program Files\SDCC\include\FX2" into 
 * Project->Properties C/C++ Build -> Settings -> Tool Settings -> SDCC-Compiler -> Directories
 * Use the '"' sign if space occour in the path!
 * add the parameter "--code-loc 512" (without '"') into the Linker parms
 * Project->Properties C/C++ Build -> Settings -> Tool Settings -> SDCC-Linker -> command field
 * 
 */

#include "fx2.h"
#include "fx2regs.h"
#include "SevenSeg.h"			// 7 Segment Led on Port A
#include "syncdly.h"            // SYNCDELAY macro

#define INT_TMR0	1

#define INTS_ENABLE 0x80
#define INT_TMR0_EN 0x02

#define TMR_EN0		0x10

BYTE buffer2ctr;

extern void sleep(unsigned int);

int _sdcc_external_startup() { 
	return 1;
}

void StuffBuffer(void){
	
	while(!(EP2468STAT & bmEP2FULL)) {
    	SYNCDELAY;
	    EP2FIFOBUF[0] = buffer2ctr;
    	buffer2ctr++;
	    SYNCDELAY;
    	EP2BCH = 0x04;
	    SYNCDELAY;  
    	EP2BCL = 0x00;        // arm EP2IN
	    SYNCDELAY;
	}
return;
}

// The entry point.
void main(void) {
//	BYTE i;
	// Init USB
	EUSB = 1; // Enable USB interrupt

	USBIE |= 0xFF;  // Enable all USB Control interrupts

	INTSETUP = 0x08; // Enable USB Autovectoring

	EPIE |= 0x0F; // Enable EP0/EP1 interrupts

	// Init CPU clock, 48mhz
	CPUCS = 0x10;

	// Set SRAM to as fast as possible
	CKCON = 0;

	// Init interrupts
	IE = INTS_ENABLE;
	
    // set the slave FIFO interface to 48MHz
	IFCONFIG |= 0x40;
	

	// Registers which require a synchronization delay, see section 15.14
	// FIFORESET        FIFOPINPOLAR	
	// INPKTEND         OUTPKTEND
	// EPxBCH:L         REVCTL
	// GPIFTCB3         GPIFTCB2
	// GPIFTCB1         GPIFTCB0
	// EPxFIFOPFH:L     EPxAUTOINLENH:L
	// EPxFIFOCFG       EPxGPIFFLGSEL
	// PINFLAGSxx       EPxFIFOIRQ
	// EPxFIFOIE        GPIFIRQ
	// GPIFIE           GPIFADRH:L
	// UDMACRCH:L       EPxGPIFTRIG
	// GPIFTRIG
	  
	// Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
	//      ...these have been replaced by GPIFTC[B3:B0] registers

	// default: all endpoints have their VALID bit set
	// default: TYPE1 = 1 and TYPE0 = 0 --> BULK  
	// default: EP2 and EP4 DIR bits are 1 (IN direction)
	// default: EP6 and EP8 DIR bits are 1 (IN direction)
	// default: EP2, EP4, EP6, and EP8 are double buffered

	// Config bits
	//EP  | b7    | b6   | b5    | b4    | b3   | b2 | b1   | b0
	//----+-------+------+-------+-------+------+----+------+-----
	//2,6 | VALID | DIR  | TYPE1 | TYPE0 | SIZE | 0  | BUF1 | BUF0
	//4,8 | VALID | DIR  | TYPE1 | TYPE0 | 0    | 0  | 0    | 0
	//
	//      0 Invalid
	//      1 Valid
	//              0 OUT
	//              1 IN
	//                     0       0 Invalid
	//                     0       1 ISOCHRONOUS
	//                     1       0 BULK (default)
	//                     1       1 INTERRUPT
	//                                    0 = 512
	//                                    1 = 1024
	//                                                 0      0 Quad
	//                                                 0      1 Invalid
	//                                                 1      0 Double
	//                                                 1      1 Triple
	  
	EP2CFG    = 0xD8; // iso 1024 quad
	SYNCDELAY;   
    EP2ISOINPKTS = 0x03;
	SYNCDELAY;   
	
	
	EP4CFG    = 0x00;
	SYNCDELAY;
	EP6CFG    = 0x00;
	SYNCDELAY;                    
	EP8CFG    = 0x00; 
	SYNCDELAY;                    
	EP2FIFOBUF[1] = '2';
	
    EP1OUTCFG = 0x00; 
    SYNCDELAY;
    EP1INCFG = 0x00;
    SYNCDELAY;
   
    // Clear out any committed packets
    FIFORESET = 0x80;
    SYNCDELAY;
    FIFORESET = 0x02;
    SYNCDELAY;
    FIFORESET = 0x00;
    SYNCDELAY;
	
	
	// Prevent High speed enumeration...
	//   Windows gives the usual "it's running slower" message
	//CT1 = 0; // 0 = allow high speed, anything else (should be 2?) is disallow

	sleep(500);

	// disconnect from USB and set the renumerate bit
    USBCS |= (bmDISCON | bmRENUM);        

	// delay for 500ms ?  I've even seen 1500 ms
	sleep(1500);

	// maybe we should even clear IRQs
	USBIRQ = 0xff;          // Clear any pending USB interrupt requests.  They're for our old life.
	EPIRQ = 0xff;
	EZUSB_IRQ_CLEAR();
	
	// reconnect USB
	USBCS &=~bmDISCON;      
	// delay again...
	sleep(500);

	// CLKOUT enabled
	CPUCS |= 0x02;

	// Now enable timer interrupt
	IE = INTS_ENABLE | INT_TMR0_EN;

	// Init timer 0
	TH0 = 0x00; // Timer 0 value
	TL0 = 0x00;
	TMOD = 0x01; // TMR0: Mode 1, 16 bit counter
	TCON = TMR_EN0;

    while (1) {
    	StuffBuffer();
    }    
}
