]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blame - gpif-acquisition.c
Moved gpif code out to separate source file
[sigrok-firmware-fx2lafw.git] / gpif-acquisition.c
CommitLineData
e41576ec
JH
1/*
2 * This file is part of the fx2lafw project.
3 *
4 * Copyright (C) 2011-2012 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <fx2regs.h>
23#include <fx2macros.h>
24#include <delay.h>
25#include <gpif.h>
26
27#include <fx2lafw.h>
28#include <gpif-acquisition.h>
29
30/* GPIF terminology: DP = decision point, NDP = non-decision-point */
31
32/*
33 * GPIF waveforms.
34 *
35 * See section "10.3.4 State Instructions" in the TRM for details.
36 */
37static const BYTE wavedata[128] = {
38 /* Waveform 0: */
39
40 /*
41 * This is the basic algorithm implemented in our GPIF state machine:
42 *
43 * State 0: NDP: Sample the FIFO data bus.
44 * State 1: DP: If EP2 is full, go to state 7 (the IDLE state), i.e.,
45 * end the current waveform. Otherwise, go to state 0 again,
46 * i.e., sample data until EP2 is full.
47 * State 2: Unused.
48 * State 3: Unused.
49 * State 4: Unused.
50 * State 5: Unused.
51 * State 6: Unused.
52 */
53
54 /* S0-S6: LENGTH/BRANCH */
55 /*
56 * For NDPs (LENGTH): Number of IFCLK cycles to stay in this state.
57 * For DPs (BRANCH): [7] ReExec, [5:3]: BRANCHON1, [2:0]: BRANCHON0.
58 *
59 * 0x01: Stay one IFCLK cycle in this state.
60 * 0x38: No Re-execution, BRANCHON1 = state 7, BRANCHON0 = state 0.
61 */
62 // 0x01, 0x38, 0x01, 0x01, 0x01, 0x01, 0x01,
63 // FIXME: For now just loop over the "sample data" state forever.
64 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
65 /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */
66 0x07,
67
68 /* S0-S6: OPCODE */
69 /*
70 * 0x02: NDP, sample the FIFO data bus.
71 * 0x01: DP, don't sample the FIFO data bus.
72 */
73 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
74 /* Reserved */
75 0x00,
76
77 /* S0-S6: OUTPUT */
78 /* Unused, we don't output anything, we only sample the pins. */
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 /* Reserved */
81 0x00,
82
83 /* S0-S6: LOGIC FUNCTION (not used for NDPs) */
84 /*
85 * 0x36: LFUNC = "A AND B", A = FIFO flag, B = FIFO flag.
86 * The FIFO flag (FF == full flag, in our case) is configured via
87 * EP2GPIFFLGSEL.
88 *
89 * So: If the EP2 FIFO is full and the EP2 FIFO is full, go to
90 * the state specified by BRANCHON1 (state 7), otherwise BRANCHON0
91 * (state 0). See the LENGTH/BRANCH value above for details.
92 */
93 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
94 /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */
95 0x3f,
96
97 /* TODO: Must unused waveforms be "valid"? */
98
99 /* Waveform 1 (unused): */
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104
105 /* Waveform 2 (unused): */
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110
111 /* Waveform 3 (unused): */
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116};
117
118static void gpif_setup_registers(void)
119{
120 /* TODO. Value probably irrelevant, as we don't use RDY* signals? */
121 GPIFREADYCFG = 0;
122
123 /*
124 * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs.
125 * TODO: Probably irrelevant, as we don't use CTL0-CTL5?
126 */
127 GPIFCTLCFG = 0;
128
129 /* When GPIF is idle, tri-state the data bus. */
130 /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */
131 GPIFIDLECS = (1 << 0);
132
133 /* When GPIF is idle, set CTL0-CTL5 to 0. */
134 GPIFIDLECTL = 0;
135
136 /*
137 * Map index 0 in wavedata[] to FIFORD. The rest is assigned too,
138 * but not used by us.
139 *
140 * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index,
141 * [3:2] = FIFOWR index, [1:0] = FIFORD index
142 */
143 GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0);
144
145 /* Contains RDY* pin values. Read-only according to TRM. */
146 GPIFREADYSTAT = 0;
147}
148
149static void gpif_write_waveforms(void)
150{
151 int i;
152
153 /*
154 * Write the four waveforms into the respective WAVEDATA register
155 * locations (0xe400 - 0xe47f) using the FX2's autopointer feature.
156 */
157 AUTOPTRSETUP = 0x07; /* Increment autopointers 1 & 2. */
158 AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */
159 AUTOPTRL1 = LSB((WORD)wavedata);
160 AUTOPTRH2 = 0xe4; /* Dest is WAVEDATA (0xe400). */
161 AUTOPTRL2 = 0x00;
162 for (i = 0; i < 128; i++)
163 EXTAUTODAT2 = EXTAUTODAT1;
164}
165
166static void gpif_init_addr_pins(void)
167{
168 /*
169 * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of
170 * PORTC[7:0] and PORTE[7]), and output an initial address (zero).
171 * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E.
172 */
173 PORTCCFG = 0xff; /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */
174 OEC = 0xff; /* Configure PORTC[7:0] as outputs. */
175 PORTECFG |= 0x80; /* Set PORTE[7] as alt. func. (GPIFADR[8]). */
176 OEE |= 0x80; /* Configure PORTE[7] as output. */
177 SYNCDELAY();
178 GPIFADRL = 0x00; /* Clear GPIFADR[7:0]. */
179 SYNCDELAY();
180 GPIFADRH = 0x00; /* Clear GPIFADR[8]. */
181}
182
183static void gpif_init_flowstates(void)
184{
185 /* Clear all flowstate registers, we don't use this functionality. */
186 FLOWSTATE = 0;
187 FLOWLOGIC = 0;
188 FLOWEQ0CTL = 0;
189 FLOWEQ1CTL = 0;
190 FLOWHOLDOFF = 0;
191 FLOWSTB = 0;
192 FLOWSTBEDGE = 0;
193 FLOWSTBHPERIOD = 0;
194}
195
196void gpif_init_la(void)
197{
198 /*
199 * Setup the FX2 in GPIF master mode, using the internal clock
200 * (non-inverted) at 48MHz, and using async sampling.
201 */
202 IFCONFIG = 0xee;
203
204 /* Abort currently executing GPIF waveform (if any). */
205 GPIFABORT = 0xff;
206
207 /* Setup the GPIF registers. */
208 gpif_setup_registers();
209
210 /* Write the four GPIF waveforms into the WAVEDATA register. */
211 gpif_write_waveforms();
212
213 /* Initialize GPIF address pins, output initial values. */
214 gpif_init_addr_pins();
215
216 /* Initialize flowstate registers (not used by us). */
217 gpif_init_flowstates();
218}
219
220void gpif_acquisition_start(void)
221{
222 /* Perform the initial GPIF read. */
223 gpif_fifo_read(GPIF_EP2);
224}