]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blob - hantek_6022be.c
README: Update to mention the Hantek 6022BE firmware.
[sigrok-firmware-fx2lafw.git] / hantek_6022be.c
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
33 volatile WORD ledcounter = 0;
34
35
36 volatile __bit dosud=FALSE;
37 volatile __bit dosuspend=FALSE;
38
39 // custom functions
40 extern void main_loop();
41 extern void main_init();
42
43 void 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
123 void resume_isr() __interrupt RESUME_ISR {
124  CLEAR_RESUME();
125 }
126   
127 void sudav_isr() __interrupt SUDAV_ISR {
128  dosud=TRUE;
129  CLEAR_SUDAV();
130 }
131 void usbreset_isr() __interrupt USBRESET_ISR {
132  handle_hispeed(FALSE);
133  CLEAR_USBRESET();
134 }
135 void hispeed_isr() __interrupt HISPEED_ISR {
136  handle_hispeed(TRUE);
137  CLEAR_HISPEED();
138 }
139
140 void suspend_isr() __interrupt SUSPEND_ISR {
141  dosuspend=TRUE;
142  CLEAR_SUSPEND();
143 }
144
145 void 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
185 BYTE altiface = 0; // alt interface
186 extern 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  */
207 BOOL 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
232 BOOL 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
243 void 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
256 void stop_sampling()
257 {
258     GPIFABORT = 0xff;
259     SYNCDELAY3;
260     if (altiface == 0) {
261         INPKTEND = 6;
262     } else {
263         INPKTEND = 2;
264     }
265 }
266
267 void 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
292 extern __code BYTE highspd_dscr;
293 extern __code BYTE fullspd_dscr;
294 void 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
319 const 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
342 BOOL 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
411 //************************** Configuration Handlers *****************************
412
413 // set *alt_ifc to the current alt interface for ifc
414 BOOL 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.
422 BOOL 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.
432 BYTE handle_get_configuration() { 
433     return 0;
434 }
435
436 BOOL handle_set_configuration(BYTE cfg) { 
437     (void) cfg; // ignore unused parameter
438     return TRUE;
439 }
440
441
442 //******************* VENDOR COMMAND HANDLERS **************************
443
444 BOOL 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
483 void 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
504 void main_loop() {
505 }
506
507