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