/*****************************************************************************/

/*
 *      fsk.c  --  AnchorChips EZUSB Project main.
 *
 *      Copyright (C) 1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "regezusb.h"

xdata at 0xc001 unsigned short FSKRXCNT;
xdata at 0xc002 unsigned short FSKRXDATA;
xdata at 0xc003 unsigned short FSKRXFLAG;
xdata at 0xc000 unsigned short FSKTXCNT;
xdata at 0xc000 unsigned short FSKTXDATA;
xdata at 0xc001 unsigned short FSKTXCRC;
xdata at 0xc002 unsigned short FSKTXRAW;
xdata at 0xc003 unsigned short FSKTXRAWCLR;
xdata at 0xc004 unsigned short FSKRSSI;
xdata at 0xc008 unsigned short FSKCTRL;
xdata at 0xc009 unsigned short FSKSTAT;
xdata at 0xc00a unsigned short FSKT7FOUT;
xdata at 0xc00b unsigned short FSKT7FIN;

xdata short *errmsg = 0;
unsigned short errcode, errval;

unsigned short ctrlcode;
unsigned int ctrlcount;


void wait_1ms(void)
{
/*   Delay for 1 millisecond (1000 microseconds). */
/*   10 cycles * 166.6 ns per cycle is 1.66 microseconds per loop. */
/*   1000 microseconds / 1.66 = 602.  [assumes 24 MHz clock] */
               
	_asm
	mov     _DPS,#0
	mov     dptr,#(0xffff - 602)    ; /* long pulse for operating */
    loop:
        inc     dptr            ; 3 cycles
        mov     a,dpl           ; 2 cycles
        orl     a,dph           ; 2 cycles
        jnz     loop            ; 3 cycles
        _endasm;
}


#pragma SAVE
#pragma NOOVERLAY

