From: Uwe Hermann Date: Mon, 24 Apr 2017 12:47:26 +0000 (+0200) Subject: scopes: Unify code-base, remove duplicate code/files. X-Git-Tag: sigrok-firmware-fx2lafw-0.1.6~16 X-Git-Url: http://sigrok.org/gitweb/?p=sigrok-firmware-fx2lafw.git;a=commitdiff_plain;h=fd70a923c92d0f33d2b7ae4bf17339e2ff28454c scopes: Unify code-base, remove duplicate code/files. All currently supported scopes (and those that will be added in the future) now use the common include/scopes.inc firmware implementation. Only the device-specific code and #defines are moved to the respective subdirectory in hw/. The now-obsolete hantek_6022be.c, hantek_6022bl.c, and sainsmart_dds120.c files are removed. --- diff --git a/Makefile.am b/Makefile.am index b9190cd4..63967c33 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,35 +83,22 @@ fx2lafw_objects = \ fx2lafw.rel \ gpif-acquisition.rel -hantek_6022be_headers = \ +scope_headers = \ include/dscr_hantek_6022be.inc \ + include/scope.inc \ include/common.inc -hantek_6022be_sources = \ - hantek_6022be.c +hantek_6022be_headers = $(scope_headers) +hantek_6022be_sources = hw/hantek-6022be/fw.c +hantek_6022be_objects = hw/hantek-6022be/fw.rel -hantek_6022be_objects = \ - hantek_6022be.rel +hantek_6022bl_headers = $(scope_headers) +hantek_6022bl_sources = hw/hantek-6022bl/fw.c +hantek_6022bl_objects = hw/hantek-6022bl/fw.rel -hantek_6022bl_headers = \ - include/dscr_hantek_6022be.inc \ - include/common.inc - -hantek_6022bl_sources = \ - hantek_6022bl.c - -hantek_6022bl_objects = \ - hantek_6022bl.rel - -sainsmart_dds120_headers = \ - include/dscr_hantek_6022be.inc \ - include/common.inc - -sainsmart_dds120_sources = \ - sainsmart_dds120.c - -sainsmart_dds120_objects = \ - sainsmart_dds120.rel +sainsmart_dds120_headers = $(scope_headers) +sainsmart_dds120_sources = hw/sainsmart-dds120/fw.c +sainsmart_dds120_objects = hw/sainsmart-dds120/fw.rel fx2lib_headers = \ fx2lib/include/autovector.h \ diff --git a/hantek_6022be.c b/hantek_6022be.c deleted file mode 100644 index 69ba9586..00000000 --- a/hantek_6022be.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * This file is part of the sigrok-firmware-fx2lafw project. - * - * Copyright (C) 2009 Ubixum, Inc. - * Copyright (C) 2015 Jochen Hoenicke - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include -#include -#include -#include - -#define SET_ANALOG_MODE() - -#define SET_COUPLING(x) - -#define SET_CALIBRATION_PULSE(x) - -/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ -#define TOGGLE_CALIBRATION_PIN() PA7 = !PA7 - -#define LED_CLEAR() PC0 = 1; PC1 = 1; -#define LED_GREEN() PC0 = 1; PC1 = 0; -#define LED_RED() PC0 = 0; PC1 = 1; - -#define TIMER2_VAL 500 - -/* CTLx pin index (IFCLK, ADC clock input). */ -#define CTL_BIT 2 - -#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ -#define OE_CTL (((1 << CTL_BIT) << 4) | (1 << CTL_BIT)) /* OEx = CTLx = 1 */ - -/* Change to support as many interfaces as you need. */ -static BYTE altiface = 0; - -static volatile WORD ledcounter = 0; - -static volatile __bit dosud = FALSE; -static volatile __bit dosuspend = FALSE; - -extern __code BYTE highspd_dscr; -extern __code BYTE fullspd_dscr; - -void resume_isr(void) __interrupt RESUME_ISR -{ - CLEAR_RESUME(); -} - -void sudav_isr(void) __interrupt SUDAV_ISR -{ - dosud = TRUE; - CLEAR_SUDAV(); -} - -void usbreset_isr(void) __interrupt USBRESET_ISR -{ - handle_hispeed(FALSE); - CLEAR_USBRESET(); -} - -void hispeed_isr(void) __interrupt HISPEED_ISR -{ - handle_hispeed(TRUE); - CLEAR_HISPEED(); -} - -void suspend_isr(void) __interrupt SUSPEND_ISR -{ - dosuspend = TRUE; - CLEAR_SUSPEND(); -} - -void timer2_isr(void) __interrupt TF2_ISR -{ - TOGGLE_CALIBRATION_PIN(); - - if (ledcounter && (--ledcounter == 0)) - LED_CLEAR(); - - TF2 = 0; -} - -/* - * This sets three bits for each channel, one channel at a time. - * For channel 0 we want to set bits 5, 6 & 7 - * For channel 1 we want to set bits 2, 3 & 4 - * - * We convert the input values that are strange due to original - * firmware code into the value of the three bits as follows: - * - * val -> bits - * 1 -> 010b - * 2 -> 001b - * 5 -> 000b - * 10 -> 011b - * - * The third bit is always zero since there are only four outputs connected - * in the serial selector chip. - * - * The multiplication of the converted value by 0x24 sets the relevant bits in - * both channels and then we mask it out to only affect the channel currently - * requested. - */ -static BOOL set_voltage(BYTE channel, BYTE val) -{ - BYTE bits, mask; - - switch (val) { - case 1: - bits = 0x24 * 2; - break; - case 2: - bits = 0x24 * 1; - break; - case 5: - bits = 0x24 * 0; - break; - case 10: - bits = 0x24 * 3; - break; - default: - return FALSE; - } - - mask = (channel) ? 0xe0 : 0x1c; - IOC = (IOC & ~mask) | (bits & mask); - - return TRUE; -} - -/** - * Each LSB in the nibble of the byte controls the coupling per channel. - * - * Setting PE3 disables AC coupling capacitor on CH0. - * Setting PE0 disables AC coupling capacitor on CH1. - */ -static void set_coupling(BYTE coupling_cfg) -{ - if (coupling_cfg & 0x01) - IOE |= 0x08; - else - IOE &= ~0x08; - - if (coupling_cfg & 0x10) - IOE |= 0x01; - else - IOE &= ~0x01; -} - -static BOOL set_numchannels(BYTE numchannels) -{ - if (numchannels == 1 || numchannels == 2) { - BYTE fifocfg = 7 + numchannels; - EP2FIFOCFG = fifocfg; - EP6FIFOCFG = fifocfg; - return TRUE; - } - - return FALSE; -} - -static void clear_fifo(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - FIFORESET = 0x80; - SYNCDELAY3; - FIFORESET = 0x82; - SYNCDELAY3; - FIFORESET = 0x86; - SYNCDELAY3; - FIFORESET = 0; -} - -static void stop_sampling(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - INPKTEND = (altiface == 0) ? 6 : 2; -} - -static void start_sampling(void) -{ - int i; - - SET_ANALOG_MODE(); - - clear_fifo(); - - for (i = 0; i < 1000; i++); - - while (!(GPIFTRIG & 0x80)) - ; - - SYNCDELAY3; - GPIFTCB1 = 0x28; - SYNCDELAY3; - GPIFTCB0 = 0; - GPIFTRIG = (altiface == 0) ? 6 : 4; - - /* Set green LED, don't clear LED afterwards (ledcounter = 0). */ - LED_GREEN(); - ledcounter = 0; -} - -static void select_interface(BYTE alt) -{ - const BYTE *pPacketSize = \ - ((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr) - + (9 + (16 * alt) + 9 + 4); - - altiface = alt; - - if (alt == 0) { - /* Bulk on EP6. */ - EP2CFG = 0x00; - EP6CFG = 0xe0; - EP6GPIFFLGSEL = 1; - EP6AUTOINLENL = pPacketSize[0]; - EP6AUTOINLENH = pPacketSize[1]; - } else { - /* Iso on EP2. */ - EP2CFG = 0xd8; - EP6CFG = 0x00; - EP2GPIFFLGSEL = 1; - EP2AUTOINLENL = pPacketSize[0]; - EP2AUTOINLENH = pPacketSize[1] & 0x7; - EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1; - } -} - -static const struct samplerate_info { - BYTE rate; - BYTE wait0; - BYTE wait1; - BYTE opc0; - BYTE opc1; - BYTE out0; - BYTE ifcfg; -} samplerates[] = { - { 48, 0x80, 0, 3, 0, 0x00, 0xea }, - { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, - { 24, 1, 0, 2, 1, OUT0, 0xca }, - { 16, 1, 1, 2, 0, OUT0, 0xca }, - { 12, 2, 1, 2, 0, OUT0, 0xca }, - { 8, 3, 2, 2, 0, OUT0, 0xca }, - { 4, 6, 5, 2, 0, OUT0, 0xca }, - { 2, 12, 11, 2, 0, OUT0, 0xca }, - { 1, 24, 23, 2, 0, OUT0, 0xca }, - { 50, 48, 47, 2, 0, OUT0, 0xca }, - { 20, 120, 119, 2, 0, OUT0, 0xca }, - { 10, 240, 239, 2, 0, OUT0, 0xca }, -}; - -static BOOL set_samplerate(BYTE rate) -{ - BYTE i = 0; - - while (samplerates[i].rate != rate) { - i++; - if (i == sizeof(samplerates) / sizeof(samplerates[0])) - return FALSE; - } - - IFCONFIG = samplerates[i].ifcfg; - - AUTOPTRSETUP = 7; - AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */ - AUTOPTRL2 = 0x00; - - /* - * The program for low-speed, e.g. 1 MHz, is: - * wait 24, CTLx=0, FIFO - * wait 23, CTLx=1 - * jump 0, CTLx=1 - * - * The program for 24 MHz is: - * wait 1, CTLx=0, FIFO - * jump 0, CTLx=1 - * - * The program for 30/48 MHz is: - * jump 0, CTLx=Z, FIFO, LOOP - * - * (CTLx is device-dependent, could be e.g. CTL0 or CTL2.) - */ - - /* LENGTH / BRANCH 0-7 */ - EXTAUTODAT2 = samplerates[i].wait0; - EXTAUTODAT2 = samplerates[i].wait1; - EXTAUTODAT2 = 1; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OPCODE 0-7 */ - EXTAUTODAT2 = samplerates[i].opc0; - EXTAUTODAT2 = samplerates[i].opc1; - EXTAUTODAT2 = 1; /* DATA=0 DP=1 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OUTPUT 0-7 */ - EXTAUTODAT2 = samplerates[i].out0; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* LOGIC FUNCTION 0-7 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - for (i = 0; i < 96; i++) - EXTAUTODAT2 = 0; - - return TRUE; -} - -static BOOL set_calibration_pulse(BYTE fs) -{ - switch (fs) { - case 0: // 100Hz - RCAP2L = -10000 & 0xff; - RCAP2H = (-10000 & 0xff00) >> 8; - return TRUE; - case 1: // 1kHz - RCAP2L = -1000 & 0xff; - RCAP2H = (-1000 & 0xff00) >> 8; - return TRUE; - case 10: // 1kHz - RCAP2L = (BYTE)(-100 & 0xff); - RCAP2H = 0xff; - return TRUE; - case 50: // 50kHz - RCAP2L = (BYTE)(-20 & 0xff); - RCAP2H = 0xff; - return TRUE; - default: - return FALSE; - } -} - -/* Set *alt_ifc to the current alt interface for ifc. */ -BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc) -{ - (void)ifc; - - *alt_ifc = altiface; - - return TRUE; -} - -/* - * Return TRUE if you set the interface requested. - * - * Note: This function should reconfigure and reset the endpoints - * according to the interface descriptors you provided. - */ -BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc) -{ - if (ifc == 0) - select_interface(alt_ifc); - - return TRUE; -} - -BYTE handle_get_configuration(void) -{ - /* We only support configuration 0. */ - return 0; -} - -BOOL handle_set_configuration(BYTE cfg) -{ - /* We only support configuration 0. */ - (void)cfg; - - return TRUE; -} - -BOOL handle_vendorcommand(BYTE cmd) -{ - stop_sampling(); - - /* Set red LED, clear after timeout. */ - LED_RED(); - ledcounter = 1000; - - /* Clear EP0BCH/L for each valid command. */ - if (cmd >= 0xe0 && cmd <= 0xe6) { - EP0BCH = 0; - EP0BCL = 0; - while (EP0CS & bmEPBUSY); - } - - switch (cmd) { - case 0xe0: - case 0xe1: - set_voltage(cmd - 0xe0, EP0BUF[0]); - return TRUE; - case 0xe2: - set_samplerate(EP0BUF[0]); - return TRUE; - case 0xe3: - if (EP0BUF[0] == 1) - start_sampling(); - return TRUE; - case 0xe4: - set_numchannels(EP0BUF[0]); - return TRUE; - case 0xe5: - SET_COUPLING(EP0BUF[0]); - return TRUE; - case 0xe6: - SET_CALIBRATION_PULSE(EP0BUF[0]); - return TRUE; - } - - return FALSE; /* Not handled by handlers. */ -} - -static void init(void) -{ - EP4CFG = 0; - EP8CFG = 0; - - SET_ANALOG_MODE(); - - /* In idle mode tristate all outputs. */ - GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */ - GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */ - GPIFWFSELECT = 0x00; - GPIFREADYSTAT = 0x00; - - stop_sampling(); - - set_voltage(0, 1); - set_voltage(1, 1); - set_samplerate(1); - set_numchannels(2); - select_interface(0); -} - -static void main(void) -{ - /* Save energy. */ - SETCPUFREQ(CLK_12M); - - init(); - - /* Set up interrupts. */ - USE_USB_INTS(); - - ENABLE_SUDAV(); - ENABLE_USBRESET(); - ENABLE_HISPEED(); - ENABLE_SUSPEND(); - ENABLE_RESUME(); - - /* Global (8051) interrupt enable. */ - EA = 1; - - /* Init timer2. */ - RCAP2L = -TIMER2_VAL & 0xff; - RCAP2H = (-TIMER2_VAL & 0xff00) >> 8; - T2CON = 0; - ET2 = 1; - TR2 = 1; - - RENUMERATE_UNCOND(); - - PORTECFG = 0; - PORTCCFG = 0; - PORTACFG = 0; - OEE = 0xff; - OEC = 0xff; - OEA = 0xff; - - while (TRUE) { - if (dosud) { - dosud = FALSE; - handle_setupdata(); - } - - if (dosuspend) { - dosuspend = FALSE; - do { - /* Make sure ext wakeups are cleared. */ - WAKEUPCS |= bmWU | bmWU2; - SUSPEND = 1; - PCON |= 1; - __asm - nop - nop - nop - nop - nop - nop - nop - __endasm; - } while (!remote_wakeup_allowed && REMOTE_WAKEUP()); - - /* Resume (TRM 6.4). */ - if (REMOTE_WAKEUP()) { - delay(5); - USBCS |= bmSIGRESUME; - delay(15); - USBCS &= ~bmSIGRESUME; - } - } - } -} diff --git a/hantek_6022bl.c b/hantek_6022bl.c deleted file mode 100644 index aa16921a..00000000 --- a/hantek_6022bl.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * This file is part of the sigrok-firmware-fx2lafw project. - * - * Copyright (C) 2009 Ubixum, Inc. - * Copyright (C) 2015 Jochen Hoenicke - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include -#include -#include -#include - -#define SET_ANALOG_MODE() PA7 = 1 - -#define SET_COUPLING(x) - -#define SET_CALIBRATION_PULSE(x) - -/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ -#define TOGGLE_CALIBRATION_PIN() PC2 = !PC2 - -#define LED_CLEAR() PC0 = 1; PC1 = 1; -#define LED_GREEN() PC0 = 1; PC1 = 0; -#define LED_RED() PC0 = 0; PC1 = 1; - -#define TIMER2_VAL 500 - -/* CTLx pin index (IFCLK, ADC clock input). */ -#define CTL_BIT 0 - -#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ -#define OE_CTL (((1 << CTL_BIT) << 4) | (1 << CTL_BIT)) /* OEx = CTLx = 1 */ - -/* Change to support as many interfaces as you need. */ -static BYTE altiface = 0; - -static volatile WORD ledcounter = 0; - -static volatile __bit dosud = FALSE; -static volatile __bit dosuspend = FALSE; - -extern __code BYTE highspd_dscr; -extern __code BYTE fullspd_dscr; - -void resume_isr(void) __interrupt RESUME_ISR -{ - CLEAR_RESUME(); -} - -void sudav_isr(void) __interrupt SUDAV_ISR -{ - dosud = TRUE; - CLEAR_SUDAV(); -} - -void usbreset_isr(void) __interrupt USBRESET_ISR -{ - handle_hispeed(FALSE); - CLEAR_USBRESET(); -} - -void hispeed_isr(void) __interrupt HISPEED_ISR -{ - handle_hispeed(TRUE); - CLEAR_HISPEED(); -} - -void suspend_isr(void) __interrupt SUSPEND_ISR -{ - dosuspend = TRUE; - CLEAR_SUSPEND(); -} - -void timer2_isr(void) __interrupt TF2_ISR -{ - TOGGLE_CALIBRATION_PIN(); - - if (ledcounter && (--ledcounter == 0)) - LED_CLEAR(); - - TF2 = 0; -} - -/* - * This sets three bits for each channel, one channel at a time. - * For channel 0 we want to set bits 1, 2 & 3 - * For channel 1 we want to set bits 4, 5 & 6 - * - * We convert the input values that are strange due to original - * firmware code into the value of the three bits as follows: - * - * val -> bits - * 1 -> 010b - * 2 -> 001b - * 5 -> 000b - * 10 -> 011b - * - * The third bit is always zero since there are only four outputs connected - * in the serial selector chip. - * - * The multiplication of the converted value by 0x24 sets the relevant bits in - * both channels and then we mask it out to only affect the channel currently - * requested. - */ -static BOOL set_voltage(BYTE channel, BYTE val) -{ - BYTE bits, mask; - - switch (val) { - case 1: - bits = 0x02; - break; - case 2: - bits = 0x01; - break; - case 5: - bits = 0x00; - break; - case 10: - bits = 0x03; - break; - default: - return FALSE; - } - - bits = bits << (channel ? 1 : 4); - mask = (channel) ? 0x70 : 0x0e; - IOA = (IOA & ~mask) | (bits & mask); - - return TRUE; -} - -/** - * Each LSB in the nibble of the byte controls the coupling per channel. - * - * Setting PE3 disables AC coupling capacitor on CH0. - * Setting PE0 disables AC coupling capacitor on CH1. - */ -static void set_coupling(BYTE coupling_cfg) -{ - if (coupling_cfg & 0x01) - IOE |= 0x08; - else - IOE &= ~0x08; - - if (coupling_cfg & 0x10) - IOE |= 0x01; - else - IOE &= ~0x01; -} - -static BOOL set_numchannels(BYTE numchannels) -{ - if (numchannels == 1 || numchannels == 2) { - BYTE fifocfg = 7 + numchannels; - EP2FIFOCFG = fifocfg; - EP6FIFOCFG = fifocfg; - return TRUE; - } - - return FALSE; -} - -static void clear_fifo(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - FIFORESET = 0x80; - SYNCDELAY3; - FIFORESET = 0x82; - SYNCDELAY3; - FIFORESET = 0x86; - SYNCDELAY3; - FIFORESET = 0; -} - -static void stop_sampling(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - INPKTEND = (altiface == 0) ? 6 : 2; -} - -static void start_sampling(void) -{ - int i; - - SET_ANALOG_MODE(); - - clear_fifo(); - - for (i = 0; i < 1000; i++); - - while (!(GPIFTRIG & 0x80)) - ; - - SYNCDELAY3; - GPIFTCB1 = 0x28; - SYNCDELAY3; - GPIFTCB0 = 0; - GPIFTRIG = (altiface == 0) ? 6 : 4; - - /* Set green LED, don't clear LED afterwards (ledcounter = 0). */ - LED_GREEN(); - ledcounter = 0; -} - -static void select_interface(BYTE alt) -{ - const BYTE *pPacketSize = \ - ((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr) - + (9 + (16 * alt) + 9 + 4); - - altiface = alt; - - if (alt == 0) { - /* Bulk on EP6. */ - EP2CFG = 0x00; - EP6CFG = 0xe0; - EP6GPIFFLGSEL = 1; - EP6AUTOINLENL = pPacketSize[0]; - EP6AUTOINLENH = pPacketSize[1]; - } else { - /* Iso on EP2. */ - EP2CFG = 0xd8; - EP6CFG = 0x00; - EP2GPIFFLGSEL = 1; - EP2AUTOINLENL = pPacketSize[0]; - EP2AUTOINLENH = pPacketSize[1] & 0x7; - EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1; - } -} - -static const struct samplerate_info { - BYTE rate; - BYTE wait0; - BYTE wait1; - BYTE opc0; - BYTE opc1; - BYTE out0; - BYTE ifcfg; -} samplerates[] = { - { 48, 0x80, 0, 3, 0, 0x00, 0xea }, - { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, - { 24, 1, 0, 2, 1, OUT0, 0xca }, - { 16, 1, 1, 2, 0, OUT0, 0xca }, - { 12, 2, 1, 2, 0, OUT0, 0xca }, - { 8, 3, 2, 2, 0, OUT0, 0xca }, - { 4, 6, 5, 2, 0, OUT0, 0xca }, - { 2, 12, 11, 2, 0, OUT0, 0xca }, - { 1, 24, 23, 2, 0, OUT0, 0xca }, - { 50, 48, 47, 2, 0, OUT0, 0xca }, - { 20, 120, 119, 2, 0, OUT0, 0xca }, - { 10, 240, 239, 2, 0, OUT0, 0xca }, -}; - -static BOOL set_samplerate(BYTE rate) -{ - BYTE i = 0; - - while (samplerates[i].rate != rate) { - i++; - if (i == sizeof(samplerates) / sizeof(samplerates[0])) - return FALSE; - } - - IFCONFIG = samplerates[i].ifcfg; - - AUTOPTRSETUP = 7; - AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */ - AUTOPTRL2 = 0x00; - - /* - * The program for low-speed, e.g. 1 MHz, is: - * wait 24, CTLx=0, FIFO - * wait 23, CTLx=1 - * jump 0, CTLx=1 - * - * The program for 24 MHz is: - * wait 1, CTLx=0, FIFO - * jump 0, CTLx=1 - * - * The program for 30/48 MHz is: - * jump 0, CTLx=Z, FIFO, LOOP - * - * (CTLx is device-dependent, could be e.g. CTL0 or CTL2.) - */ - - /* LENGTH / BRANCH 0-7 */ - EXTAUTODAT2 = samplerates[i].wait0; - EXTAUTODAT2 = samplerates[i].wait1; - EXTAUTODAT2 = 1; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OPCODE 0-7 */ - EXTAUTODAT2 = samplerates[i].opc0; - EXTAUTODAT2 = samplerates[i].opc1; - EXTAUTODAT2 = 1; /* DATA=0 DP=1 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OUTPUT 0-7 */ - EXTAUTODAT2 = samplerates[i].out0; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* LOGIC FUNCTION 0-7 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - for (i = 0; i < 96; i++) - EXTAUTODAT2 = 0; - - return TRUE; -} - -static BOOL set_calibration_pulse(BYTE fs) -{ - switch (fs) { - case 0: // 100Hz - RCAP2L = -10000 & 0xff; - RCAP2H = (-10000 & 0xff00) >> 8; - return TRUE; - case 1: // 1kHz - RCAP2L = -1000 & 0xff; - RCAP2H = (-1000 & 0xff00) >> 8; - return TRUE; - case 10: // 1kHz - RCAP2L = (BYTE)(-100 & 0xff); - RCAP2H = 0xff; - return TRUE; - case 50: // 50kHz - RCAP2L = (BYTE)(-20 & 0xff); - RCAP2H = 0xff; - return TRUE; - default: - return FALSE; - } -} - -/* Set *alt_ifc to the current alt interface for ifc. */ -BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc) -{ - (void)ifc; - - *alt_ifc = altiface; - - return TRUE; -} - -/* - * Return TRUE if you set the interface requested. - * - * Note: This function should reconfigure and reset the endpoints - * according to the interface descriptors you provided. - */ -BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc) -{ - if (ifc == 0) - select_interface(alt_ifc); - - return TRUE; -} - -BYTE handle_get_configuration(void) -{ - /* We only support configuration 0. */ - return 0; -} - -BOOL handle_set_configuration(BYTE cfg) -{ - /* We only support configuration 0. */ - (void)cfg; - - return TRUE; -} - -BOOL handle_vendorcommand(BYTE cmd) -{ - stop_sampling(); - - /* Set red LED, clear after timeout. */ - LED_RED(); - ledcounter = 1000; - - /* Clear EP0BCH/L for each valid command. */ - if (cmd >= 0xe0 && cmd <= 0xe6) { - EP0BCH = 0; - EP0BCL = 0; - while (EP0CS & bmEPBUSY); - } - - switch (cmd) { - case 0xe0: - case 0xe1: - set_voltage(cmd - 0xe0, EP0BUF[0]); - return TRUE; - case 0xe2: - set_samplerate(EP0BUF[0]); - return TRUE; - case 0xe3: - if (EP0BUF[0] == 1) - start_sampling(); - return TRUE; - case 0xe4: - set_numchannels(EP0BUF[0]); - return TRUE; - case 0xe5: - SET_COUPLING(EP0BUF[0]); - return TRUE; - case 0xe6: - SET_CALIBRATION_PULSE(EP0BUF[0]); - return TRUE; - } - - return FALSE; /* Not handled by handlers. */ -} - -static void init(void) -{ - EP4CFG = 0; - EP8CFG = 0; - - SET_ANALOG_MODE(); - - /* In idle mode tristate all outputs. */ - GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */ - GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */ - GPIFWFSELECT = 0x00; - GPIFREADYSTAT = 0x00; - - stop_sampling(); - - set_voltage(0, 1); - set_voltage(1, 1); - set_samplerate(1); - set_numchannels(2); - select_interface(0); -} - -static void main(void) -{ - /* Save energy. */ - SETCPUFREQ(CLK_12M); - - init(); - - /* Set up interrupts. */ - USE_USB_INTS(); - - ENABLE_SUDAV(); - ENABLE_USBRESET(); - ENABLE_HISPEED(); - ENABLE_SUSPEND(); - ENABLE_RESUME(); - - /* Global (8051) interrupt enable. */ - EA = 1; - - /* Init timer2. */ - RCAP2L = -TIMER2_VAL & 0xff; - RCAP2H = (-TIMER2_VAL & 0xff00) >> 8; - T2CON = 0; - ET2 = 1; - TR2 = 1; - - RENUMERATE_UNCOND(); - - PORTECFG = 0; - PORTCCFG = 0; - PORTACFG = 0; - OEE = 0xff; - OEC = 0xff; - OEA = 0xff; - - while (TRUE) { - if (dosud) { - dosud = FALSE; - handle_setupdata(); - } - - if (dosuspend) { - dosuspend = FALSE; - do { - /* Make sure ext wakeups are cleared. */ - WAKEUPCS |= bmWU | bmWU2; - SUSPEND = 1; - PCON |= 1; - __asm - nop - nop - nop - nop - nop - nop - nop - __endasm; - } while (!remote_wakeup_allowed && REMOTE_WAKEUP()); - - /* Resume (TRM 6.4). */ - if (REMOTE_WAKEUP()) { - delay(5); - USBCS |= bmSIGRESUME; - delay(15); - USBCS &= ~bmSIGRESUME; - } - } - } -} diff --git a/hw/hantek-6022be/fw.c b/hw/hantek-6022be/fw.c new file mode 100644 index 00000000..341571a6 --- /dev/null +++ b/hw/hantek-6022be/fw.c @@ -0,0 +1,110 @@ +/* + * This file is part of the sigrok-firmware-fx2lafw project. + * + * Copyright (C) 2009 Ubixum, Inc. + * Copyright (C) 2015 Jochen Hoenicke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include + +#define SET_ANALOG_MODE() + +#define SET_COUPLING(x) + +#define SET_CALIBRATION_PULSE(x) + +/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ +#define TOGGLE_CALIBRATION_PIN() PA7 = !PA7 + +#define LED_CLEAR() PC0 = 1; PC1 = 1; +#define LED_GREEN() PC0 = 1; PC1 = 0; +#define LED_RED() PC0 = 0; PC1 = 1; + +#define TIMER2_VAL 500 + +/* CTLx pin index (IFCLK, ADC clock input). */ +#define CTL_BIT 2 + +#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ + +static const struct samplerate_info samplerates[] = { + { 48, 0x80, 0, 3, 0, 0x00, 0xea }, + { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, + { 24, 1, 0, 2, 1, OUT0, 0xca }, + { 16, 1, 1, 2, 0, OUT0, 0xca }, + { 12, 2, 1, 2, 0, OUT0, 0xca }, + { 8, 3, 2, 2, 0, OUT0, 0xca }, + { 4, 6, 5, 2, 0, OUT0, 0xca }, + { 2, 12, 11, 2, 0, OUT0, 0xca }, + { 1, 24, 23, 2, 0, OUT0, 0xca }, + { 50, 48, 47, 2, 0, OUT0, 0xca }, + { 20, 120, 119, 2, 0, OUT0, 0xca }, + { 10, 240, 239, 2, 0, OUT0, 0xca }, +}; + +/* + * This sets three bits for each channel, one channel at a time. + * For channel 0 we want to set bits 5, 6 & 7 + * For channel 1 we want to set bits 2, 3 & 4 + * + * We convert the input values that are strange due to original + * firmware code into the value of the three bits as follows: + * + * val -> bits + * 1 -> 010b + * 2 -> 001b + * 5 -> 000b + * 10 -> 011b + * + * The third bit is always zero since there are only four outputs connected + * in the serial selector chip. + * + * The multiplication of the converted value by 0x24 sets the relevant bits in + * both channels and then we mask it out to only affect the channel currently + * requested. + */ +static BOOL set_voltage(BYTE channel, BYTE val) +{ + BYTE bits, mask; + + switch (val) { + case 1: + bits = 0x24 * 2; + break; + case 2: + bits = 0x24 * 1; + break; + case 5: + bits = 0x24 * 0; + break; + case 10: + bits = 0x24 * 3; + break; + default: + return FALSE; + } + + mask = (channel) ? 0xe0 : 0x1c; + IOC = (IOC & ~mask) | (bits & mask); + + return TRUE; +} + +#include diff --git a/hw/hantek-6022bl/fw.c b/hw/hantek-6022bl/fw.c new file mode 100644 index 00000000..a78350ec --- /dev/null +++ b/hw/hantek-6022bl/fw.c @@ -0,0 +1,111 @@ +/* + * This file is part of the sigrok-firmware-fx2lafw project. + * + * Copyright (C) 2009 Ubixum, Inc. + * Copyright (C) 2015 Jochen Hoenicke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include + +#define SET_ANALOG_MODE() PA7 = 1 + +#define SET_COUPLING(x) + +#define SET_CALIBRATION_PULSE(x) + +/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ +#define TOGGLE_CALIBRATION_PIN() PC2 = !PC2 + +#define LED_CLEAR() PC0 = 1; PC1 = 1; +#define LED_GREEN() PC0 = 1; PC1 = 0; +#define LED_RED() PC0 = 0; PC1 = 1; + +#define TIMER2_VAL 500 + +/* CTLx pin index (IFCLK, ADC clock input). */ +#define CTL_BIT 0 + +#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ + +static const struct samplerate_info samplerates[] = { + { 48, 0x80, 0, 3, 0, 0x00, 0xea }, + { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, + { 24, 1, 0, 2, 1, OUT0, 0xca }, + { 16, 1, 1, 2, 0, OUT0, 0xca }, + { 12, 2, 1, 2, 0, OUT0, 0xca }, + { 8, 3, 2, 2, 0, OUT0, 0xca }, + { 4, 6, 5, 2, 0, OUT0, 0xca }, + { 2, 12, 11, 2, 0, OUT0, 0xca }, + { 1, 24, 23, 2, 0, OUT0, 0xca }, + { 50, 48, 47, 2, 0, OUT0, 0xca }, + { 20, 120, 119, 2, 0, OUT0, 0xca }, + { 10, 240, 239, 2, 0, OUT0, 0xca }, +}; + +/* + * This sets three bits for each channel, one channel at a time. + * For channel 0 we want to set bits 1, 2 & 3 + * For channel 1 we want to set bits 4, 5 & 6 + * + * We convert the input values that are strange due to original + * firmware code into the value of the three bits as follows: + * + * val -> bits + * 1 -> 010b + * 2 -> 001b + * 5 -> 000b + * 10 -> 011b + * + * The third bit is always zero since there are only four outputs connected + * in the serial selector chip. + * + * The multiplication of the converted value by 0x24 sets the relevant bits in + * both channels and then we mask it out to only affect the channel currently + * requested. + */ +static BOOL set_voltage(BYTE channel, BYTE val) +{ + BYTE bits, mask; + + switch (val) { + case 1: + bits = 0x02; + break; + case 2: + bits = 0x01; + break; + case 5: + bits = 0x00; + break; + case 10: + bits = 0x03; + break; + default: + return FALSE; + } + + bits = bits << (channel ? 1 : 4); + mask = (channel) ? 0x70 : 0x0e; + IOA = (IOA & ~mask) | (bits & mask); + + return TRUE; +} + +#include diff --git a/hw/sainsmart-dds120/fw.c b/hw/sainsmart-dds120/fw.c new file mode 100644 index 00000000..690eadf6 --- /dev/null +++ b/hw/sainsmart-dds120/fw.c @@ -0,0 +1,152 @@ +/* + * This file is part of the sigrok-firmware-fx2lafw project. + * + * Copyright (C) 2009 Ubixum, Inc. + * Copyright (C) 2015 Jochen Hoenicke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include + +#define SET_ANALOG_MODE() PA7 = 1 + +#define SET_COUPLING(x) set_coupling(x) + +#define SET_CALIBRATION_PULSE(x) set_calibration_pulse(x) + +/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ +/* Note: There's no PE2 as IOE is not bit-addressable (see TRM 15.2). */ +#define TOGGLE_CALIBRATION_PIN() IOE = IOE ^ 0x04 + +#define LED_CLEAR() NOP +#define LED_GREEN() NOP +#define LED_RED() NOP + +#define TIMER2_VAL 1000 + +/* CTLx pin index (IFCLK, ADC clock input). */ +#define CTL_BIT 2 + +#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ + +static const struct samplerate_info samplerates[] = { + { 48, 0x80, 0, 3, 0, 0x00, 0xea }, + { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, + { 24, 1, 0, 2, 1, OUT0, 0xea }, + { 16, 1, 1, 2, 0, OUT0, 0xea }, + { 15, 1, 0, 2, 1, OUT0, 0xaa }, + { 12, 2, 1, 2, 0, OUT0, 0xea }, + { 11, 1, 1, 2, 0, OUT0, 0xaa }, + { 8, 3, 2, 2, 0, OUT0, 0xea }, + { 6, 2, 2, 2, 0, OUT0, 0xaa }, + { 5, 3, 2, 2, 0, OUT0, 0xaa }, + { 4, 6, 5, 2, 0, OUT0, 0xea }, + { 3, 5, 4, 2, 0, OUT0, 0xaa }, + { 2, 12, 11, 2, 0, OUT0, 0xea }, + { 1, 24, 23, 2, 0, OUT0, 0xea }, + { 50, 48, 47, 2, 0, OUT0, 0xea }, + { 20, 120, 119, 2, 0, OUT0, 0xea }, + { 10, 240, 239, 2, 0, OUT0, 0xea }, +}; + +/** + * 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. + * + * #Channel 0: + * PC1=1; PC2=0; PC3=0 -> Gain x0.1 = -20dB + * PC1=1; PC2=0; PC3=1 -> Gain x0.2 = -14dB + * PC1=1; PC2=1; PC3=0 -> Gain x0.4 = -8dB + * PC1=0; PC2=0; PC3=0 -> Gain x0.5 = -6dB + * PC1=0; PC2=0; PC3=1 -> Gain x1 = 0dB + * PC1=0; PC2=1; PC3=0 -> Gain x2 = +6dB + * + * #Channel 1: + * PE1=1; PC4=0; PC5=0 -> Gain x0.1 = -20dB + * PE1=1; PC4=0; PC5=1 -> Gain x0.2 = -14dB + * PE1=1; PC4=1; PC5=0 -> Gain x0.4 = -8dB + * PE1=0; PC4=0; PC5=0 -> Gain x0.5 = -6dB + * PE1=0; PC4=0; PC5=1 -> Gain x1 = 0dB + * PE1=0; PC4=1; PC5=0 -> Gain x2 = +6dB + */ +static BOOL set_voltage(BYTE channel, BYTE val) +{ + BYTE bits_C, bit_E, mask_C, mask_E; + + if (channel == 0) { + mask_C = 0x0E; + mask_E = 0x00; + bit_E = 0; + switch (val) { + case 1: + bits_C = 0x02; + break; + case 2: + bits_C = 0x06; + break; + case 5: + bits_C = 0x00; + break; + case 10: + bits_C = 0x04; + break; + case 20: + bits_C = 0x08; + break; + default: + return FALSE; + } + } else if (channel == 1) { + mask_C = 0x30; + mask_E = 0x02; + switch (val) { + case 1: + bits_C = 0x00; + bit_E = 0x02; + break; + case 2: + bits_C = 0x10; + bit_E = 0x02; + break; + case 5: + bits_C = 0x00; + bit_E = 0x00; + break; + case 10: + bits_C = 0x10; + bit_E = 0x00; + break; + case 20: + bits_C = 0x20; + bit_E = 0x00; + break; + default: + return FALSE; + } + } else { + return FALSE; + } + IOC = (IOC & ~mask_C) | (bits_C & mask_C); + IOE = (IOE & ~mask_E) | (bit_E & mask_E); + + return TRUE; +} + +#include diff --git a/sainsmart_dds120.c b/sainsmart_dds120.c deleted file mode 100644 index cd2de1af..00000000 --- a/sainsmart_dds120.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * This file is part of the sigrok-firmware-fx2lafw project. - * - * Copyright (C) 2009 Ubixum, Inc. - * Copyright (C) 2015 Jochen Hoenicke - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include -#include -#include -#include - -#define SET_ANALOG_MODE() PA7 = 1 - -#define SET_COUPLING(x) set_coupling(x) - -#define SET_CALIBRATION_PULSE(x) set_calibration_pulse(x) - -/* Toggle the 1kHz calibration pin, only accurate up to ca. 8MHz. */ -/* Note: There's no PE2 as IOE is not bit-addressable (see TRM 15.2). */ -#define TOGGLE_CALIBRATION_PIN() IOE = IOE ^ 0x04 - -#define LED_CLEAR() NOP -#define LED_GREEN() NOP -#define LED_RED() NOP - -#define TIMER2_VAL 1000 - -/* CTLx pin index (IFCLK, ADC clock input). */ -#define CTL_BIT 2 - -#define OUT0 ((1 << CTL_BIT) << 4) /* OEx = 1, CTLx = 0 */ -#define OE_CTL (((1 << CTL_BIT) << 4) | (1 << CTL_BIT)) /* OEx = CTLx = 1 */ - -/* Change to support as many interfaces as you need. */ -static BYTE altiface = 0; - -static volatile WORD ledcounter = 0; - -static volatile __bit dosud = FALSE; -static volatile __bit dosuspend = FALSE; - -extern __code BYTE highspd_dscr; -extern __code BYTE fullspd_dscr; - -void resume_isr(void) __interrupt RESUME_ISR -{ - CLEAR_RESUME(); -} - -void sudav_isr(void) __interrupt SUDAV_ISR -{ - dosud = TRUE; - CLEAR_SUDAV(); -} - -void usbreset_isr(void) __interrupt USBRESET_ISR -{ - handle_hispeed(FALSE); - CLEAR_USBRESET(); -} - -void hispeed_isr(void) __interrupt HISPEED_ISR -{ - handle_hispeed(TRUE); - CLEAR_HISPEED(); -} - -void suspend_isr(void) __interrupt SUSPEND_ISR -{ - dosuspend = TRUE; - CLEAR_SUSPEND(); -} - -void timer2_isr(void) __interrupt TF2_ISR -{ - TOGGLE_CALIBRATION_PIN(); - - if (ledcounter && (--ledcounter == 0)) - LED_CLEAR(); - - TF2 = 0; -} - -/** - * 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. - * - * #Channel 0: - * PC1=1; PC2=0; PC3= 0 -> Gain x0.1 = -20dB - * PC1=1; PC2=0; PC3= 1 -> Gain x0.2 = -14dB - * PC1=1; PC2=1; PC3= 0 -> Gain x0.4 = -8dB - * PC1=0; PC2=0; PC3= 0 -> Gain x0.5 = -6dB - * PC1=0; PC2=0; PC3= 1 -> Gain x1 = 0dB - * PC1=0; PC2=1; PC3= 0 -> Gain x2 = +6dB - * - * #Channel 1: - * PE1=1; PC4=0; PC5= 0 -> Gain x0.1 = -20dB - * PE1=1; PC4=0; PC5= 1 -> Gain x0.2 = -14dB - * PE1=1; PC4=1; PC5= 0 -> Gain x0.4 = -8dB - * PE1=0; PC4=0; PC5= 0 -> Gain x0.5 = -6dB - * PE1=0; PC4=0; PC5= 1 -> Gain x1 = 0dB - * PE1=0; PC4=1; PC5= 0 -> Gain x2 = +6dB - */ -static BOOL set_voltage(BYTE channel, BYTE val) -{ - BYTE bits_C, bit_E, mask_C, mask_E; - - if (channel == 0) { - mask_C = 0x0E; - mask_E = 0x00; - bit_E = 0; - switch (val) { - case 1: - bits_C = 0x02; - break; - case 2: - bits_C = 0x06; - break; - case 5: - bits_C = 0x00; - break; - case 10: - bits_C = 0x04; - break; - case 20: - bits_C = 0x08; - break; - default: - return FALSE; - } - } else if (channel == 1) { - mask_C = 0x30; - mask_E = 0x02; - switch (val) { - case 1: - bits_C = 0x00; - bit_E = 0x02; - break; - case 2: - bits_C = 0x10; - bit_E = 0x02; - break; - case 5: - bits_C = 0x00; - bit_E = 0x00; - break; - case 10: - bits_C = 0x10; - bit_E = 0x00; - break; - case 20: - bits_C = 0x20; - bit_E = 0x00; - break; - default: - return FALSE; - } - } else { - return FALSE; - } - IOC = (IOC & ~mask_C) | (bits_C & mask_C); - IOE = (IOE & ~mask_E) | (bit_E & mask_E); - - return TRUE; -} - -/** - * Each LSB in the nibble of the byte controls the coupling per channel. - * - * Setting PE3 disables AC coupling capacitor on CH0. - * Setting PE0 disables AC coupling capacitor on CH1. - */ -static void set_coupling(BYTE coupling_cfg) -{ - if (coupling_cfg & 0x01) - IOE |= 0x08; - else - IOE &= ~0x08; - - if (coupling_cfg & 0x10) - IOE |= 0x01; - else - IOE &= ~0x01; -} - -static BOOL set_numchannels(BYTE numchannels) -{ - if (numchannels == 1 || numchannels == 2) { - BYTE fifocfg = 7 + numchannels; - EP2FIFOCFG = fifocfg; - EP6FIFOCFG = fifocfg; - return TRUE; - } - - return FALSE; -} - -static void clear_fifo(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - FIFORESET = 0x80; - SYNCDELAY3; - FIFORESET = 0x82; - SYNCDELAY3; - FIFORESET = 0x86; - SYNCDELAY3; - FIFORESET = 0; -} - -static void stop_sampling(void) -{ - GPIFABORT = 0xff; - SYNCDELAY3; - INPKTEND = (altiface == 0) ? 6 : 2; -} - -static void start_sampling(void) -{ - int i; - - SET_ANALOG_MODE(); - - clear_fifo(); - - for (i = 0; i < 1000; i++); - - while (!(GPIFTRIG & 0x80)) - ; - - SYNCDELAY3; - GPIFTCB1 = 0x28; - SYNCDELAY3; - GPIFTCB0 = 0; - GPIFTRIG = (altiface == 0) ? 6 : 4; - - /* Set green LED, don't clear LED afterwards (ledcounter = 0). */ - LED_GREEN(); - ledcounter = 0; -} - -static void select_interface(BYTE alt) -{ - const BYTE *pPacketSize = \ - ((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr) - + (9 + (16 * alt) + 9 + 4); - - altiface = alt; - - if (alt == 0) { - /* Bulk on EP6. */ - EP2CFG = 0x00; - EP6CFG = 0xe0; - EP6GPIFFLGSEL = 1; - EP6AUTOINLENL = pPacketSize[0]; - EP6AUTOINLENH = pPacketSize[1]; - } else { - /* Iso on EP2. */ - EP2CFG = 0xd8; - EP6CFG = 0x00; - EP2GPIFFLGSEL = 1; - EP2AUTOINLENL = pPacketSize[0]; - EP2AUTOINLENH = pPacketSize[1] & 0x7; - EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1; - } -} - -static const struct samplerate_info { - BYTE rate; - BYTE wait0; - BYTE wait1; - BYTE opc0; - BYTE opc1; - BYTE out0; - BYTE ifcfg; -} samplerates[] = { - { 48, 0x80, 0, 3, 0, 0x00, 0xea }, - { 30, 0x80, 0, 3, 0, 0x00, 0xaa }, - { 24, 1, 0, 2, 1, OUT0, 0xea }, - { 16, 1, 1, 2, 0, OUT0, 0xea }, - { 15, 1, 0, 2, 1, OUT0, 0xaa }, - { 12, 2, 1, 2, 0, OUT0, 0xea }, - { 11, 1, 1, 2, 0, OUT0, 0xaa }, - { 8, 3, 2, 2, 0, OUT0, 0xea }, - { 6, 2, 2, 2, 0, OUT0, 0xaa }, - { 5, 3, 2, 2, 0, OUT0, 0xaa }, - { 4, 6, 5, 2, 0, OUT0, 0xea }, - { 3, 5, 4, 2, 0, OUT0, 0xaa }, - { 2, 12, 11, 2, 0, OUT0, 0xea }, - { 1, 24, 23, 2, 0, OUT0, 0xea }, - { 50, 48, 47, 2, 0, OUT0, 0xea }, - { 20, 120, 119, 2, 0, OUT0, 0xea }, - { 10, 240, 239, 2, 0, OUT0, 0xea }, -}; - -static BOOL set_samplerate(BYTE rate) -{ - BYTE i = 0; - - while (samplerates[i].rate != rate) { - i++; - if (i == sizeof(samplerates) / sizeof(samplerates[0])) - return FALSE; - } - - IFCONFIG = samplerates[i].ifcfg; - - AUTOPTRSETUP = 7; - AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */ - AUTOPTRL2 = 0x00; - - /* - * The program for low-speed, e.g. 1 MHz, is: - * wait 24, CTLx=0, FIFO - * wait 23, CTLx=1 - * jump 0, CTLx=1 - * - * The program for 24 MHz is: - * wait 1, CTLx=0, FIFO - * jump 0, CTLx=1 - * - * The program for 30/48 MHz is: - * jump 0, CTLx=Z, FIFO, LOOP - * - * (CTLx is device-dependent, could be e.g. CTL0 or CTL2.) - */ - - /* LENGTH / BRANCH 0-7 */ - EXTAUTODAT2 = samplerates[i].wait0; - EXTAUTODAT2 = samplerates[i].wait1; - EXTAUTODAT2 = 1; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OPCODE 0-7 */ - EXTAUTODAT2 = samplerates[i].opc0; - EXTAUTODAT2 = samplerates[i].opc1; - EXTAUTODAT2 = 1; /* DATA=0 DP=1 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* OUTPUT 0-7 */ - EXTAUTODAT2 = samplerates[i].out0; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = OE_CTL; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - /* LOGIC FUNCTION 0-7 */ - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - EXTAUTODAT2 = 0; - - for (i = 0; i < 96; i++) - EXTAUTODAT2 = 0; - - return TRUE; -} - -static BOOL set_calibration_pulse(BYTE fs) -{ - switch (fs) { - case 0: // 100Hz - RCAP2L = -10000 & 0xff; - RCAP2H = (-10000 & 0xff00) >> 8; - return TRUE; - case 1: // 1kHz - RCAP2L = -1000 & 0xff; - RCAP2H = (-1000 & 0xff00) >> 8; - return TRUE; - case 10: // 1kHz - RCAP2L = (BYTE)(-100 & 0xff); - RCAP2H = 0xff; - return TRUE; - case 50: // 50kHz - RCAP2L = (BYTE)(-20 & 0xff); - RCAP2H = 0xff; - return TRUE; - default: - return FALSE; - } -} - -/* Set *alt_ifc to the current alt interface for ifc. */ -BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc) -{ - (void)ifc; - - *alt_ifc = altiface; - - return TRUE; -} - -/* - * Return TRUE if you set the interface requested. - * - * Note: This function should reconfigure and reset the endpoints - * according to the interface descriptors you provided. - */ -BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc) -{ - if (ifc == 0) - select_interface(alt_ifc); - - return TRUE; -} - -BYTE handle_get_configuration(void) -{ - /* We only support configuration 0. */ - return 0; -} - -BOOL handle_set_configuration(BYTE cfg) -{ - /* We only support configuration 0. */ - (void)cfg; - - return TRUE; -} - -BOOL handle_vendorcommand(BYTE cmd) -{ - stop_sampling(); - - /* Set red LED, clear after timeout. */ - LED_RED(); - ledcounter = 1000; - - /* Clear EP0BCH/L for each valid command. */ - if (cmd >= 0xe0 && cmd <= 0xe6) { - EP0BCH = 0; - EP0BCL = 0; - while (EP0CS & bmEPBUSY); - } - - switch (cmd) { - case 0xe0: - case 0xe1: - set_voltage(cmd - 0xe0, EP0BUF[0]); - return TRUE; - case 0xe2: - set_samplerate(EP0BUF[0]); - return TRUE; - case 0xe3: - if (EP0BUF[0] == 1) - start_sampling(); - return TRUE; - case 0xe4: - set_numchannels(EP0BUF[0]); - return TRUE; - case 0xe5: - SET_COUPLING(EP0BUF[0]); - return TRUE; - case 0xe6: - SET_CALIBRATION_PULSE(EP0BUF[0]); - return TRUE; - } - - return FALSE; /* Not handled by handlers. */ -} - -static void init(void) -{ - EP4CFG = 0; - EP8CFG = 0; - - SET_ANALOG_MODE(); - - /* In idle mode tristate all outputs. */ - GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */ - GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */ - GPIFWFSELECT = 0x00; - GPIFREADYSTAT = 0x00; - - stop_sampling(); - - set_voltage(0, 1); - set_voltage(1, 1); - set_samplerate(1); - set_numchannels(2); - select_interface(0); -} - -static void main(void) -{ - /* Save energy. */ - SETCPUFREQ(CLK_12M); - - init(); - - /* Set up interrupts. */ - USE_USB_INTS(); - - ENABLE_SUDAV(); - ENABLE_USBRESET(); - ENABLE_HISPEED(); - ENABLE_SUSPEND(); - ENABLE_RESUME(); - - /* Global (8051) interrupt enable. */ - EA = 1; - - /* Init timer2. */ - RCAP2L = -TIMER2_VAL & 0xff; - RCAP2H = (-TIMER2_VAL & 0xff00) >> 8; - T2CON = 0; - ET2 = 1; - TR2 = 1; - - RENUMERATE_UNCOND(); - - PORTECFG = 0; - PORTCCFG = 0; - PORTACFG = 0; - OEE = 0xff; - OEC = 0xff; - OEA = 0xff; - - SET_ANALOG_MODE(); - - while (TRUE) { - if (dosud) { - dosud = FALSE; - handle_setupdata(); - } - - if (dosuspend) { - dosuspend = FALSE; - do { - /* Make sure ext wakeups are cleared. */ - WAKEUPCS |= bmWU | bmWU2; - SUSPEND = 1; - PCON |= 1; - __asm - nop - nop - nop - nop - nop - nop - nop - __endasm; - } while (!remote_wakeup_allowed && REMOTE_WAKEUP()); - - /* Resume (TRM 6.4). */ - if (REMOTE_WAKEUP()) { - delay(5); - USBCS |= bmSIGRESUME; - delay(15); - USBCS &= ~bmSIGRESUME; - } - } - } -}