]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blame - sainsmart_dds120.c
hantek_6022be.c: Fix a code comment.
[sigrok-firmware-fx2lafw.git] / sainsmart_dds120.c
CommitLineData
ce1d0a86
BL
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
040a6eae 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
ce1d0a86
BL
19 */
20
21#include <fx2macros.h>
22#include <fx2ints.h>
23#include <autovector.h>
24#include <delay.h>
25#include <setupdat.h>
26
27/* Change to support as many interfaces as you need. */
28static BYTE altiface = 0;
29
30static volatile __bit dosud = FALSE;
31static volatile __bit dosuspend = FALSE;
32
33extern __code BYTE highspd_dscr;
34extern __code BYTE fullspd_dscr;
35
36void resume_isr(void) __interrupt RESUME_ISR
37{
38 CLEAR_RESUME();
39}
40
41void sudav_isr(void) __interrupt SUDAV_ISR
42{
43 dosud = TRUE;
44 CLEAR_SUDAV();
45}
46
47void usbreset_isr(void) __interrupt USBRESET_ISR
48{
49 handle_hispeed(FALSE);
50 CLEAR_USBRESET();
51}
52
53void hispeed_isr(void) __interrupt HISPEED_ISR
54{
55 handle_hispeed(TRUE);
56 CLEAR_HISPEED();
57}
58
59void suspend_isr(void) __interrupt SUSPEND_ISR
60{
61 dosuspend = TRUE;
62 CLEAR_SUSPEND();
63}
64
65void timer2_isr(void) __interrupt TF2_ISR
66{
67 /* Toggle the 1kHz pin, only accurate up to ca 8MHz */
68 IOE = IOE^0x04;
69 TF2 = 0;
70}
71
72/**
73 * The gain stage is 2 stage approach. -6dB and -20dB on the first stage (attentuator). The second stage is then doing the gain by 3 different resistor values switched into the feedback loop.
74 * #Channel 0:
75 * PC1=1; PC2=0; PC3= 0 -> Gain x0.1 = -20dB
76 * PC1=1; PC2=0; PC3= 1 -> Gain x0.2 = -14dB
77 * PC1=1; PC2=1; PC3= 0 -> Gain x0.4 = -8dB
78 * PC1=0; PC2=0; PC3= 0 -> Gain x0.5 = -6dB
79 * PC1=0; PC2=0; PC3= 1 -> Gain x1 = 0dB
80 * PC1=0; PC2=1; PC3= 0 -> Gain x2 = +6dB
81 * #Channel 1:
82 * PE1=1; PC4=0; PC5= 0 -> Gain x0.1 = -20dB
83 * PE1=1; PC4=0; PC5= 1 -> Gain x0.2 = -14dB
84 * PE1=1; PC4=1; PC5= 0 -> Gain x0.4 = -8dB
85 * PE1=0; PC4=0; PC5= 0 -> Gain x0.5 = -6dB
86 * PE1=0; PC4=0; PC5= 1 -> Gain x1 = 0dB
87 * PE1=0; PC4=1; PC5= 0 -> Gain x2 = +6dB
88 */
89static BOOL set_voltage(BYTE channel, BYTE val)
90{
91 BYTE bits_C, bit_E, mask_C, mask_E;
92
93 if (channel == 0) {
94 mask_C = 0x0E;
95 mask_E = 0x00;
96 bit_E = 0;
97 switch (val) {
98 case 1:
99 bits_C = 0x02;
100 break;
101 case 2:
102 bits_C = 0x06;
103 break;
104 case 5:
105 bits_C = 0x00;
106 break;
107 case 10:
108 bits_C = 0x04;
109 break;
110 case 20:
111 bits_C = 0x08;
112 break;
113 default:
114 return FALSE;
115 }
116 } else if (channel == 1) {
117 mask_C = 0x30;
118 mask_E = 0x02;
119 switch (val) {
120 case 1:
121 bits_C = 0x00;
122 bit_E = 0x02;
123 break;
124 case 2:
125 bits_C = 0x10;
126 bit_E = 0x02;
127 break;
128 case 5:
129 bits_C = 0x00;
130 bit_E = 0x00;
131 break;
132 case 10:
133 bits_C = 0x10;
134 bit_E = 0x00;
135 break;
136 case 20:
137 bits_C = 0x20;
138 bit_E = 0x00;
139 break;
140 default:
141 return FALSE;
142 }
143 } else {
144 return FALSE;
145 }
146 IOC = (IOC & ~mask_C) | (bits_C & mask_C);
147 IOE = (IOE & ~mask_E) | (bit_E & mask_E);
148
149 return TRUE;
150}
151
75ad0fa5
BL
152
153/**
154 * Each LSB in the nibble of the byte controls the coupling per channel.
155 *
156 * Setting PE3 disables AC coupling capacitor on CH0.
157 * Setting PE0 disables AC coupling capacitor on CH1.
158 */
159static void set_coupling(BYTE coupling_cfg)
160{
161 if (coupling_cfg & 0x01)
162 IOE |= 0x08;
163 else
164 IOE &= ~0x08;
165
166 if (coupling_cfg & 0x10)
167 IOE |= 0x01;
168 else
169 IOE &= ~0x01;
170}
171
ce1d0a86
BL
172static BOOL set_numchannels(BYTE numchannels)
173{
174 if (numchannels == 1 || numchannels == 2) {
175 BYTE fifocfg = 7 + numchannels;
176 EP2FIFOCFG = fifocfg;
177 EP6FIFOCFG = fifocfg;
178 return TRUE;
179 }
180
181 return FALSE;
182}
183
184static void clear_fifo(void)
185{
186 GPIFABORT = 0xff;
187 SYNCDELAY3;
188 FIFORESET = 0x80;
189 SYNCDELAY3;
190 FIFORESET = 0x82;
191 SYNCDELAY3;
192 FIFORESET = 0x86;
193 SYNCDELAY3;
194 FIFORESET = 0;
195}
196
197static void stop_sampling(void)
198{
199 GPIFABORT = 0xff;
200 SYNCDELAY3;
201 INPKTEND = (altiface == 0) ? 6 : 2;
202}
203
204static void start_sampling(void)
205{
206 int i;
207
208 clear_fifo();
209
210 for (i = 0; i < 1000; i++);
211
212 while (!(GPIFTRIG & 0x80))
213 ;
214
215 SYNCDELAY3;
216 GPIFTCB1 = 0x28;
217 SYNCDELAY3;
218 GPIFTCB0 = 0;
219 GPIFTRIG = (altiface == 0) ? 6 : 4;
220
221}
222
223static void select_interface(BYTE alt)
224{
225 const BYTE *pPacketSize = \
226 ((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr)
227 + (9 + (16 * alt) + 9 + 4);
228
229 altiface = alt;
230
231 if (alt == 0) {
232 /* Bulk on EP6. */
233 EP2CFG = 0x00;
234 EP6CFG = 0xe0;
235 EP6GPIFFLGSEL = 1;
236 EP6AUTOINLENL = pPacketSize[0];
237 EP6AUTOINLENH = pPacketSize[1];
238 } else {
239 /* Iso on EP2. */
240 EP2CFG = 0xd8;
241 EP6CFG = 0x00;
242 EP2GPIFFLGSEL = 1;
243 EP2AUTOINLENL = pPacketSize[0];
244 EP2AUTOINLENH = pPacketSize[1] & 0x7;
245 EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1;
246 }
247}
248
249static const struct samplerate_info {
250 BYTE rate;
251 BYTE wait0;
252 BYTE wait1;
253 BYTE opc0;
254 BYTE opc1;
255 BYTE out0;
256 BYTE ifcfg;
257} samplerates[] = {
258 { 48, 0x80, 0, 3, 0, 0x00, 0xea },
259 { 30, 0x80, 0, 3, 0, 0x00, 0xaa },
260 { 24, 1, 0, 2, 1, 0x40, 0xea },
261 { 16, 1, 1, 2, 0, 0x40, 0xea },
33c275bb 262 { 15, 1, 0, 2, 1, 0x40, 0xaa },
ce1d0a86 263 { 12, 2, 1, 2, 0, 0x40, 0xea },
33c275bb 264 { 11, 1, 1, 2, 0, 0x40, 0xaa },
ce1d0a86 265 { 8, 3, 2, 2, 0, 0x40, 0xea },
33c275bb
BL
266 { 6, 2, 2, 2, 0, 0x40, 0xaa },
267 { 5, 3, 2, 2, 0, 0x40, 0xaa },
ce1d0a86 268 { 4, 6, 5, 2, 0, 0x40, 0xea },
33c275bb 269 { 3, 5, 4, 2, 0, 0x40, 0xaa },
ce1d0a86
BL
270 { 2, 12, 11, 2, 0, 0x40, 0xea },
271 { 1, 24, 23, 2, 0, 0x40, 0xea },
272 { 50, 48, 47, 2, 0, 0x40, 0xea },
273 { 20, 120, 119, 2, 0, 0x40, 0xea },
274 { 10, 240, 239, 2, 0, 0x40, 0xea },
275};
276
277static BOOL set_samplerate(BYTE rate)
278{
279 BYTE i = 0;
280
281 while (samplerates[i].rate != rate) {
282 i++;
283 if (i == sizeof(samplerates) / sizeof(samplerates[0]))
284 return FALSE;
285 }
286
287 IFCONFIG = samplerates[i].ifcfg;
288
289 AUTOPTRSETUP = 7;
24373950 290 AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */
ce1d0a86
BL
291 AUTOPTRL2 = 0x00;
292
293 /*
294 * The program for low-speed, e.g. 1 MHz, is:
295 * wait 24, CTL2=0, FIFO
296 * wait 23, CTL2=1
297 * jump 0, CTL2=1
298 *
299 * The program for 24 MHz is:
300 * wait 1, CTL2=0, FIFO
301 * jump 0, CTL2=1
302 *
303 * The program for 30/48 MHz is:
304 * jump 0, CTL2=Z, FIFO, LOOP
305 */
306
24373950 307 /* LENGTH / BRANCH 0-7 */
ce1d0a86
BL
308 EXTAUTODAT2 = samplerates[i].wait0;
309 EXTAUTODAT2 = samplerates[i].wait1;
310 EXTAUTODAT2 = 1;
311 EXTAUTODAT2 = 0;
312 EXTAUTODAT2 = 0;
313 EXTAUTODAT2 = 0;
314 EXTAUTODAT2 = 0;
315 EXTAUTODAT2 = 0;
316
24373950 317 /* OPCODE 0-7 */
ce1d0a86
BL
318 EXTAUTODAT2 = samplerates[i].opc0;
319 EXTAUTODAT2 = samplerates[i].opc1;
24373950 320 EXTAUTODAT2 = 1; /* DATA=0 DP=1 */
ce1d0a86
BL
321 EXTAUTODAT2 = 0;
322 EXTAUTODAT2 = 0;
323 EXTAUTODAT2 = 0;
324 EXTAUTODAT2 = 0;
325 EXTAUTODAT2 = 0;
326
24373950 327 /* OUTPUT 0-7 */
ce1d0a86 328 EXTAUTODAT2 = samplerates[i].out0;
24373950
UH
329 EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
330 EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
331 EXTAUTODAT2 = 0;
332 EXTAUTODAT2 = 0;
333 EXTAUTODAT2 = 0;
334 EXTAUTODAT2 = 0;
335 EXTAUTODAT2 = 0;
ce1d0a86 336
24373950 337 /* LOGIC FUNCTION 0-7 */
ce1d0a86
BL
338 EXTAUTODAT2 = 0;
339 EXTAUTODAT2 = 0;
340 EXTAUTODAT2 = 0;
341 EXTAUTODAT2 = 0;
342 EXTAUTODAT2 = 0;
343 EXTAUTODAT2 = 0;
344 EXTAUTODAT2 = 0;
345 EXTAUTODAT2 = 0;
346
347 for (i = 0; i < 96; i++)
348 EXTAUTODAT2 = 0;
349
350 return TRUE;
351}
352
a425fae9
BL
353static BOOL set_calibration_pulse(BYTE fs)
354{
355 switch (fs) {
356 case 0: // 100Hz
357 RCAP2L = -10000 & 0xff;
386296a7 358 RCAP2H = (-10000 & 0xff00) >> 8;
a425fae9
BL
359 return TRUE;
360 case 1: // 1kHz
361 RCAP2L = -1000 & 0xff;
386296a7 362 RCAP2H = (-1000 & 0xff00) >> 8;
a425fae9
BL
363 return TRUE;
364 case 10: // 1kHz
386296a7 365 RCAP2L = (BYTE)(-100 & 0xff);
a425fae9
BL
366 RCAP2H = 0xff;
367 return TRUE;
368 case 50: // 50kHz
386296a7 369 RCAP2L = (BYTE)(-20 & 0xff);
a425fae9
BL
370 RCAP2H = 0xff;
371 return TRUE;
372 default:
373 return FALSE;
374 }
375}
376
ce1d0a86
BL
377/* Set *alt_ifc to the current alt interface for ifc. */
378BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
379{
380 (void)ifc;
381
382 *alt_ifc = altiface;
383
384 return TRUE;
385}
386
387/*
388 * Return TRUE if you set the interface requested.
389 *
390 * Note: This function should reconfigure and reset the endpoints
391 * according to the interface descriptors you provided.
392 */
393BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc)
394{
395 if (ifc == 0)
396 select_interface(alt_ifc);
397
398 return TRUE;
399}
400
401BYTE handle_get_configuration(void)
402{
403 /* We only support configuration 0. */
404 return 0;
405}
406
407BOOL handle_set_configuration(BYTE cfg)
408{
409 /* We only support configuration 0. */
410 (void)cfg;
411
412 return TRUE;
413}
414
415BOOL handle_vendorcommand(BYTE cmd)
416{
417 stop_sampling();
418
419 /* Clear EP0BCH/L for each valid command. */
a425fae9 420 if (cmd >= 0xe0 && cmd <= 0xe6) {
ce1d0a86
BL
421 EP0BCH = 0;
422 EP0BCL = 0;
423 while (EP0CS & bmEPBUSY);
424 }
425
426 switch (cmd) {
427 case 0xe0:
428 case 0xe1:
429 set_voltage(cmd - 0xe0, EP0BUF[0]);
430 return TRUE;
431 case 0xe2:
432 set_samplerate(EP0BUF[0]);
433 return TRUE;
434 case 0xe3:
435 if (EP0BUF[0] == 1)
436 start_sampling();
437 return TRUE;
438 case 0xe4:
439 set_numchannels(EP0BUF[0]);
440 return TRUE;
75ad0fa5
BL
441 case 0xe5:
442 set_coupling(EP0BUF[0]);
443 return TRUE;
a425fae9
BL
444 case 0xe6:
445 set_calibration_pulse(EP0BUF[0]);
446 return TRUE;
ce1d0a86
BL
447 }
448
449 return FALSE; /* Not handled by handlers. */
450}
451
452static void init(void)
453{
454 EP4CFG = 0;
455 EP8CFG = 0;
456
457 /* In idle mode tristate all outputs. */
24373950
UH
458 GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */
459 GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */
ce1d0a86
BL
460 GPIFWFSELECT = 0x00;
461 GPIFREADYSTAT = 0x00;
462
463 stop_sampling();
464
465 set_voltage(0, 1);
466 set_voltage(1, 1);
467 set_samplerate(1);
468 set_numchannels(2);
469 select_interface(0);
470}
471
472static void main(void)
473{
474 /* Save energy. */
475 SETCPUFREQ(CLK_12M);
476
477 init();
478
479 /* Set up interrupts. */
480 USE_USB_INTS();
481
482 ENABLE_SUDAV();
483 ENABLE_USBRESET();
484 ENABLE_HISPEED();
485 ENABLE_SUSPEND();
486 ENABLE_RESUME();
487
488 /* Global (8051) interrupt enable. */
489 EA = 1;
490
491 /* Init timer2. */
492 RCAP2L = -1000 & 0xff;
386296a7 493 RCAP2H = (-1000 & 0xff00) >> 8;
ce1d0a86
BL
494 T2CON = 0;
495 ET2 = 1;
496 TR2 = 1;
497
498 RENUMERATE_UNCOND();
499
500 PORTCCFG = 0;
501 PORTACFG = 0;
502 PORTECFG = 0;
503 OEE = 0xFF;
504 OEC = 0xff;
505 OEA = 0x80;
506
507 PA7 = 1;
508
509 while (TRUE) {
510 if (dosud) {
511 dosud = FALSE;
512 handle_setupdata();
513 }
514
515 if (dosuspend) {
516 dosuspend = FALSE;
517 do {
518 /* Make sure ext wakeups are cleared. */
519 WAKEUPCS |= bmWU|bmWU2;
520 SUSPEND = 1;
521 PCON |= 1;
522 __asm
523 nop
524 nop
525 nop
526 nop
527 nop
528 nop
529 nop
530 __endasm;
531 } while (!remote_wakeup_allowed && REMOTE_WAKEUP());
532
533 /* Resume (TRM 6.4). */
534 if (REMOTE_WAKEUP()) {
535 delay(5);
536 USBCS |= bmSIGRESUME;
537 delay(15);
538 USBCS &= ~bmSIGRESUME;
539 }
540 }
541 }
542}