#if 0
void int0_isr(void) interrupt 0
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _TCON+1
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void timer0_isr(void) interrupt 1
{
	static short div;

	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _TCON+5
        _endasm;

	div++;
	div &= 0x7;
	if (!div)
		OUTC ^= 0x08;
	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void int1_isr(void) interrupt 2
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _TCON+3
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void timer1_isr(void) interrupt 3
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _TCON+7
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void ser0_isr(void) interrupt 4
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;




	/* clear interrupt */
	_asm
	clr _SCON0+0
	clr _SCON0+1
        _endasm;
	/* epilogue */
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void timer2_isr(void) interrupt 5
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _T2CON+7
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void resume_isr(void) interrupt 6
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _EICON+4
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void ser1_isr(void) interrupt 7
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;


	
	/* clear interrupt */
	_asm
	clr _SCON1+0
	clr _SCON1+1
        _endasm;
	/* epilogue */
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void i2c_isr(void) interrupt 9
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.5
        mov _EXIF,a
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void int4_isr(void) interrupt 10
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.6
        mov _EXIF,a
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void int5_isr(void) interrupt 11
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.7
        mov _EXIF,a
        _endasm;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void int6_isr(void) interrupt 12
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	clr _EICON+3
        _endasm;

	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

static const short usb_device_descriptor[] = { 
	0x12,        /* bLength */
	0x01,        /* bDescriptorType */
	0x00, 0x01,  /* bcdUSB */
	0xff,        /* bDeviceClass (vendor specific) */
	0x00,        /* bDeviceSubClass */
	0xff,        /* bDeviceProtocol (vendor specific) */
	0x40,        /* bMaxPacketSize0 */
	0x34, 0x12,  /* idVendor */
	0x78, 0x56,  /* idProduct */
	0x02, 0x01,  /* bcdDevice */
	0x00,        /* iManufacturer */
	0x00,        /* iProduct */
	0x00,        /* iSerialNumber */
	0x01         /* bNumConfigurations */
};

static const short usb_config0_descriptor[] = {
	0x09,        /* bLength */
	0x02,        /* bDescriptorType */
	0x19, 0x00,  /* wTotalLength */
	0x01,        /* bNumInterfaces */
	0x01,        /* bConfigurationValue */
	0x00,        /* iConfiguration */
	0x40,        /* bmAttributs */
	0x19,        /* MaxPower */
	/* interface descriptor */
	0x09,        /* bLength */
	0x04,        /* bDescriptorType */
	0x00,        /* bInterfaceNumber */
	0x00,        /* bAlternateSetting */
	0x01,        /* bNumEndpoints */
	0xff,        /* bInterfaceClass (vendor specific) */
	0x00,        /* bInterfaceSubClass */
	0xff,        /* bInterfaceProtocol (vendor specific) */
	0x00,        /* iInterface */
	/* endpoint descriptor */
	0x07,        /* bLength */
	0x05,        /* bDescriptorType */
	0x02,        /* bEndpointAddress */
	0x02,        /* bmAttributes (bulk) */
	0x40, 0x00,  /* wMaxPacketSize */
	0x00         /* bInterval */
};


void usb_sudav_isr(void) interrupt 13
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
        USBIRQ = 0x01;
	/* reset control OUT code */
	ctrlcode = 0;
	/* process control transfer */
	switch (SETUPDAT[1]) { /* bRequest field */
	/* vendor specific */
	case 0xb0:
		if (SETUPDAT[0] != 0xC0)
			goto setupstall;
		{
			short cnt0 = SETUPDAT[6], cnt1;
			xdata short *p1 = (xdata short *)"blah";
			xdata short *p2 = IN0BUF;

			if (cnt0 > 64)
				cnt0 = 64;
			cnt1 = cnt0;
			if (p1) {
				while (cnt0 > 0U && *p1) {
					*p2++ = *p1++;
					cnt0--;
				}
			}	
			while (cnt0 > 0U) {
				*p2++ = 0;
				cnt0--;
			}
			IN0BC = cnt1;
		}
		goto setupack;

	case 0xb1:
		if (SETUPDAT[0] != 0xC0)
			goto setupstall;
		IN0BUF[0] = errcode;
		IN0BUF[1] = errval;
		IN0BUF[2] = SP;
		IN0BUF[3] = 0;
		if ((unsigned short)SETUPDAT[6] > 4U)
			IN0BC = 4;
		else
			IN0BC = SETUPDAT[6];
		goto setupack;

	case 0xbc:
		if (SETUPDAT[0] != 0x40)
			goto setupstall;
		if ((SETUPDAT[6] | SETUPDAT[7]) != 0)
			goto setupstall;
		_asm                     ;
		mov dptr,#(_SETUPDAT+2)  ;
		movx a,@dptr             ;
		mov (_txdelay+0),a       ;
		inc dptr                 ;
		movx a,@dptr             ;
		mov (_txdelay+1),a       ;
		_endasm                  ;
		goto setupack;

	case 0xbd:
#if 0
		if (SETUPDAT[0] != 0x40)
			goto setupstall;
		if ((SETUPDAT[6] | SETUPDAT[7]) != 0)
			goto setupstall;
		_asm         ;
		clr _SCON0+1 ;
		_endasm      ;
		SBUF0 = SETUPDAT[2];
#endif
		goto setupack;

	case 0xbe:
		if (SETUPDAT[0] != 0x40)
			goto setupstall;
		if ((SETUPDAT[6] | SETUPDAT[7]) != 0)
			goto setupstall;
		FSKT7FOUT = SETUPDAT[2];
		goto setupack;

	case 0xc0:
		if (SETUPDAT[0] != 0xc0)
			goto setupstall;
#if 0
		if (SETUPDAT[6] < 6)
			goto setupstall;
#endif
		_asm                  ;
		mov a,_txstate        ;
		mov b,a               ;
		setb b.2              ;
		cjne a,#0,intrx0      ;
		clr b.2               ;
	  intrx0:
		mov dptr,#_FSKSTAT    ;
		movx a,@dptr          ;
		mov c,acc.0           ;
		mov b.3,c             ;
		mov c,_SCON0+1        ;
		mov b.5,c             ;
		jnb _SCON0+0,intrx2   ;
		mov a,_SBUF0          ;
		mov dptr,#(_IN0BUF+4) ;
		movx @dptr,a          ;
		setb b.4              ;
		clr _SCON0+0          ;
	  intrx2:
		; /* bytewide elements */
		mov dptr,#(_IN0BUF)   ;
		mov a,b               ;
		mov a,_txstate        ;
		movx @dptr,a          ;
		mov a,_txwr           ;
		cpl a                 ;
		add a,_txrd           ;
		anl a,#(_TXCHUNKS-1)  ;
		mov dptr,#(_IN0BUF+1) ;
		movx @dptr,a          ;
		mov a,_rxrd           ;
		cpl a                 ;
		add a,_rxwr           ;
		inc a                 ;
		anl a,#(_RXCHUNKS-1)  ;
		mov dptr,#(_IN0BUF+2) ;
		movx @dptr,a          ;
		mov dptr,#_FSKRSSI    ;
		movx a,@dptr          ;
		mov dptr,#(_IN0BUF+3) ;
		movx @dptr,a          ;
		; /* counter */
		inc _irqcount         ;
		mov a,_irqcount       ;
		mov dptr,#(_IN0BUF+5) ;
		movx @dptr,a          ;
		; /* set length */
		mov dptr,#_IN0BC      ;
		mov a,#6              ;
		movx @dptr,a          ;
		_endasm;
		goto setupack;
		
	default:
		goto setupstall;
	}
  setupack:
	EP0CS = 2;  /* clear HSNAK */
	goto endusbisr;
  setupstall:
	EP0CS = 3;  /* signal stall */
	goto endusbisr;
	
  endusbisr:

	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_sof_isr(void) interrupt 14
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	USBIRQ = 0x02;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_sutok_isr(void) interrupt 15
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	USBIRQ = 0x04;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_suspend_isr(void) interrupt 16
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	USBIRQ = 0x08;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_usbreset_isr(void) interrupt 17
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	USBIRQ = 0x10;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep0in_isr(void) interrupt 18
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x01;



	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep0out_isr(void) interrupt 19
{
	xdata unsigned short *dptr;
	unsigned short cnt;

	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x01;

	/* check code */
	if (ctrlcode != 1)
		goto setupstall;
	cnt = OUT0BC;
	
	goto arm;

setupack:
	EP0CS = 2;  /* clear HSNAK */
	ctrlcode = 0;
	goto endusbisr;
setupstall:
	EP0CS = 3;  /* signal stall */
	ctrlcode = 0;
	goto endusbisr;
arm:
	OUT0BC = 1;
endusbisr:	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

unsigned short irqcount;

void fill_intr(void)
{
	_asm                  ;
	mov a,_txstate        ;
	mov b,a               ;
	setb b.2              ;
	cjne a,#0,intr0       ;
	clr b.2               ;
  intr0:
	mov dptr,#_FSKSTAT    ;
	movx a,@dptr          ;
	mov c,acc.0           ;
	mov b.3,c             ;
	mov c,_SCON0+1        ;
	mov b.5,c             ;
	jnb _SCON0+0,intr2    ;
	mov a,_SBUF0          ;
	mov dptr,#(_IN1BUF+4) ;
	movx @dptr,a          ;
	setb b.4              ;
	clr _SCON0+0          ;
  intr2:
	; /* bytewide elements */
	mov dptr,#(_IN1BUF)   ;
	mov a,b               ;
	mov a,_txstate        ;
	movx @dptr,a          ;
	mov a,_txwr           ;
	cpl a                 ;
	add a,_txrd           ;
	anl a,#(_TXCHUNKS-1)  ;
	mov dptr,#(_IN1BUF+1) ;
	movx @dptr,a          ;
	mov a,_rxrd           ;
	cpl a                 ;
	add a,_rxwr           ;
	inc a                 ;
	anl a,#(_RXCHUNKS-1)  ;
	mov dptr,#(_IN1BUF+2) ;
	movx @dptr,a          ;
	mov dptr,#_FSKRSSI    ;
	movx a,@dptr          ;
	mov dptr,#(_IN1BUF+3) ;
	movx @dptr,a          ;
	; /* counter */
	inc _irqcount         ;
	mov a,_irqcount       ;
	mov dptr,#(_IN1BUF+5) ;
	movx @dptr,a          ;
	; /* set length */
	mov dptr,#_IN1BC      ;
	mov a,#6              ;
	movx @dptr,a          ;
	_endasm;
}

void usb_ep1in_isr(void) interrupt 20
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x02;
	
	_asm             ;
	acall _fill_intr ;
	_endasm;

	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep1out_isr(void) interrupt 21
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x02;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep2in_isr(void) interrupt 22
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x04;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep2out_isr(void) interrupt 23
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x04;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep3in_isr(void) interrupt 24
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x08;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep3out_isr(void) interrupt 25
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x08;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep4in_isr(void) interrupt 26
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x10;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep4out_isr(void) interrupt 27
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x10;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep5in_isr(void) interrupt 28
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x20;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep5out_isr(void) interrupt 29
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x20;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep6in_isr(void) interrupt 30
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x40;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep6out_isr(void) interrupt 31
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x40;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep7in_isr(void) interrupt 32
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	IN07IRQ = 0x80;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

void usb_ep7out_isr(void) interrupt 33
{
	_asm         ;
	push _DPL1   ;
	push _DPH1   ;
        push _DPS    ;
	mov  _DPS,#0 ;
        _endasm;
	/* clear interrupt */
	_asm
	mov a,_EXIF
        clr acc.4
        mov _EXIF,a
        _endasm;
	OUT07IRQ = 0x80;


	
	_asm         ;
	pop _DPS     ;
	pop _DPH1    ;
	pop _DPL1    ;
	_endasm;
}

#endif

#pragma RESTORE


void fill_intr(void);

unsigned short leddiv;
unsigned short irqcount;

/*
 * The chunks need to be powers of 2!
 */
#define TXCHUNKS 16
#define RXCHUNKS 32

idata unsigned short txbcnt[TXCHUNKS];
idata unsigned short rxbcnt[RXCHUNKS];

idata unsigned short stack[0x100-TXCHUNKS-RXCHUNKS];

unsigned short txstate; /* 0 = idle, 1 = txdelay, 2 = packet, 3 = txtail */
unsigned int flagcnt, txdelay;
unsigned short txwr, txrd, txtwr, txptr;
unsigned short rxstate;
unsigned short rxwr, rxrd, rxtwr, rxptr;

xdata unsigned short txbuf[TXCHUNKS][64];
xdata unsigned short rxbuf[RXCHUNKS][64];





void ezusbmain(void)
{
	errcode = 0;
	errval = 0;

	txdelay = 10;
	txstate = txwr = txrd = txtwr = txptr = 0;
	rxstate = rxwr = rxrd = rxtwr = rxptr = 0;

	irqcount = 0;

	ISOCTL = 1;  /* disable ISO endpoints */
	USBBAV = 1;  /* enable autovector, disable breakpoint logic */
	/*
	 * Timer setup:
	 * timer 0: LED blink    : T0M=0, CT0=0, MODE0=1
	 * timer 1: Baudrate gen : T1M=1, CT1=0, MODE1=2
	 */
	CKCON = 0x31; /* one external wait state, to avoid chip bugs */
	TMOD = 0x21;
	TCON = 0x55;  /* INT0/INT1 edge */
	TH1 = 256-156;  /* 1200 bauds */
	PCON = 0;  /* SMOD0=0 */

	/* set IO ports accordingly */
	PORTACFG = 0;
	OUTA = 0x82;  /* set PROG hi */
	OEA = 0xc2;   /* out: TMS,TDI,PROG  in: DONE */
	PORTBCFG = 0;
	OEB = 0;
	PORTCCFG = 0xc3;  /* RD/WR/TXD0/RXD0 are special function pins */
	OUTC = 0x20;
	OEC = 0x2a;   /* out: LEDCON,LEDSTA,TCK  in: TDO,INIT */

	/* enable interrupts */
	IE = 0x82;      /* enable timer 0 int */
	EIE = 0x01;     /* enable USB interrupts */
        USBIEN = 1;     /* enable SUDAV interrupt */
	IN07VAL = 0x7;  /* enable EP0+EP1+EP2 */
	OUT07VAL = 0x5; /* enable EP0+EP2 */
	INISOVAL = 0;
	OUTISOVAL = 0;
	IN07IEN = 3;    /* enable EP0+EP1 interrupt */
	OUT07IEN = 1;   /* enable EP0 interrupt */

	/* initialize UART 0 for T7F communication */
	SCON0 = 0x52;     /* Mode 1, Timer 1, Receiver enable */

	/*USBPAIR = 0x09;   /* pair EP 2&3 for input & output */
	USBPAIR = 0;

#if 0
	TOGCTL = 0x12;
	TOGCTL = 0x32;    /* clear EP 2 in toggle */

	TOGCTL = 0x02;
	TOGCTL = 0x22;    /* clear EP 2 out toggle */
#endif
	OUT2BC = 0;

	fill_intr();

	errmsg = (xdata short *)"all ok";
	errcode = 0x20;

	return;
	
err:
	for (;;);
}
