]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blob - gpif-acquisition.c
Add Hantek PSO2020 firmware support
[sigrok-firmware-fx2lafw.git] / gpif-acquisition.c
1 /*
2  * This file is part of the sigrok-firmware-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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <eputils.h>
22 #include <fx2regs.h>
23 #include <fx2macros.h>
24 #include <delay.h>
25 #include <gpif.h>
26 #include <fx2lafw.h>
27 #include <gpif-acquisition.h>
28
29 __bit gpif_acquiring;
30
31 static void gpif_reset_waveforms(void)
32 {
33         int i;
34
35         /* Reset WAVEDATA. */
36         AUTOPTRSETUP = 0x03;
37         AUTOPTRH1 = 0xe4;
38         AUTOPTRL1 = 0x00;
39         for (i = 0; i < 128; i++)
40                 EXTAUTODAT1 = 0;
41 }
42
43 static void gpif_setup_registers(void)
44 {
45         /* TODO. Value probably irrelevant, as we don't use RDY* signals? */
46         GPIFREADYCFG = 0;
47
48         /* Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs. */
49         GPIFCTLCFG = 0;
50
51         /* When GPIF is idle, tri-state the data bus. */
52         /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */
53         GPIFIDLECS = (0 << 0);
54
55         /* When GPIF is idle, set CTL0-CTL5 to 0. */
56         GPIFIDLECTL = 0;
57
58         /*
59          * Map index 0 in WAVEDATA to FIFORD. The rest is assigned too,
60          * but not used by us.
61          *
62          * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index,
63          *               [3:2] = FIFOWR index, [1:0] = FIFORD index
64          */
65         GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0);
66
67         /* Contains RDY* pin values. Read-only according to TRM. */
68         GPIFREADYSTAT = 0;
69
70         /* Make GPIF stop on transaction count not flag. */
71         EP2GPIFPFSTOP = (0 << 0);
72 }
73
74 static void gpif_init_addr_pins(void)
75 {
76         /*
77          * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of
78          * PORTC[7:0] and PORTE[7]), and output an initial address (zero).
79          * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E.
80          */
81         PORTCCFG = 0xff;    /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */
82         OEC = 0xff;         /* Configure PORTC[7:0] as outputs. */
83         PORTECFG |= 0x80;   /* Set PORTE[7] as alt. func. (GPIFADR[8]). */
84         OEE |= 0x80;        /* Configure PORTE[7] as output. */
85         SYNCDELAY();
86         GPIFADRL = 0x00;    /* Clear GPIFADR[7:0]. */
87         SYNCDELAY();
88         GPIFADRH = 0x00;    /* Clear GPIFADR[8]. */
89 }
90
91 static void gpif_init_flowstates(void)
92 {
93         /* Clear all flowstate registers, we don't use this functionality. */
94         FLOWSTATE = 0;
95         FLOWLOGIC = 0;
96         FLOWEQ0CTL = 0;
97         FLOWEQ1CTL = 0;
98         FLOWHOLDOFF = 0;
99         FLOWSTB = 0;
100         FLOWSTBEDGE = 0;
101         FLOWSTBHPERIOD = 0;
102 }
103
104 void gpif_init_la(void)
105 {
106         /*
107          * Setup the FX2 in GPIF master mode, using the internal clock
108          * (non-inverted) at 48MHz, and using async sampling.
109          */
110         IFCONFIG = 0xee;
111
112         /* Abort currently executing GPIF waveform (if any). */
113         GPIFABORT = 0xff;
114
115         /* Setup the GPIF registers. */
116         gpif_setup_registers();
117
118         /* Reset WAVEDATA. */
119         gpif_reset_waveforms();
120
121         /* Initialize GPIF address pins, output initial values. */
122         gpif_init_addr_pins();
123
124         /* Initialize flowstate registers (not used by us). */
125         gpif_init_flowstates();
126
127         /* Reset the status. */
128         gpif_acquiring = FALSE;
129 }
130
131 static void gpif_make_delay_state(volatile BYTE *pSTATE, uint8_t delay, uint8_t output)
132 {
133         /*
134          * DELAY
135          * Delay cmd->sample_delay clocks.
136          */
137         pSTATE[0] = delay;
138
139         /*
140          * OPCODE
141          * SGL=0, GIN=0, INCAD=0, NEXT=0, DATA=0, DP=0
142          */
143         pSTATE[8] = 0;
144
145         /*
146          * OUTPUT
147          * CTL[0:5]=output
148          */
149         pSTATE[16] = output;
150
151         /*
152          * LOGIC FUNCTION
153          * Not used.
154          */
155         pSTATE[24] = 0x00;
156 }
157
158 static void gpif_make_data_dp_state(volatile BYTE *pSTATE)
159 {
160         /*
161          * BRANCH
162          * Branch to IDLE if condition is true, back to S0 otherwise.
163          */
164         pSTATE[0] = (7 << 3) | (0 << 0);
165
166         /*
167          * OPCODE
168          * SGL=0, GIN=0, INCAD=0, NEXT=0, DATA=1, DP=1
169          */
170         pSTATE[8] = (1 << 1) | (1 << 0);
171
172         /*
173          * OUTPUT
174          * CTL[0:5]=0
175          */
176         pSTATE[16] = 0x00;
177
178         /*
179          * LOGIC FUNCTION
180          * Evaluate if the FIFO full flag is set.
181          * LFUNC=0 (AND), TERMA=6 (FIFO Flag), TERMB=6 (FIFO Flag)
182          */
183         pSTATE[24] = (6 << 3) | (6 << 0);
184 }
185
186 bool gpif_acquisition_start(const struct cmd_start_acquisition *cmd)
187 {
188         int i;
189         volatile BYTE *pSTATE = &GPIF_WAVE_DATA;
190
191         /* Ensure GPIF is idle before reconfiguration. */
192         while (!(GPIFTRIG & 0x80));
193
194         /* Configure the EP2 FIFO. */
195         if (cmd->flags & CMD_START_FLAGS_SAMPLE_16BIT)
196                 EP2FIFOCFG = bmAUTOIN | bmWORDWIDE;
197         else
198                 EP2FIFOCFG = bmAUTOIN;
199         SYNCDELAY();
200
201         /* Set IFCONFIG to the correct clock source. */
202         if (cmd->flags & CMD_START_FLAGS_CLK_48MHZ) {
203                 IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmASYNC |
204                            bmGSTATE | bmIFGPIF;
205         } else {
206                 IFCONFIG = bmIFCLKSRC | bmIFCLKOE | bmASYNC |
207                            bmGSTATE | bmIFGPIF;
208         }
209
210         /* Populate delay states. */
211         if ((cmd->sample_delay_h == 0 && cmd->sample_delay_l == 0) ||
212             cmd->sample_delay_h >= 6)
213                 return false;
214
215         if (cmd->flags & CMD_START_FLAGS_CLK_CTL2) {
216                 uint8_t delay_1, delay_2 = cmd->sample_delay_l;
217
218                 /* We need a pulse where the CTL1/2 pins alternate states. */
219                 if (cmd->sample_delay_h) {
220                         for (i = 0; i < cmd->sample_delay_h; i++)
221                                 gpif_make_delay_state(pSTATE++, 0, 0x06);
222                 } else {
223                         delay_1 = delay_2 / 2;
224                         delay_2 -= delay_1;
225                         gpif_make_delay_state(pSTATE++, delay_1, 0x06);
226                 }
227
228                 /* sample_delay_l is always != 0 for the supported rates. */
229                 gpif_make_delay_state(pSTATE++, delay_2, 0x00);
230         } else {
231                 for (i = 0; i < cmd->sample_delay_h; i++)
232                         gpif_make_delay_state(pSTATE++, 0, 0x00);
233
234                 if (cmd->sample_delay_l != 0)
235                         gpif_make_delay_state(pSTATE++, cmd->sample_delay_l, 0x00);
236         }
237
238         /* Populate S1 - the decision point. */
239         gpif_make_data_dp_state(pSTATE++);
240
241         /* Execute the whole GPIF waveform once. */
242         gpif_set_tc16(1);
243
244         /* Perform the initial GPIF read. */
245         gpif_fifo_read(GPIF_EP2);
246
247         /* Update the status. */
248         gpif_acquiring = TRUE;
249
250         return true;
251 }
252
253 void gpif_poll(void)
254 {
255         /* Detect if acquisition has completed. */
256         if (gpif_acquiring && (GPIFTRIG & 0x80)) {
257                 /* Activate NAK-ALL to avoid race conditions. */
258                 FIFORESET = 0x80;
259                 SYNCDELAY();
260
261                 /* Switch to manual mode. */
262                 EP2FIFOCFG = 0;
263                 SYNCDELAY();
264
265                 /* Reset EP2. */
266                 FIFORESET = 0x02;
267                 SYNCDELAY();
268
269                 /* Return to auto mode. */
270                 EP2FIFOCFG = bmAUTOIN;
271                 SYNCDELAY();
272
273                 /* Release NAK-ALL. */
274                 FIFORESET = 0x00;
275                 SYNCDELAY();
276
277                 gpif_acquiring = FALSE;
278         }
279 }