]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blob - hantek_6022be.c
hantek_6022be.c: Drop unneeded debug code, random cruft.
[sigrok-firmware-fx2lafw.git] / hantek_6022be.c
1 /*
2  * This file is part of the sigrok-firmware-fx2lafw project.
3  *
4  * Copyright (C) 2009 Ubixum, Inc.
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
20  */
21
22 #include <fx2macros.h>
23 #include <fx2ints.h>
24 #include <autovector.h>
25 #include <delay.h>
26 #include <setupdat.h>
27
28 // change to support as many interfaces as you need
29 BYTE altiface = 0; // alt interface
30
31 volatile WORD ledcounter = 0;
32
33 volatile __bit dosud=FALSE;
34 volatile __bit dosuspend=FALSE;
35
36 extern void main_init();
37
38 void 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
77      if (dosud) {
78        dosud=FALSE;
79        handle_setupdata();
80      }
81
82      if (dosuspend) {
83         dosuspend=FALSE;
84         do {
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()); 
98
99         // resume
100         // trm 6.4
101         if ( REMOTE_WAKEUP() ) {
102             delay(5);
103             USBCS |= bmSIGRESUME;
104             delay(15);
105             USBCS &= ~bmSIGRESUME;
106         }
107      }
108  }
109 }
110
111 void resume_isr() __interrupt RESUME_ISR {
112  CLEAR_RESUME();
113 }
114   
115 void sudav_isr() __interrupt SUDAV_ISR {
116  dosud=TRUE;
117  CLEAR_SUDAV();
118 }
119 void usbreset_isr() __interrupt USBRESET_ISR {
120  handle_hispeed(FALSE);
121  CLEAR_USBRESET();
122 }
123 void hispeed_isr() __interrupt HISPEED_ISR {
124  handle_hispeed(TRUE);
125  CLEAR_HISPEED();
126 }
127
128 void suspend_isr() __interrupt SUSPEND_ISR {
129  dosuspend=TRUE;
130  CLEAR_SUSPEND();
131 }
132
133 void 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 }
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  */
162 BOOL 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
187 BOOL 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
198 void 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
211 void stop_sampling()
212 {
213     GPIFABORT = 0xff;
214     SYNCDELAY3;
215     if (altiface == 0) {
216         INPKTEND = 6;
217     } else {
218         INPKTEND = 2;
219     }
220 }
221
222 void 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
247 extern __code BYTE highspd_dscr;
248 extern __code BYTE fullspd_dscr;
249 void 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
274 const 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
297 BOOL 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
366 // set *alt_ifc to the current alt interface for ifc
367 BOOL 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.
375 BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc) {  
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.
384 BYTE handle_get_configuration() { 
385     return 0;
386 }
387
388 BOOL handle_set_configuration(BYTE cfg) { 
389     (void) cfg; // ignore unused parameter
390     return TRUE;
391 }
392
393 BOOL 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
430 void 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);
446 }