]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blame - hantek_6022be.c
hantek_6022be.c: Drop unneeded debug code, random cruft.
[sigrok-firmware-fx2lafw.git] / hantek_6022be.c
CommitLineData
484b3aa0
UH
1/*
2 * This file is part of the sigrok-firmware-fx2lafw project.
3 *
4 * Copyright (C) 2009 Ubixum, Inc.
189db3d4
UH
5 * Copyright (C) 2015 Jochen Hoenicke
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
484b3aa0 20 */
189db3d4
UH
21
22#include <fx2macros.h>
23#include <fx2ints.h>
24#include <autovector.h>
25#include <delay.h>
26#include <setupdat.h>
27
484b3aa0
UH
28// change to support as many interfaces as you need
29BYTE altiface = 0; // alt interface
189db3d4
UH
30
31volatile WORD ledcounter = 0;
32
189db3d4
UH
33volatile __bit dosud=FALSE;
34volatile __bit dosuspend=FALSE;
35
189db3d4
UH
36extern void main_init();
37
38void main() {
39
40 SETCPUFREQ(CLK_12M); // save energy
41
42 main_init();
43
44 // set up interrupts.
45 USE_USB_INTS();
46
47 ENABLE_SUDAV();
48 ENABLE_USBRESET();
49 ENABLE_HISPEED();
50 ENABLE_SUSPEND();
51 ENABLE_RESUME();
52
53 EA=1;
54
55 // init timer2
56 RCAP2L = -500 & 0xff;
57 RCAP2H = (-500 >> 8) & 0xff;
58 T2CON = 0;
59 ET2 = 1;
60 TR2 = 1;
61
62// iic files (c2 load) don't need to renumerate/delay
63// trm 3.6
64#ifndef NORENUM
65 RENUMERATE();
66#else
67 USBCS &= ~bmDISCON;
68#endif
69
70 PORTCCFG = 0;
71 PORTACFG = 0;
72 OEC = 0xff;
73 OEA = 0x80;
74
75 while(TRUE) {
76
189db3d4
UH
77 if (dosud) {
78 dosud=FALSE;
79 handle_setupdata();
80 }
81
82 if (dosuspend) {
83 dosuspend=FALSE;
84 do {
189db3d4
UH
85 WAKEUPCS |= bmWU|bmWU2; // make sure ext wakeups are cleared
86 SUSPEND=1;
87 PCON |= 1;
88 __asm
89 nop
90 nop
91 nop
92 nop
93 nop
94 nop
95 nop
96 __endasm;
97 } while ( !remote_wakeup_allowed && REMOTE_WAKEUP());
189db3d4
UH
98
99 // resume
100 // trm 6.4
101 if ( REMOTE_WAKEUP() ) {
102 delay(5);
103 USBCS |= bmSIGRESUME;
104 delay(15);
105 USBCS &= ~bmSIGRESUME;
106 }
189db3d4 107 }
484b3aa0
UH
108 }
109}
189db3d4
UH
110
111void resume_isr() __interrupt RESUME_ISR {
112 CLEAR_RESUME();
113}
114
115void sudav_isr() __interrupt SUDAV_ISR {
116 dosud=TRUE;
117 CLEAR_SUDAV();
118}
119void usbreset_isr() __interrupt USBRESET_ISR {
120 handle_hispeed(FALSE);
121 CLEAR_USBRESET();
122}
123void hispeed_isr() __interrupt HISPEED_ISR {
124 handle_hispeed(TRUE);
125 CLEAR_HISPEED();
126}
127
128void suspend_isr() __interrupt SUSPEND_ISR {
129 dosuspend=TRUE;
130 CLEAR_SUSPEND();
131}
132
133void timer2_isr() __interrupt TF2_ISR {
134 PA7 = !PA7;
135 if (ledcounter) {
136 if (--ledcounter == 0) {
137 // clear LED
138 PC0 = 1;
139 PC1 = 1;
140 }
141 }
142 TF2 = 0;
143}
189db3d4
UH
144
145/* This sets three bits for each channel, one channel at a time.
146 * For channel 0 we want to set bits 5, 6 & 7
147 * For channel 1 we want to set bits 2, 3 & 4
148 *
149 * We convert the input values that are strange due to original firmware code into the value of the three bits as follows:
150 * val -> bits
151 * 1 -> 010b
152 * 2 -> 001b
153 * 5 -> 000b
154 * 10 -> 011b
155 *
156 * The third bit is always zero since there are only four outputs connected in the serial selector chip.
157 *
158 * The multiplication of the converted value by 0x24 sets the relevant bits in
159 * both channels and then we mask it out to only affect the channel currently
160 * requested.
161 */
162BOOL set_voltage(BYTE channel, BYTE val)
163{
164 BYTE bits, mask;
165 switch (val) {
166 case 1:
167 bits = 0x24 * 2;
168 break;
169 case 2:
170 bits = 0x24 * 1;
171 break;
172 case 5:
173 bits = 0x24 * 0;
174 break;
175 case 10:
176 bits = 0x24 * 3;
177 break;
178 default:
179 return FALSE;
180 }
181
182 mask = channel ? 0xe0 : 0x1c;
183 IOC = (IOC & ~mask) | (bits & mask);
184 return TRUE;
185}
186
187BOOL set_numchannels(BYTE numchannels)
188{
189 if (numchannels == 1 || numchannels == 2) {
190 BYTE fifocfg = 7 + numchannels;
191 EP2FIFOCFG = fifocfg;
192 EP6FIFOCFG = fifocfg;
193 return TRUE;
194 }
195 return FALSE;
196}
197
198void clear_fifo()
199{
200 GPIFABORT = 0xff;
201 SYNCDELAY3;
202 FIFORESET = 0x80;
203 SYNCDELAY3;
204 FIFORESET = 0x82;
205 SYNCDELAY3;
206 FIFORESET = 0x86;
207 SYNCDELAY3;
208 FIFORESET = 0;
209}
210
211void stop_sampling()
212{
213 GPIFABORT = 0xff;
214 SYNCDELAY3;
215 if (altiface == 0) {
216 INPKTEND = 6;
217 } else {
218 INPKTEND = 2;
219 }
220}
221
222void start_sampling()
223{
224 int i;
225 clear_fifo();
226
227 for (i = 0; i < 1000; i++);
228 while (!(GPIFTRIG & 0x80)) {
229 ;
230 }
231 SYNCDELAY3;
232 GPIFTCB1 = 0x28;
233 SYNCDELAY3;
234 GPIFTCB0 = 0;
235 if (altiface == 0)
236 GPIFTRIG = 6;
237 else
238 GPIFTRIG = 4;
239
240 // set green led
241 // don't clear led
242 ledcounter = 0;
243 PC0 = 1;
244 PC1 = 0;
245}
246
247extern __code BYTE highspd_dscr;
248extern __code BYTE fullspd_dscr;
249void select_interface(BYTE alt)
250{
251 const BYTE *pPacketSize = (USBCS & bmHSM ? &highspd_dscr : &fullspd_dscr)
252 + (9 + 16*alt + 9 + 4);
253 altiface = alt;
254 if (alt == 0) {
255 // bulk on port 6
256 EP2CFG = 0x00;
257 EP6CFG = 0xe0;
258 EP6GPIFFLGSEL = 1;
259
260 EP6AUTOINLENL = pPacketSize[0];
261 EP6AUTOINLENH = pPacketSize[1];
262 } else {
263 // iso on port 2
264 EP2CFG = 0xd8;
265 EP6CFG = 0x00;
266 EP2GPIFFLGSEL = 1;
267
268 EP2AUTOINLENL = pPacketSize[0];
269 EP2AUTOINLENH = pPacketSize[1] & 0x7;
270 EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1;
271 }
272}
273
274const struct samplerate_info {
275 BYTE rate;
276 BYTE wait0;
277 BYTE wait1;
278 BYTE opc0;
279 BYTE opc1;
280 BYTE out0;
281 BYTE ifcfg;
282} samplerates[] = {
283 { 48,0x80, 0, 3, 0, 0x00, 0xea },
284 { 30,0x80, 0, 3, 0, 0x00, 0xaa },
285 { 24, 1, 0, 2, 1, 0x40, 0xca },
286 { 16, 1, 1, 2, 0, 0x40, 0xca },
287 { 12, 2, 1, 2, 0, 0x40, 0xca },
288 { 8, 3, 2, 2, 0, 0x40, 0xca },
289 { 4, 6, 5, 2, 0, 0x40, 0xca },
290 { 2, 12, 11, 2, 0, 0x40, 0xca },
291 { 1, 24, 23, 2, 0, 0x40, 0xca },
292 { 50, 48, 47, 2, 0, 0x40, 0xca },
293 { 20, 120, 119, 2, 0, 0x40, 0xca },
294 { 10, 240, 239, 2, 0, 0x40, 0xca }
295};
296
297BOOL set_samplerate(BYTE rate)
298{
299 BYTE i = 0;
300 while (samplerates[i].rate != rate) {
301 i++;
302 if (i == sizeof(samplerates)/sizeof(samplerates[0]))
303 return FALSE;
304 }
305
306 IFCONFIG = samplerates[i].ifcfg;
307
308 AUTOPTRSETUP = 7;
309 AUTOPTRH2 = 0xE4;
310 AUTOPTRL2 = 0x00;
311
312 /* The program for low-speed, e.g. 1 MHz, is
313 * wait 24, CTL2=0, FIFO
314 * wait 23, CTL2=1
315 * jump 0, CTL2=1
316 *
317 * The program for 24 MHz is
318 * wait 1, CTL2=0, FIFO
319 * jump 0, CTL2=1
320 *
321 * The program for 30/48 MHz is:
322 * jump 0, CTL2=Z, FIFO, LOOP
323 */
324
325 EXTAUTODAT2 = samplerates[i].wait0;
326 EXTAUTODAT2 = samplerates[i].wait1;
327 EXTAUTODAT2 = 1;
328 EXTAUTODAT2 = 0;
329 EXTAUTODAT2 = 0;
330 EXTAUTODAT2 = 0;
331 EXTAUTODAT2 = 0;
332 EXTAUTODAT2 = 0;
333
334 EXTAUTODAT2 = samplerates[i].opc0;
335 EXTAUTODAT2 = samplerates[i].opc1;
336 EXTAUTODAT2 = 1;
337 EXTAUTODAT2 = 0;
338 EXTAUTODAT2 = 0;
339 EXTAUTODAT2 = 0;
340 EXTAUTODAT2 = 0;
341 EXTAUTODAT2 = 0;
342
343 EXTAUTODAT2 = samplerates[i].out0;
344 EXTAUTODAT2 = 0x44;
345 EXTAUTODAT2 = 0x44;
346 EXTAUTODAT2 = 0x00;
347 EXTAUTODAT2 = 0x00;
348 EXTAUTODAT2 = 0x00;
349 EXTAUTODAT2 = 0x00;
350 EXTAUTODAT2 = 0x00;
351
352 EXTAUTODAT2 = 0;
353 EXTAUTODAT2 = 0;
354 EXTAUTODAT2 = 0;
355 EXTAUTODAT2 = 0;
356 EXTAUTODAT2 = 0;
357 EXTAUTODAT2 = 0;
358 EXTAUTODAT2 = 0;
359 EXTAUTODAT2 = 0;
360
361 for (i = 0; i < 96; i++)
362 EXTAUTODAT2 = 0;
363 return TRUE;
364}
365
189db3d4
UH
366// set *alt_ifc to the current alt interface for ifc
367BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc) {
368 (void) ifc; // ignore unused parameter
369 *alt_ifc=altiface;
370 return TRUE;
371}
372// return TRUE if you set the interface requested
373// NOTE this function should reconfigure and reset the endpoints
374// according to the interface descriptors you provided.
375BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc) {
189db3d4
UH
376 if (ifc == 0) {
377 select_interface(alt_ifc);
378 }
379 return TRUE;
380}
381
382// handle getting and setting the configuration
383// 1 is the default. We don't support multiple configurations.
384BYTE handle_get_configuration() {
385 return 0;
386}
387
388BOOL handle_set_configuration(BYTE cfg) {
389 (void) cfg; // ignore unused parameter
390 return TRUE;
391}
392
189db3d4
UH
393BOOL handle_vendorcommand(BYTE cmd) {
394 stop_sampling();
395 // Set Red LED
396 PC0 = 0;
397 PC1 = 1;
398 ledcounter = 1000;
399 switch (cmd) {
400 case 0xe0:
401 case 0xe1:
402 EP0BCH=0;
403 EP0BCL=0;
404 while (EP0CS & bmEPBUSY);
405 set_voltage(cmd - 0xe0, EP0BUF[0]);
406 return TRUE;
407 case 0xe2:
408 EP0BCH=0;
409 EP0BCL=0;
410 while (EP0CS & bmEPBUSY);
411 set_samplerate(EP0BUF[0]);
412 return TRUE;
413 case 0xe3:
414 EP0BCH=0;
415 EP0BCL=0;
416 while (EP0CS & bmEPBUSY);
417 if (EP0BUF[0] == 1)
418 start_sampling();
419 return TRUE;
420 case 0xe4:
421 EP0BCH=0;
422 EP0BCL=0;
423 while (EP0CS & bmEPBUSY);
424 set_numchannels(EP0BUF[0]);
425 return TRUE;
426 }
427 return FALSE; // not handled by handlers
428}
429
189db3d4
UH
430void main_init() {
431 EP4CFG = 0;
432 EP8CFG = 0;
433
434 // in idle mode tristate all outputs
435 GPIFIDLECTL = 0x00;
436 GPIFCTLCFG = 0x80;
437 GPIFWFSELECT = 0x00;
438 GPIFREADYSTAT = 0x00;
439
440 stop_sampling();
441 set_voltage(0, 1);
442 set_voltage(1, 1);
443 set_samplerate(1);
444 set_numchannels(2);
445 select_interface(0);
189db3d4 446}