199 lines
5.1 KiB
C
199 lines
5.1 KiB
C
|
/**
|
||
|
* Copyright (C) 2009 Ubixum, Inc.
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2.1 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library 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
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with this library; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
**/
|
||
|
|
||
|
|
||
|
#include <fx2regs.h>
|
||
|
#include <fx2macros.h>
|
||
|
#include <delay.h>
|
||
|
|
||
|
#include <gpif.h>
|
||
|
|
||
|
#define SYNCDELAY SYNCDELAY4
|
||
|
|
||
|
void
|
||
|
gpif_init(BYTE * wavedata, BYTE * initdata)
|
||
|
{
|
||
|
|
||
|
BYTE i;
|
||
|
|
||
|
// 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
|
||
|
|
||
|
// 8051 doesn't have access to waveform memories 'til
|
||
|
// the part is in GPIF mode.
|
||
|
|
||
|
// IFCLKSRC=1 , FIFOs executes on internal clk source
|
||
|
// xMHz=1 , 48MHz internal clk rate
|
||
|
// IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz
|
||
|
// IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk
|
||
|
// ASYNC=1 , master samples asynchronous
|
||
|
// GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF
|
||
|
// IFCFG[1:0]=10, FX2 in GPIF master mode IFCONFIG
|
||
|
IFCONFIG &= ~0x03; // turn off IFCFG[1:0]
|
||
|
IFCONFIG |= 0x02; // set's IFCFG[1:0] to 10 to put in GPIF master mode.
|
||
|
|
||
|
|
||
|
GPIFABORT = 0xFF; // abort any waveforms pending
|
||
|
|
||
|
GPIFREADYCFG = initdata[0];
|
||
|
GPIFCTLCFG = initdata[1];
|
||
|
GPIFIDLECS = initdata[2];
|
||
|
GPIFIDLECTL = initdata[3];
|
||
|
GPIFWFSELECT = initdata[5];
|
||
|
GPIFREADYSTAT = initdata[6];
|
||
|
|
||
|
// use dual autopointer feature...
|
||
|
AUTOPTRSETUP = 0x07; // inc both pointers,
|
||
|
// ...warning: this introduces pdata hole(s)
|
||
|
// ...at E67B (XAUTODAT1) and E67C (XAUTODAT2)
|
||
|
|
||
|
// source
|
||
|
AUTOPTRH1 = MSB((WORD) wavedata);
|
||
|
AUTOPTRL1 = LSB((WORD) wavedata);
|
||
|
|
||
|
// destination
|
||
|
AUTOPTRH2 = 0xE4;
|
||
|
AUTOPTRL2 = 0x00;
|
||
|
|
||
|
// transfer
|
||
|
for (i = 0x00; i < 128; i++) {
|
||
|
EXTAUTODAT2 = EXTAUTODAT1;
|
||
|
}
|
||
|
|
||
|
// Configure GPIF Address pins, output initial value,
|
||
|
// these instructions don't do anything on the
|
||
|
// smaller chips (e.g., 56 pin model only has ports a,b,d)
|
||
|
PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0]
|
||
|
OEC = 0xFF; // and as outputs
|
||
|
PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8]
|
||
|
OEE |= 0x80; // and as output
|
||
|
|
||
|
// ...OR... tri-state GPIFADR[8:0] pins
|
||
|
// PORTCCFG = 0x00; // [7:0] as port I/O
|
||
|
// OEC = 0x00; // and as inputs
|
||
|
// PORTECFG &= 0x7F; // [8] as port I/O
|
||
|
// OEE &= 0x7F; // and as input
|
||
|
|
||
|
// GPIF address pins update when GPIFADRH/L written
|
||
|
SYNCDELAY; //
|
||
|
GPIFADRH = 0x00; // bits[7:1] always 0
|
||
|
SYNCDELAY; //
|
||
|
GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000
|
||
|
|
||
|
// set the initial flowstates to be all 0 in case flow states are not used
|
||
|
|
||
|
FLOWSTATE = 0;
|
||
|
FLOWLOGIC = 0;
|
||
|
FLOWEQ0CTL = 0;
|
||
|
FLOWEQ1CTL = 0;
|
||
|
FLOWHOLDOFF = 0;
|
||
|
FLOWSTB = 0;
|
||
|
FLOWSTBEDGE = 0;
|
||
|
FLOWSTBHPERIOD = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_setflowstate(BYTE * flowstates, BYTE bank)
|
||
|
{
|
||
|
BYTE base = 9 * bank;
|
||
|
FLOWSTATE = flowstates[base];
|
||
|
FLOWLOGIC = flowstates[base + 1];
|
||
|
FLOWEQ0CTL = flowstates[base + 2];
|
||
|
FLOWEQ1CTL = flowstates[base + 3];
|
||
|
FLOWHOLDOFF = flowstates[base + 4];
|
||
|
FLOWSTB = flowstates[base + 5];
|
||
|
FLOWSTBEDGE = flowstates[base + 6];
|
||
|
FLOWSTBHPERIOD = flowstates[base + 7];
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_set_tc32(DWORD tc)
|
||
|
{
|
||
|
GPIFTCB3 = MSB(MSW(tc));
|
||
|
SYNCDELAY;
|
||
|
GPIFTCB2 = LSB(MSW(tc));
|
||
|
SYNCDELAY;
|
||
|
GPIFTCB1 = MSB(LSW(tc));
|
||
|
SYNCDELAY;
|
||
|
GPIFTCB0 = LSB(LSW(tc));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_set_tc16(WORD tc)
|
||
|
{
|
||
|
GPIFTCB1 = MSB(tc);
|
||
|
SYNCDELAY;
|
||
|
GPIFTCB0 = LSB(tc);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
gpif_single_read16(WORD * res, WORD len)
|
||
|
{
|
||
|
BYTE c;
|
||
|
while (!(GPIFTRIG & 0x80)); // wait done
|
||
|
// dummy read to trigger real read
|
||
|
res[0] = XGPIFSGLDATLX;
|
||
|
for (c = 0; c < len; ++c) {
|
||
|
while (!(GPIFTRIG & 0x80)); // wait done
|
||
|
// real read
|
||
|
res[c] = GPIFSGLDATH << 8;
|
||
|
// whether or not to do another transfer is controlled by GPIFSGLDATLNOX or ..DATLX
|
||
|
res[c] |= c == len - 1 ? GPIFSGLDATLNOX : GPIFSGLDATLX;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_single_write16(WORD * dat, WORD len)
|
||
|
{
|
||
|
BYTE c;
|
||
|
for (c = 0; c < len; ++c) {
|
||
|
while (!(GPIFTRIG & 0x80));
|
||
|
XGPIFSGLDATH = MSB(dat[c]);
|
||
|
XGPIFSGLDATLX = LSB(dat[c]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_fifo_read(GPIF_EP_NUM ep_num)
|
||
|
{
|
||
|
while (!(GPIFTRIG & 0x80)); // wait until things are finished
|
||
|
GPIFTRIG = GPIFTRGRD | ep_num;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gpif_fifo_write(GPIF_EP_NUM ep_num)
|
||
|
{
|
||
|
while (!(GPIFTRIG & 0x80)); // wait until things are finished
|
||
|
GPIFTRIG = ep_num; // R/W=0, E[1:0] = ep_num
|
||
|
}
|