]>
Commit | Line | Data |
---|---|---|
1 | /** | |
2 | * Copyright (C) 2009 Ubixum, Inc. | |
3 | * | |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with this library; if not, write to the Free Software | |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | **/ | |
18 | ||
19 | ||
20 | #include <fx2regs.h> | |
21 | #include <fx2macros.h> | |
22 | #include <delay.h> | |
23 | ||
24 | #include <gpif.h> | |
25 | ||
26 | #define SYNCDELAY() SYNCDELAY4 | |
27 | ||
28 | void gpif_init( BYTE* wavedata, BYTE* initdata ) { | |
29 | ||
30 | BYTE i; | |
31 | ||
32 | // Registers which require a synchronization delay, see section 15.14 | |
33 | // FIFORESET FIFOPINPOLAR | |
34 | // INPKTEND OUTPKTEND | |
35 | // EPxBCH:L REVCTL | |
36 | // GPIFTCB3 GPIFTCB2 | |
37 | // GPIFTCB1 GPIFTCB0 | |
38 | // EPxFIFOPFH:L EPxAUTOINLENH:L | |
39 | // EPxFIFOCFG EPxGPIFFLGSEL | |
40 | // PINFLAGSxx EPxFIFOIRQ | |
41 | // EPxFIFOIE GPIFIRQ | |
42 | // GPIFIE GPIFADRH:L | |
43 | // UDMACRCH:L EPxGPIFTRIG | |
44 | // GPIFTRIG | |
45 | ||
46 | // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... | |
47 | // ...these have been replaced by GPIFTC[B3:B0] registers | |
48 | ||
49 | // 8051 doesn't have access to waveform memories 'til | |
50 | // the part is in GPIF mode. | |
51 | ||
52 | // IFCLKSRC=1 , FIFOs executes on internal clk source | |
53 | // xMHz=1 , 48MHz internal clk rate | |
54 | // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz | |
55 | // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk | |
56 | // ASYNC=1 , master samples asynchronous | |
57 | // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF | |
58 | // IFCFG[1:0]=10, FX2 in GPIF master mode IFCONFIG | |
59 | IFCONFIG &= ~0x03; // turn off IFCFG[1:0] | |
60 | IFCONFIG |= 0x02; // set's IFCFG[1:0] to 10 to put in GPIF master mode. | |
61 | ||
62 | ||
63 | GPIFABORT = 0xFF; // abort any waveforms pending | |
64 | ||
65 | GPIFREADYCFG = initdata[ 0 ]; | |
66 | GPIFCTLCFG = initdata[ 1 ]; | |
67 | GPIFIDLECS = initdata[ 2 ]; | |
68 | GPIFIDLECTL = initdata[ 3 ]; | |
69 | GPIFWFSELECT = initdata[ 5 ]; | |
70 | GPIFREADYSTAT = initdata[ 6 ]; | |
71 | ||
72 | // use dual autopointer feature... | |
73 | AUTOPTRSETUP = 0x07; // inc both pointers, | |
74 | // ...warning: this introduces pdata hole(s) | |
75 | // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) | |
76 | ||
77 | // source | |
78 | AUTOPTRH1 = MSB( (WORD)wavedata ); | |
79 | AUTOPTRL1 = LSB( (WORD)wavedata ); | |
80 | ||
81 | // destination | |
82 | AUTOPTRH2 = 0xE4; | |
83 | AUTOPTRL2 = 0x00; | |
84 | ||
85 | // transfer | |
86 | for ( i = 0x00; i < 128; i++ ) | |
87 | { | |
88 | EXTAUTODAT2 = EXTAUTODAT1; | |
89 | } | |
90 | ||
91 | // Configure GPIF Address pins, output initial value, | |
92 | // these instructions don't do anything on the | |
93 | // smaller chips (e.g., 56 pin model only has ports a,b,d) | |
94 | PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] | |
95 | OEC = 0xFF; // and as outputs | |
96 | PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] | |
97 | OEE |= 0x80; // and as output | |
98 | ||
99 | // ...OR... tri-state GPIFADR[8:0] pins | |
100 | // PORTCCFG = 0x00; // [7:0] as port I/O | |
101 | // OEC = 0x00; // and as inputs | |
102 | // PORTECFG &= 0x7F; // [8] as port I/O | |
103 | // OEE &= 0x7F; // and as input | |
104 | ||
105 | // GPIF address pins update when GPIFADRH/L written | |
106 | SYNCDELAY(); // | |
107 | GPIFADRH = 0x00; // bits[7:1] always 0 | |
108 | SYNCDELAY(); // | |
109 | GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 | |
110 | ||
111 | // set the initial flowstates to be all 0 in case flow states are not used | |
112 | ||
113 | FLOWSTATE = 0; | |
114 | FLOWLOGIC = 0; | |
115 | FLOWEQ0CTL = 0; | |
116 | FLOWEQ1CTL = 0; | |
117 | FLOWHOLDOFF = 0; | |
118 | FLOWSTB = 0; | |
119 | FLOWSTBEDGE = 0; | |
120 | FLOWSTBHPERIOD = 0; | |
121 | } | |
122 | ||
123 | void gpif_setflowstate( BYTE* flowstates, BYTE bank) { | |
124 | BYTE base = 9*bank; | |
125 | FLOWSTATE = flowstates[ base ]; | |
126 | FLOWLOGIC = flowstates[ base+1 ]; | |
127 | FLOWEQ0CTL = flowstates[ base+2 ]; | |
128 | FLOWEQ1CTL = flowstates[ base+3 ]; | |
129 | FLOWHOLDOFF = flowstates[ base+4 ]; | |
130 | FLOWSTB = flowstates[ base+5 ]; | |
131 | FLOWSTBEDGE = flowstates[ base+6 ]; | |
132 | FLOWSTBHPERIOD = flowstates[ base+7 ]; | |
133 | } | |
134 | ||
135 | void gpif_set_tc32(DWORD tc) { | |
136 | GPIFTCB3 = MSB(MSW(tc)); | |
137 | SYNCDELAY(); | |
138 | GPIFTCB2 = LSB(MSW(tc)); | |
139 | SYNCDELAY(); | |
140 | GPIFTCB1 = MSB(LSW(tc)); | |
141 | SYNCDELAY(); | |
142 | GPIFTCB0 = LSB(LSW(tc)); | |
143 | } | |
144 | void gpif_set_tc16(WORD tc) { | |
145 | GPIFTCB1= MSB(tc); | |
146 | SYNCDELAY(); | |
147 | GPIFTCB0= LSB(tc); | |
148 | } | |
149 | ||
150 | ||
151 | void gpif_single_read16( WORD* res, WORD len ){ | |
152 | BYTE c; | |
153 | while (!(GPIFTRIG & 0x80)); // wait done | |
154 | // dummy read to trigger real read | |
155 | res[0] = XGPIFSGLDATLX; | |
156 | for (c=0;c<len;++c) { | |
157 | while ( !(GPIFTRIG & 0x80) ); // wait done | |
158 | // real read | |
159 | res[c] = GPIFSGLDATH << 8; | |
160 | // whether or not to do another transfer is controlled by GPIFSGLDATLNOX or ..DATLX | |
161 | res[c] |= c==len-1 ? GPIFSGLDATLNOX : GPIFSGLDATLX ; | |
162 | } | |
163 | } | |
164 | ||
165 | void gpif_single_write16( WORD* dat, WORD len) { | |
166 | BYTE c; | |
167 | for (c=0;c<len;++c) { | |
168 | while (!(GPIFTRIG & 0x80) ); | |
169 | XGPIFSGLDATH = MSB(dat[c]); | |
170 | XGPIFSGLDATLX = LSB(dat[c]); | |
171 | } | |
172 | } | |
173 | ||
174 | void gpif_fifo_read ( GPIF_EP_NUM ep_num ) { | |
175 | while ( !(GPIFTRIG & 0x80 ) ); // wait until things are finished | |
176 | GPIFTRIG = GPIFTRGRD | ep_num; | |
177 | } | |
178 | ||
179 | void gpif_fifo_write ( GPIF_EP_NUM ep_num ) { | |
180 | while ( !(GPIFTRIG & 0x80) ); // wait until things are finished | |
181 | GPIFTRIG = ep_num; // R/W=0, E[1:0] = ep_num | |
182 | } |