├── firmware ├── Makefile ├── usb_std_req.c ├── usb_std_req.h ├── usb_other_req.h ├── f38x_flash.h ├── usb_other_req.c ├── gpib.h ├── gpib_io.h ├── inf │ └── gpib-usbcdc_C8051F38x.inf ├── parser.h ├── type.h ├── util.h ├── main.h ├── util.c ├── usb_cdc.h ├── f38x_usb_register.h ├── main.c ├── f38x_flash.c ├── usb_descriptor.h ├── f38x_usb.h ├── gpib_io.c ├── parser.c ├── usb_descriptor.c ├── usb_cdc.c ├── gpib.c ├── f38x_usb.c └── c8051f380.h ├── board ├── gpib-usbcdc.brd ├── gpib-usbcdc.sch ├── gpib-usbcdc_layout.png └── LICENSE ├── docs ├── manual_by_Alessandro.odt └── manual_by_Alessandro.pdf ├── .travis.yml ├── README.md └── scripts └── build-sdcc.sh /firmware/Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/firmware/Makefile -------------------------------------------------------------------------------- /board/gpib-usbcdc.brd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/board/gpib-usbcdc.brd -------------------------------------------------------------------------------- /board/gpib-usbcdc.sch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/board/gpib-usbcdc.sch -------------------------------------------------------------------------------- /firmware/usb_std_req.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/firmware/usb_std_req.c -------------------------------------------------------------------------------- /board/gpib-usbcdc_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/board/gpib-usbcdc_layout.png -------------------------------------------------------------------------------- /docs/manual_by_Alessandro.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/docs/manual_by_Alessandro.odt -------------------------------------------------------------------------------- /docs/manual_by_Alessandro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/HEAD/docs/manual_by_Alessandro.pdf -------------------------------------------------------------------------------- /board/LICENSE: -------------------------------------------------------------------------------- 1 | The files in this directory are published under the license of Creative Commons Attribution-ShareAlike 4.0 International. 2 | Please see http://creativecommons.org/licenses/by-sa/4.0/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: cpp 3 | 4 | addons: 5 | apt: 6 | packages: 7 | - libboost-all-dev 8 | #- sdcc 9 | 10 | env: 11 | global: 12 | - SDCC=3.3.0 13 | - SDCC_DIR=/tmp/sdcc-$SDCC 14 | 15 | cache: 16 | directories: 17 | - $SDCC_DIR 18 | 19 | before_install: 20 | - export PATH=$PATH:$SDCC_DIR/bin 21 | - chmod +x ./scripts/build-sdcc.sh 22 | 23 | install: 24 | - ./scripts/build-sdcc.sh 25 | 26 | before_script: 27 | - sdcc --version 28 | 29 | script: 30 | - (cd ./firmware && make clean all) 31 | 32 | deploy: 33 | provider: releases 34 | api_key: 35 | secure: $GITHUB_TOKEN 36 | file: 37 | - ./firmware/build_by_sdcc/gpib-usbcdc.hex 38 | - ./firmware/build_by_sdcc/gpib-usbcdc.omf 39 | skip_cleanup: true 40 | all_branches: true # https://github.com/travis-ci/travis-ci/issues/1675 41 | on: 42 | tags: true -------------------------------------------------------------------------------- /firmware/usb_std_req.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef _USB_STD_REQ_H_ 33 | #define _USB_STD_REQ_H_ 34 | 35 | void usb_standard_request(); 36 | 37 | #endif /* _USB_STD_REQ_H_ */ 38 | -------------------------------------------------------------------------------- /firmware/usb_other_req.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef _USB_OTHER_REQ_H_ 33 | #define _USB_OTHER_REQ_H_ 34 | 35 | void usb_class_init(); 36 | void usb_class_request(); 37 | void usb_vendor_request(); 38 | 39 | #endif /* _USB_OTHER_REQ_H_ */ 40 | -------------------------------------------------------------------------------- /firmware/f38x_flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __F38X_FLASH_H__ 33 | #define __F38X_FLASH_H__ 34 | 35 | #include "type.h" 36 | 37 | #define FLASH_PAGESIZE 512 38 | #define FLASH_SCRATCH_PAGE 0x7c00 39 | 40 | typedef UINT flash_address_t; 41 | 42 | void flash_erase_page(flash_address_t addr); 43 | u16 flash_write(flash_address_t dst, u8 *src, u16 size); 44 | u16 flash_update(flash_address_t dst, u8 *src, u16 size); 45 | 46 | #endif /* __F38X_FLASH_H__ */ 47 | -------------------------------------------------------------------------------- /firmware/usb_other_req.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "main.h" 33 | #include "f38x_usb.h" 34 | 35 | #include "usb_other_req.h" 36 | #include "usb_descriptor.h" 37 | #include "usb_cdc.h" 38 | 39 | void usb_class_init(){ 40 | } 41 | 42 | void usb_class_request(){ 43 | if(ep0_setup.wIndex.i > 0){return;} 44 | switch(usb_mode){ 45 | #ifndef CDC_IS_REPLACED_BY_FTDI 46 | case USB_CDC_READY: 47 | case USB_CDC_ACTIVE: 48 | usb_CDC_req(); 49 | break; 50 | #endif 51 | } 52 | } 53 | 54 | void usb_vendor_request(){ 55 | #ifdef CDC_IS_REPLACED_BY_FTDI 56 | usb_CDC_req(); 57 | #endif 58 | } 59 | -------------------------------------------------------------------------------- /firmware/gpib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __GPIB_H__ 33 | #define __GPIB_H__ 34 | 35 | #include "type.h" 36 | 37 | void gpib_init(); 38 | void gpib_polling(); 39 | 40 | typedef struct { 41 | u8 item[15][2]; 42 | u8 valid_items; 43 | } address_t; 44 | 45 | typedef struct { 46 | address_t address; 47 | u8 read_after_write; 48 | u8 eoi; 49 | u8 eos; 50 | u8 eot; 51 | char eot_char; 52 | u8 listen_only; 53 | u8 is_controller; 54 | u16 timeout_ms; 55 | u8 status; 56 | u8 debug; 57 | } gpib_config_struct; 58 | 59 | typedef __xdata gpib_config_struct gpib_config_t; 60 | 61 | extern gpib_config_t gpib_config; 62 | 63 | #endif /* __GPIB_H__ */ 64 | -------------------------------------------------------------------------------- /firmware/gpib_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __GPIB_IO_H__ 33 | #define __GPIB_IO_H__ 34 | 35 | #include "type.h" 36 | 37 | void gpib_io_init(); 38 | void gpib_io_set_timeout(); 39 | 40 | #define GPIB_WRITE_USE_EOI 0x01 41 | 42 | u8 gpib_putchar(char c, u8 flags); 43 | u16 gpib_write(char *buf, u16 length, u8 flags); 44 | 45 | #define GPIB_GETCHAR_IS_ERROR(x) (x < 0) 46 | #define GPIB_GETCHAR_IS_EOI(x) (x >= 0x100) 47 | #define GPIB_GETCHAR_IS_CMD(x) (x >= 0x200) 48 | #define GPIB_GETCHAR_TO_DATA(x) ((u8)(x & 0xFF)) 49 | 50 | int gpib_getchar(); 51 | 52 | #define GPIB_READ_UNTIL_EOI 0x01 53 | 54 | u16 gpib_read(void (*push)(char), u8 flags); 55 | 56 | enum uniline_message_t { 57 | GPIB_UNI_CMD_START, 58 | GPIB_UNI_CMD_END, 59 | GPIB_UNI_BUS_CLEAR_START, 60 | GPIB_UNI_BUS_CLEAR_END, 61 | GPIB_UNI_CHECK_SRQ_ASSERT, 62 | GPIB_UNI_SRQ_ASSERT, 63 | GPIB_UNI_SRQ_DEASSERT, 64 | }; 65 | 66 | u8 gpib_uniline(enum uniline_message_t msg); 67 | 68 | #endif /* __GPIB_IO_H__ */ 69 | -------------------------------------------------------------------------------- /firmware/inf/gpib-usbcdc_C8051F38x.inf: -------------------------------------------------------------------------------- 1 | ; CDC_ACM.inf 2 | ; 3 | ; INF file for F32x_USB_CDC_skeleton example 4 | ; 5 | ; 1) Replace VID/PID to your own in [MYCORP] section 6 | ; VID_vvvv&PID_pppp 7 | ; vvvv, pppp: four digit hex number of VID and PID, respectively 8 | ; 9 | ; 2) Replace 'MYCORP' to your own abbreviated one (without space) 10 | ; ex Silicon Laboratories -> SILABS 11 | ; - Replace all MYCORP in this inf file 12 | ; 13 | ; 3) Replace 'MYDEV000' to your device model number (without space) 14 | ; ex C8051F320 Development kit -> F320DK 15 | ; - Replace all MYDEV000 in this inf file 16 | ; 17 | ; 4) Edit the strings in [Strings] section 18 | ; 19 | 20 | [Version] 21 | Signature="$Windows NT$" 22 | Class=Ports 23 | ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} 24 | 25 | Provider=%MYCORP% 26 | LayoutFile=layout.inf 27 | DriverVer=08/04/2004,5.1.2699.2180 28 | 29 | [Manufacturer] 30 | %MYCORP%=MYCORP,NTamd64 31 | 32 | [DestinationDirs] 33 | FakeModemCopyFileSection=12 34 | DefaultDestDir=12 35 | 36 | ;------------------------------------------ 37 | ; Windows 2000/XP/Vista32/Win732 Support 38 | ;------------------------------------------ 39 | 40 | [MYCORP] 41 | %MYDEV000%=MYDEV000,USB\VID_10C4&PID_8A5F 42 | 43 | [MYDEV000.NT] 44 | include=mdmcpq.inf 45 | CopyFiles=FakeModemCopyFileSection 46 | AddReg=MYDEV000.NT.AddReg 47 | 48 | [MYDEV000.NT.AddReg] 49 | HKR,,DevLoader,,*ntkern 50 | HKR,,NTMPDriver,,usbser.sys 51 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 52 | 53 | [MYDEV000.NT.Services] 54 | AddService = usbser, 0x00000002, Service_Inst 55 | 56 | ;------------------------------------------ 57 | ; Windows Vista64/Win764 Support 58 | ;------------------------------------------ 59 | 60 | [MYCORP.NTamd64] 61 | %MYDEV000%=MYDEV000,USB\VID_10C4&PID_8A5F 62 | 63 | [MYDEV000.NTamd64] 64 | include=mdmcpq.inf 65 | CopyFiles=FakeModemCopyFileSection 66 | AddReg=MYDEV000.NTamd64.AddReg 67 | 68 | [MYDEV000.NTamd64.AddReg] 69 | HKR,,DevLoader,,*ntkern 70 | HKR,,NTMPDriver,,usbser.sys 71 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 72 | 73 | [MYDEV000.NTamd64.Services] 74 | AddService=usbser, 0x00000002, Service_Inst 75 | 76 | 77 | [Service_Inst] 78 | DisplayName = %Serial.SvcDesc% 79 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 80 | StartType = 3 ; SERVICE_DEMAND_START 81 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 82 | ServiceBinary = %12%\usbser.sys 83 | LoadOrderGroup = Base 84 | 85 | [Strings] 86 | MYCORP = "YOU System" ; Your company name 87 | MYDEV000 = "GPIB-USB" ; Device description 88 | Serial.SvcDesc = "GPIB-USB CDC" ; Device driver description -------------------------------------------------------------------------------- /firmware/parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __PARSER_H__ 33 | #define __PARSER_H__ 34 | 35 | #include "type.h" 36 | 37 | enum command_t { 38 | CMD_ADDR, 39 | CMD_AUTO, 40 | CMD_CLR, 41 | CMD_EOI, 42 | CMD_EOS, 43 | CMD_EOT_ENABLE, 44 | CMD_EOT_CHAR, 45 | CMD_IFC, 46 | CMD_LLO, 47 | CMD_LOC, 48 | CMD_LON, 49 | CMD_MODE, 50 | CMD_READ, 51 | CMD_READ_TMO_MS, 52 | CMD_RST, 53 | CMD_SAVECFG, 54 | CMD_SPOLL, 55 | CMD_SRQ, 56 | CMD_STATUS, 57 | CMD_TRG, 58 | CMD_VER, 59 | CMD_HELP, 60 | CMD_DEBUG, 61 | CMD_INPUTABLE, 62 | CMD_ERROR = CMD_INPUTABLE, 63 | CMD_TALK, 64 | }; 65 | 66 | extern const __code char * __code command_str[CMD_INPUTABLE]; 67 | 68 | void parser_reset(); 69 | 70 | typedef __xdata struct { 71 | enum command_t cmd; 72 | int args; 73 | int arg[30]; 74 | } parsed_info_t; 75 | 76 | extern void run_command(parsed_info_t *info); 77 | void parse(char c); 78 | 79 | #define ARG_ERR -1 80 | #define ARG_EOI 256 81 | 82 | #endif /* __PARSER_H__ */ 83 | -------------------------------------------------------------------------------- /firmware/type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __TYPE_H__ 33 | #define __TYPE_H__ 34 | 35 | typedef unsigned char u8; 36 | typedef signed char s8; 37 | typedef unsigned short u16; 38 | typedef signed short s16; 39 | typedef unsigned long u32; 40 | typedef signed long s32; 41 | 42 | typedef unsigned char UCHAR; 43 | typedef unsigned int UINT; 44 | typedef unsigned long ULONG; 45 | 46 | #ifndef TRUE 47 | #define TRUE 1 48 | #endif 49 | #ifndef FALSE 50 | #define FALSE 0 51 | #endif 52 | 53 | typedef u8 BYTE; 54 | typedef u16 WORD; 55 | typedef u32 DWORD; 56 | 57 | typedef union {u16 i; u8 c[2];} WORD_t; 58 | typedef union {u32 i; u8 c[4];} DWORD_t; 59 | 60 | #define LSB 0 61 | #define MSB 1 62 | 63 | #if !(defined(__SDCC) || defined(SDCC)) 64 | #define __bit unsigned char 65 | #define __data 66 | #define __xdata 67 | #define __code 68 | #define __interrupt(x) 69 | #define __at(x) 70 | #define u32_lsbyte(x) ((x) & 0xFF) 71 | #else 72 | #define u32_lsbyte(x) (((DWORD_t *)&(x))->c[0]) // Little Endian 73 | #endif 74 | 75 | #endif /* __TYPE_H__ */ 76 | -------------------------------------------------------------------------------- /firmware/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __UTIL_H__ 33 | #define __UTIL_H__ 34 | 35 | #include "main.h" 36 | #include "type.h" 37 | 38 | void wait_8n6clk(unsigned char i); 39 | void _wait_us(unsigned int count); 40 | void wait_ms(unsigned int count); 41 | 42 | #define wait_us(n) { \ 43 | ((n) <= 100) ? wait_8n6clk((n) * 5) : _wait_us((n) - 1); \ 44 | } 45 | 46 | #ifdef ENDIAN_SWAP_BY_FUNC 47 | u32 swap_u32(u32 dw); 48 | u16 swap_u16(u16 w); 49 | #else 50 | #define swap_u32(dw) \ 51 | ( (u32)(((u32)(dw) & 0x000000FF) << 24) \ 52 | | (((u32)(dw) & 0x0000FF00) << 8) \ 53 | | (((u32)(dw) & 0x00FF0000) >> 8) \ 54 | | (((u32)(dw) & 0xFF000000) >> 24) \ 55 | ) 56 | #define swap_u16(w) \ 57 | ( (u16)(((u16)(w) & 0x00FF) << 8) \ 58 | | (((u16)(w) & 0xFF00) >> 8) \ 59 | ) 60 | #endif 61 | 62 | 63 | #if (defined(__SDCC) || defined(SDCC)) 64 | #define le_u32(dw) (dw) 65 | #define le_u16(w) (w) 66 | #define be_u32(dw) swap_u32(dw) 67 | #define be_u16(w) swap_u16(w) 68 | #define _nop_() { \ 69 | __asm \ 70 | nop \ 71 | __endasm; \ 72 | } 73 | #else 74 | #define le_u32(dw) 75 | #define le_u16(w) 76 | #define be_u32(dw) 77 | #define be_u16(w) 78 | #endif 79 | 80 | #define min(a,b) (((a)<(b))?(a):(b)) 81 | #define max(a,b) (((a)>(b))?(a):(b)) 82 | 83 | #endif /* __UTIL_H__ */ 84 | 85 | -------------------------------------------------------------------------------- /firmware/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __MAIN_H__ 33 | #define __MAIN_H__ 34 | 35 | #include "type.h" 36 | 37 | //#define _USB_LOW_SPEED_ // Change this comment to make Full/Low speed 38 | 39 | // SYSCLK frequency in Hz 40 | #define SYSCLK 48000000UL 41 | 42 | extern volatile __xdata u32 global_ms; 43 | extern volatile __xdata u32 tickcount; 44 | 45 | extern volatile __xdata u8 sys_state; 46 | #define SYS_PERIODIC_ACTIVE 0x01 47 | #define SYS_GPIB_CONTROLLER 0x10 48 | #define SYS_GPIB_TALKED 0x20 49 | #define SYS_GPIB_LISTENED 0x40 50 | 51 | extern volatile u8 timeout_10ms; 52 | 53 | // Define Endpoint Packet Sizes 54 | #ifdef _USB_LOW_SPEED_ 55 | // This value can be 8,16,32,64 depending on device speed, see USB spec 56 | #define PACKET_SIZE_EP0 0x40 57 | #else 58 | #define PACKET_SIZE_EP0 0x40 59 | #endif /* _USB_LOW_SPEED_ */ 60 | 61 | // Can range 0 - 1024 depending on data and transfer type 62 | #define PACKET_SIZE_EP1 0x0010 63 | #define PACKET_SIZE_EP2 0x0040 64 | #define PACKET_SIZE_EP3 0x0040 65 | 66 | #define CRITICAL_GLOBAL(func) \ 67 | { \ 68 | EA = 0; \ 69 | { \ 70 | func; \ 71 | } \ 72 | EA = 1; \ 73 | } 74 | 75 | 76 | #if (defined(__SDCC_REVISION) && (__SDCC_REVISION > 4818)) \ 77 | || (defined(SDCC_REVISION) && (SDCC_REVISION > 4818)) // upper than sdcc-2.7.0? 78 | #define USE_ASM_FOR_SFR_MANIP 79 | #define SHARP # 80 | #endif 81 | 82 | #endif /* __MAIN_H__ */ 83 | -------------------------------------------------------------------------------- /firmware/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "util.h" 33 | #include 34 | #include 35 | 36 | #ifdef ENDIAN_SWAP_BY_FUNC 37 | u32 swap_u32(u32 dw){ 38 | DWORD_t dw2; 39 | u8 tmp; 40 | dw2.i = dw; 41 | tmp = dw2.c[0]; 42 | dw2.c[0] = dw2.c[3]; 43 | dw2.c[3] = tmp; 44 | tmp = dw2.c[1]; 45 | dw2.c[1] = dw2.c[2]; 46 | dw2.c[2] = tmp; 47 | return dw2.i; 48 | } 49 | u16 swap_u16(u16 w){ 50 | WORD_t w2; 51 | u8 tmp; 52 | w2.i = w; 53 | tmp = w2.c[0]; 54 | w2.c[0] = w2.c[1]; 55 | w2.c[1] = tmp; 56 | return w2.i; 57 | } 58 | #endif 59 | 60 | void wait_8n6clk(unsigned char i){ 61 | while(i--); 62 | /*_asm 63 | mov r2,dpl ; 2clk 64 | start_wait_10n4: 65 | mov ar3,r2 ; 2clk 66 | dec r2 ; 1clk 67 | mov a,r3 ; 1clk 68 | jnz start_wait_10n4 ; 2/4clk 69 | ret ; 6clk 70 | _endasm;*/ 71 | } 72 | 73 | /** 74 | * Delay function with declared wait time in microseconds 75 | * 76 | * @param count time in us 77 | */ 78 | void _wait_us(unsigned int count){ 79 | while(count--) wait_8n6clk(5); // 46clk + about 45clk * n 80 | /*_asm 81 | mov r6,dpl ; 2clk 82 | mov r7,dph ; 2clk 83 | 00101$: 84 | mov ar4,r6 ; 2clk 85 | mov ar5,r7 ; 2clk 86 | dec r6 ; 1clk 87 | cjne r6,#0xFF,00113$ ; 3/5clk 88 | dec r7 ; 1clk 89 | 00113$: 90 | mov a,r4 ; 1clk 91 | orl a,r5 ; 1clk 92 | jz 00104$ ; 2/4clk 93 | mov dpl,#0x04 ; 3clk 94 | push ar7 ; 2clk 95 | push ar6 ; 2clk 96 | lcall _wait_8n6clk ; 5clk 97 | pop ar6 ; 2clk 98 | pop ar7 ; 2clk 99 | sjmp 00101$ ; 4clk 100 | 00104$: 101 | ret ; 6clk 102 | _endasm; 103 | */ 104 | } 105 | 106 | /** 107 | * Delay function with declared wait time in milliseconds 108 | * 109 | * @param count - time in ms 110 | */ 111 | void wait_ms(unsigned int count){ 112 | while(count--) wait_us(1000); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /firmware/usb_cdc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef __CDC_H__ 33 | #define __CDC_H__ 34 | 35 | #include "type.h" 36 | //#define CDC_IS_REPLACED_BY_FTDI 37 | 38 | /** 39 | * Header Functional Descriptor 40 | */ 41 | typedef struct { 42 | BYTE bLength; 43 | BYTE bDescriptorType; 44 | BYTE bDescriptorSubtype; 45 | WORD bcdCDC; 46 | } cdc_header_func_descriptor_t; 47 | 48 | /** 49 | * Call Management Functional Descriptor 50 | */ 51 | typedef struct { 52 | BYTE bLength; 53 | BYTE bDescriptorType; 54 | BYTE bDescriptorSubtype; 55 | BYTE bmCapabilities; 56 | BYTE bDataInterface; 57 | } cdc_call_man_func_descriptor_t; 58 | 59 | /** 60 | * Abstract Control Management Functional Descriptor 61 | */ 62 | typedef struct { 63 | BYTE bLength; 64 | BYTE bDescriptorType; 65 | BYTE bDescriptorSubtype; 66 | BYTE bmCapabilities; 67 | } cdc_abst_control_mana_descriptor_t; 68 | 69 | /** 70 | * Union Functional Descriptor 71 | */ 72 | typedef struct { 73 | BYTE bLength; 74 | BYTE bDescriptorType; 75 | BYTE bDescriptorSubtype; 76 | BYTE bMasterInterface; 77 | BYTE bSlaveInterface0; 78 | } cdc_union_func_descriptor_t; 79 | 80 | typedef struct { 81 | cdc_header_func_descriptor_t header; 82 | cdc_abst_control_mana_descriptor_t abst_control_mana; 83 | cdc_union_func_descriptor_t union_func; 84 | cdc_call_man_func_descriptor_t call_ma; 85 | } cdc_descriptor_t; 86 | 87 | #define cdc_config_length() sizeof(cdc_descriptor_t) 88 | 89 | typedef struct { 90 | DWORD_t baudrate; 91 | BYTE stopbit; 92 | BYTE parity; 93 | BYTE databit; 94 | } cdc_line_coding_t; 95 | 96 | // Descriptor type (Class specific) 97 | #define DSC_TYPE_CS_INTERFACE 0x24 98 | #define DSC_SUBTYPE_CS_HEADER_FUNC 0x00 99 | #define DSC_SUBTYPE_CS_CALL_MAN 0x01 100 | #define DSC_SUBTYPE_CS_ABST_CNTRL 0x02 101 | #define DSC_SUBTYPE_CS_UNION_FUNC 0x06 102 | 103 | // CDC ACM class specific requests 104 | #define SEND_ENCAPSULATED_COMMAND 0x00 105 | #define GET_ENCAPSULATED_RESPONSE 0x01 106 | #define SET_LINE_CODING 0x20 107 | #define GET_LINE_CODING 0x21 108 | #define SET_CONTROL_LINE_STATE 0x22 109 | #define SEND_BREAK 0x23 110 | 111 | void usb_CDC_req(); 112 | void cdc_polling(); 113 | u16 cdc_tx(u8 *buf, u16 size); 114 | u16 cdc_rx(u8 *buf, u16 size); 115 | 116 | #define CDC_COM_EP_IN 1 117 | #define CDC_DATA_EP_IN 2 118 | #define CDC_DATA_EP_OUT 2 119 | 120 | #ifndef CONCAT2_ 121 | #define CONCAT2_(a,b) (a ## b) 122 | #endif 123 | #ifndef CONCAT2 124 | #define CONCAT2(a,b) CONCAT2_(a, b) 125 | #endif 126 | 127 | #define CDC_DATA_EP_IN_PACKET_SIZE (CONCAT2(PACKET_SIZE_EP, CDC_DATA_EP_IN)) 128 | #define CDC_DATA_EP_OUT_PACKET_SIZE (CONCAT2(PACKET_SIZE_EP, CDC_DATA_EP_OUT)) 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GPIB-USBCDC 2 | =============== 3 | 4 | _GPIB-USBCDC_ is an interface bridge between GPIB (HPIB) and USB communication device class. 5 | It is [Prologix GPIB-USB adapter](http://prologix.biz/gpib-usb-controller.html) clone with [EFM8 Universal Bee](https://www.silabs.com/products/mcu/8-bit/efm8-universal-bee/pages/efm8-universal-bee.aspx) or [C8051F38x](http://www.silabs.com/products/mcu/8-bit/c8051f38x/Pages/c8051f38x.aspx) microcontroller. 6 | 7 | # Quick user guide 8 | 1. Connect _GPIB-USBCDC_ to the PC. _GPIB-USBCDC_ is recognized as serial port, which will be installed with [CDC inf file](https://raw.githubusercontent.com/fenrir-naru/gpib-usbcdc/master/firmware/inf/gpib-usbcdc_C8051F38x.inf). 9 | 1. Other usage is almost same as [Prologix GPIB-USB adapter](http://prologix.biz/gpib-usb-controller.html). Please see that product manual. 10 | 11 | # Manual 12 | [Nice user manual](https://github.com/fenrir-naru/gpib-usbcdc/blob/master/docs/manual_by_Alessandro.pdf) written by Alessandro Soraruf is available, Thanks! 13 | In addition, please set up your device with its address except for zero, in case of bus confliction reported by [biergaizi](https://github.com/fenrir-naru/gpib-usbcdc/issues/5). 14 | 15 | # Board 16 | [EagleCAD](http://www.cadsoftusa.com/) files are available (ver.1 [schematics](https://github.com/fenrir-naru/gpib-usbcdc/blob/master/board/gpib-usbcdc.sch) and [layout](https://github.com/fenrir-naru/gpib-usbcdc/blob/master/board/gpib-usbcdc.brd). Its components are listed in [BOM](https://github.com/fenrir-naru/gpib-usbcdc#bom-bill-of-material). The board design is published under [Creative Commons Attribution-ShareAlike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/). 17 | 18 | ## BOM (bill of material) 19 | 20 | 21 | 22 | | **Part** | **Value** | **Package** | **Multiple** | 23 | |:---------|:----------|:------------|:-------------| 24 | | C1, C4 | 1u / 6V3 | 1005 | 2 | 25 | | C2, C3, C5, C6 | 0.1u / 10V | 1005 | 4 | 26 | | CON1 | [HRS ZX62R-B-5P](http://www.digikey.jp/product-detail/ja/ZX62R-B-5P/H11574CT-ND/1787106) | | 1 | 27 | | CON2 | [Norcomp 111-024-113L001](http://www.digikey.jp/product-detail/ja/0/1024PMA-ND) | | 1 | 28 | | CON3 | [JST ZH B4B-ZR](http://www.jst-mfg.com/product/detail_e.php?series=287) | | 1 | 29 | | IC1 | [EFM8UB20F32G-A-QFN32](https://www.silabs.com/products/mcu/8-bit/efm8-universal-bee/pages/EFM8UB20F32G-A-QFN32.aspx) or [C8051F387-GM](http://www.silabs.com/products/mcu/8-bit/c8051f38x/pages/C8051F387-GM.aspx) | QFN32 | 1 | 30 | | IC2 | [SN75160BDWR](http://www.ti.com/product/sn75160b) or [SN75ALS160DWR](http://www.ti.com/product/sn75als160) | SO20 | 1 | 31 | | IC3 | [SN75162BDWR](http://www.ti.com/product/sn75162b) or [SN75ALS162DWR](http://www.ti.com/product/sn75als162) | SO24 | 1 | 32 | | LED1 | Red | 1608 | 1 | 33 | | LED2 | Orange | 1608 | 1 | 34 | | LED3 | Green | 1608 | 1 | 35 | | LED4 | Blue | 1608 | 1 | 36 | | R1, R2, R3, R4 | 470 | 1005 | 4 | 37 | | R5 | 1K | 1005 | 1 | 38 | 39 | # Firmware 40 | The official binary is published in [github release](https://github.com/fenrir-naru/gpib-usbcdc/releases). To build the firmware by yourself, install [sdcc](http://sdcc.sourceforge.net/) (testing with [ver 3.3.0 #8604](http://sourceforge.net/projects/sdcc/files/sdcc/3.3.0/)), and just "make" at "firmware" directory of the downloaded [code](https://github.com/fenrir-naru/gpib-usbcdc/tree/master/firmware). The generated firmware name is `gpib-usbcdc.hex`. The firmware code is published under [New BSD License](http://opensource.org/licenses/BSD-3-Clause). 41 | 42 | [![Build Status](https://travis-ci.org/fenrir-naru/gpib-usbcdc.svg?branch=master)](https://travis-ci.org/fenrir-naru/gpib-usbcdc) 43 | 44 | ## How to write firmware to hardware 45 | Connect a _GPIB-USBCDC_ board and a PC via [USB debug adapter (UDA)](http://www.silabs.com/products/mcu/pages/usbdebug.aspx) or compatible one. The minimum required programming connections are summarized in the following table. Then, use [Flash Programming Utilities](http://www.silabs.com/products/mcu/Pages/8-bit-microcontroller-software.aspx#flash). Note: the board may not be recognized by a PC when an UDA is connected via USB hubs. UDA is recommended to connect a PC directly. 46 | 47 | | **Signal** | **UDA side** | **_GPIB-USBCDC_ board side** | 48 | |:-----------|:-------------|:---------------------------------| 49 | | C2D | 4th pin | CON3 3rd pin | 50 | | C2CK | 7th pin | CON3 4th pin | 51 | | GND | 3rd pin | CON3 1st pin | 52 | 53 | # Additional information 54 | * The project owner's website is [Fenrir's BLog](http://fenrir.naruoka.org/). 55 | -------------------------------------------------------------------------------- /scripts/build-sdcc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ev 3 | : ${SDCC:=3.3.0} 4 | : ${SDCC_DIR:=/usr/local} 5 | 6 | if [[ $(sdcc --version) =~ "${SDCC}" ]]; then 7 | echo "Found sdcc-${SDCC}, build skipped." 8 | exit 0 9 | fi 10 | 11 | if [ ! -d sdcc-${SDCC} ]; then 12 | if [ ! -f sdcc-src-${SDCC}.tar.bz2 ]; then 13 | wget "https://downloads.sourceforge.net/project/sdcc/sdcc/${SDCC}/sdcc-src-${SDCC}.tar.bz2" -O sdcc-src-${SDCC}.tar.bz2 14 | fi 15 | mkdir sdcc-${SDCC} && tar jvxf sdcc-src-${SDCC}.tar.bz2 -C sdcc-${SDCC} --strip-components 1 16 | fi 17 | 18 | cd sdcc-${SDCC} 19 | 20 | case "${SDCC}" in 21 | 3.[34].*) 22 | (cd sdas/linksrc && patch -u -N -p1 <<'__PATCH_LINE__' || let "$?<=1") 23 | diff -uprN linksrc.orig/lkar.c linksrc/lkar.c 24 | --- linksrc.orig/lkar.c 2019-09-16 03:01:13.278101100 +0900 25 | +++ linksrc/lkar.c 2019-09-16 02:59:47.520475600 +0900 26 | @@ -47,7 +47,7 @@ along with this program. If not, see = name) 56 | ; 57 | - return strndup (name, p - name + 1); 58 | + return strndup_ (name, p - name + 1); 59 | } 60 | } 61 | 62 | __PATCH_LINE__ 63 | ;; 64 | esac 65 | 66 | case "${SDCC}" in 67 | 3.[34].*) 68 | patch -u -N -p1 <<'__PATCH_LINE__' || let "$?<=1" 69 | Index: sdcc-3.4.0/support/sdbinutils/bfd/bfd-in.h 70 | =================================================================== 71 | --- sdcc-3.4.0.orig/support/sdbinutils/bfd/bfd-in.h 2012-11-05 21:26:25.000000000 +0800 72 | +++ sdcc-3.4.0/support/sdbinutils/bfd/bfd-in.h 2014-06-19 16:40:09.274149785 +0800 73 | @@ -294,9 +294,9 @@ 74 | 75 | #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) 76 | 77 | -#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) 78 | -#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) 79 | -#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) 80 | +#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE)) 81 | +#define bfd_set_section_alignment(bfd, ptr, val) ((ptr)->alignment_power = (val)) 82 | +#define bfd_set_section_userdata(bfd, ptr, val) ((ptr)->userdata = (val)) 83 | /* Find the address one past the end of SEC. */ 84 | #define bfd_get_section_limit(bfd, sec) \ 85 | (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ 86 | @@ -519,7 +519,7 @@ 87 | 88 | #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) 89 | 90 | -#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) 91 | +#define bfd_set_cacheable(abfd,bool) ((abfd)->cacheable = bool) 92 | 93 | extern bfd_boolean bfd_cache_close 94 | (bfd *abfd); 95 | Index: sdcc-3.4.0/support/sdbinutils/bfd/bfd-in2.h 96 | =================================================================== 97 | --- sdcc-3.4.0.orig/support/sdbinutils/bfd/bfd-in2.h 2012-11-05 21:26:25.000000000 +0800 98 | +++ sdcc-3.4.0/support/sdbinutils/bfd/bfd-in2.h 2014-06-19 16:42:09.110092421 +0800 99 | @@ -301,9 +301,9 @@ 100 | 101 | #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) 102 | 103 | -#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) 104 | -#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) 105 | -#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) 106 | +#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE)) 107 | +#define bfd_set_section_alignment(bfd, ptr, val) ((ptr)->alignment_power = (val)) 108 | +#define bfd_set_section_userdata(bfd, ptr, val) ((ptr)->userdata = (val)) 109 | /* Find the address one past the end of SEC. */ 110 | #define bfd_get_section_limit(bfd, sec) \ 111 | (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ 112 | @@ -526,7 +526,7 @@ 113 | 114 | #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) 115 | 116 | -#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) 117 | +#define bfd_set_cacheable(abfd,bool) ((abfd)->cacheable = bool) 118 | 119 | extern bfd_boolean bfd_cache_close 120 | (bfd *abfd); 121 | __PATCH_LINE__ 122 | ;; 123 | esac 124 | 125 | DISABLE_DEVICES="z80 z180 r2k r3ka gbz80 ds390 ds400 pic14 pic16 hc08 s08" 126 | CONFIGURE_OPT="--prefix=${SDCC_DIR} --disable-ucsim --disable-sdcdb --disable-non-free" 127 | case "${SDCC}" in 128 | 3.[45678].*) 129 | DISABLE_DEVICES+=" tlcs90 stm8";; 130 | 3.[9].* | 4.0.*) 131 | DISABLE_DEVICES+=" tlcs90 stm8 ez80_z80 pdk13 pdk14 pdk15";; 132 | 4.1.*) 133 | DISABLE_DEVICES+=" tlcs90 stm8 ez80_z80 pdk13 pdk14 pdk15 r2ka z80n";; 134 | esac 135 | for dev in ${DISABLE_DEVICES}; do 136 | CONFIGURE_OPT+=" --disable-${dev}-port"; 137 | done 138 | 139 | ./configure ${CONFIGURE_OPT} \ 140 | && make -j \ 141 | && make install -------------------------------------------------------------------------------- /firmware/f38x_usb_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef _USB_REGS_H_ 33 | #define _USB_REGS_H_ 34 | 35 | #include "c8051f380.h" 36 | 37 | // USB Core Registers 38 | #define BASE 0x00 39 | #define FADDR BASE 40 | #define POWER (BASE + 0x01) 41 | #define IN1INT (BASE + 0x02) 42 | #define OUT1INT (BASE + 0x04) 43 | #define CMINT (BASE + 0x06) 44 | #define IN1IE (BASE + 0x07) 45 | #define OUT1IE (BASE + 0x09) 46 | #define CMIE (BASE + 0x0B) 47 | #define FRAMEL (BASE + 0x0C) 48 | #define FRAMEH (BASE + 0x0D) 49 | #define INDEX (BASE + 0x0E) 50 | #define CLKREC (BASE + 0x0F) 51 | #define E0CSR (BASE + 0x11) 52 | #define EINCSR1 (BASE + 0x11) 53 | #define EINCSR2 (BASE + 0x12) 54 | #define EOUTCSR1 (BASE + 0x14) 55 | #define EOUTCSR2 (BASE + 0x15) 56 | #define E0CNT (BASE + 0x16) 57 | #define EOUTCNTL (BASE + 0x16) 58 | #define EOUTCNTH (BASE + 0x17) 59 | #define FIFO_EP0 (BASE + 0x20) 60 | #define FIFO_EP1 (BASE + 0x21) 61 | #define FIFO_EP2 (BASE + 0x22) 62 | #define FIFO_EP3 (BASE + 0x23) 63 | 64 | // USB Core Register Bits 65 | 66 | // POWER 67 | #define rbISOUD 0x80 68 | #define rbSPEED 0x40 69 | #define rbUSBRST 0x08 70 | #define rbRESUME 0x04 71 | #define rbSUSMD 0x02 72 | #define rbSUSEN 0x01 73 | 74 | // IN1INT 75 | #define rbIN3 0x08 76 | #define rbIN2 0x04 77 | #define rbIN1 0x02 78 | #define rbEP0 0x01 79 | 80 | // OUT1INT 81 | #define rbOUT3 0x08 82 | #define rbOUT2 0x04 83 | #define rbOUT1 0x02 84 | 85 | // CMINT 86 | #define rbSOF 0x08 87 | #define rbRSTINT 0x04 88 | #define rbRSUINT 0x02 89 | #define rbSUSINT 0x01 90 | 91 | // IN1IE 92 | #define rbIN3E 0x08 93 | #define rbIN2E 0x04 94 | #define rbIN1E 0x02 95 | #define rbEP0E 0x01 96 | 97 | // OUT1IE 98 | #define rbOUT3E 0x08 99 | #define rbOUT2E 0x04 100 | #define rbOUT1E 0x02 101 | 102 | // CMIE 103 | #define rbSOFE 0x08 104 | #define rbRSTINTE 0x04 105 | #define rbRSUINTE 0x02 106 | #define rbSUSINTE 0x01 107 | 108 | // E0CSR 109 | #define rbSSUEND 0x80 110 | #define rbSOPRDY 0x40 111 | #define rbSDSTL 0x20 112 | #define rbSUEND 0x10 113 | #define rbDATAEND 0x08 114 | #define rbSTSTL 0x04 115 | #define rbINPRDY 0x02 116 | #define rbOPRDY 0x01 117 | 118 | // EINCSR1 119 | #define rbInCLRDT 0x40 120 | #define rbInSTSTL 0x20 121 | #define rbInSDSTL 0x10 122 | #define rbInFLUSH 0x08 123 | #define rbInUNDRUN 0x04 124 | #define rbInFIFONE 0x02 125 | #define rbInINPRDY 0x01 126 | 127 | // EINCSR2 128 | #define rbInDBIEN 0x80 129 | #define rbInISO 0x40 130 | #define rbInDIRSEL 0x20 131 | #define rbInFCDT 0x08 132 | #define rbInSPLIT 0x04 133 | 134 | // EOUTCSR1 135 | #define rbOutCLRDT 0x80 136 | #define rbOutSTSTL 0x40 137 | #define rbOutSDSTL 0x20 138 | #define rbOutFLUSH 0x10 139 | #define rbOutDATERR 0x08 140 | #define rbOutOVRUN 0x04 141 | #define rbOutFIFOFUL 0x02 142 | #define rbOutOPRDY 0x01 143 | 144 | // EOUTCSR2 145 | #define rbOutDBOEN 0x80 146 | #define rbOutISO 0x40 147 | 148 | // INDEX IDENTIFIERS 149 | #define EP0_IDX 0x00 150 | 151 | // Register read/write macros 152 | 153 | // These first two macros do not poll for busy, and can be used to increase program speed where 154 | // neccessary, but should never be used for successive reads or writes. 155 | #define READ_BYTE(addr, target) USB0ADR = (0x80 | addr); while(USB0ADR & 0x80); target = USB0DAT 156 | #define WRITE_BYTE(addr, data) USB0ADR = (addr); USB0DAT = data 157 | 158 | // These two macros are polling versions of the above macros, and can be used for successive reads/ 159 | // writes without taking the chance that the Interface Engine is busy from the last register access. 160 | #define POLL_READ_BYTE(addr, target) while(USB0ADR & 0x80); READ_BYTE(addr, target); 161 | #define POLL_WRITE_BYTE(addr, data) while(USB0ADR & 0x80); WRITE_BYTE(addr, data); 162 | 163 | #endif /* _USB_REGS_H_ */ 164 | 165 | 166 | -------------------------------------------------------------------------------- /firmware/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | 35 | #include "main.h" 36 | #include "util.h" 37 | 38 | #include "c8051f380.h" 39 | #include "f38x_usb.h" 40 | #include "gpib.h" 41 | 42 | volatile __xdata u32 global_ms = 0; 43 | volatile __xdata u32 tickcount = 0; 44 | volatile __xdata u8 sys_state = 0; 45 | volatile u8 timeout_10ms = 0; 46 | 47 | void sysclk_init(); 48 | void port_init(); 49 | void timer_init(); 50 | 51 | #ifdef USE_ASM_FOR_SFR_MANIP 52 | #define led_on(i) {__asm orl _P0,SHARP (0x01 << (i - 1)) __endasm; } 53 | #define led_off(i) {__asm anl _P0,SHARP ~(0x01 << (i - 1)) __endasm; } 54 | #define led_toggle(i) {__asm xrl _P0,SHARP (0x01 << (i - 1)) __endasm; } 55 | #else 56 | #define led_on(i) (P0 |= (0x01 << (i - 1))) 57 | #define led_off(i) (P0 &= ~(0x01 << (i - 1))) 58 | #define led_toggle(i) (P0 ^= (0x01 << (i - 1))) 59 | #endif 60 | 61 | void main() { 62 | sysclk_init(); // Initialize oscillator 63 | wait_ms(1000); 64 | port_init(); // Initialize crossbar and GPIO 65 | 66 | gpib_init(); 67 | 68 | timer_init(); 69 | 70 | EA = 1; // Global Interrupt enable 71 | 72 | usb0_init(); 73 | 74 | while (1) { 75 | gpib_polling(); 76 | usb_polling(); 77 | 78 | if(sys_state & SYS_PERIODIC_ACTIVE){ 79 | sys_state &= ~SYS_PERIODIC_ACTIVE; 80 | led_toggle(1); 81 | } 82 | 83 | if(sys_state & SYS_GPIB_CONTROLLER){ 84 | led_on(2); 85 | }else{ 86 | led_off(2); 87 | } 88 | 89 | { // check talked 90 | static __xdata u8 persistent = 0; 91 | if(sys_state & SYS_GPIB_TALKED){ 92 | led_on(3); 93 | persistent = 0x40; 94 | }else if(persistent > 0){ 95 | led_toggle(3); 96 | persistent--; 97 | }else{ 98 | led_off(3); 99 | } 100 | } 101 | 102 | { // check listened 103 | static __xdata u8 persistent = 0; 104 | if(sys_state & SYS_GPIB_LISTENED){ 105 | led_on(4); 106 | persistent = 0x40; 107 | }else if(persistent > 0){ 108 | led_toggle(4); 109 | persistent--; 110 | }else{ 111 | led_off(4); 112 | } 113 | } 114 | } 115 | } 116 | 117 | // System clock selections (SFR CLKSEL) 118 | #define SYS_INT_OSC 0x00 // Select to use internal oscillator 119 | #define SYS_4X_MUL 0x03 // Select to use internal oscillator 120 | #define SYS_EXT_OSC 0x01 // Select to use an external oscillator 121 | #define SYS_4X_DIV_2 0x02 122 | 123 | // USB clock selections (SFR CLKSEL) 124 | #define USB_4X_CLOCK 0x00 // Select 4x clock multiplier, for USB Full Speed 125 | #define USB_INT_OSC_DIV_2 0x10 // See Data Sheet section 13. Oscillators 126 | #define USB_EXT_OSC 0x20 127 | #define USB_EXT_OSC_DIV_2 0x30 128 | #define USB_EXT_OSC_DIV_3 0x40 129 | #define USB_EXT_OSC_DIV_4 0x50 130 | 131 | void sysclk_init(){ 132 | REF0CN = 0x07; 133 | 134 | // Configure internal oscillator for its maximum frequency and enable missing clock detector 135 | OSCICN |= 0x03; 136 | 137 | #ifdef _USB_LOW_SPEED_ 138 | CLKSEL = SYS_INT_OSC; // Select System clock 139 | CLKSEL |= USB_INT_OSC_DIV_2; // Select USB clock 140 | #else 141 | // Select internal oscillator as input to clock multiplier 142 | CLKMUL = 0x00; 143 | CLKMUL |= 0x80; // Enable clock multiplier 144 | wait_ms(1); // Delay for clock multiplier to begin 145 | CLKMUL |= 0xC0; // Initialize the clock multiplier 146 | wait_ms(1); 147 | while(!(CLKMUL & 0x20)); // Wait for multiplier to lock 148 | CLKSEL = SYS_4X_MUL; 149 | CLKSEL |= USB_4X_CLOCK; // Select USB clock 150 | #endif /* _USB_LOW_SPEED_ */ 151 | } 152 | 153 | 154 | void port_init() { 155 | 156 | // Default port state 157 | // Pn = 1 (High), PnMDIN = 1 (not analog), PnMDOUT = 0 (open-drain) => Hi-Z 158 | 159 | // P0 160 | // 0-7 => GPIO 161 | P0MDIN = 0xFF; 162 | P0MDOUT = 0x0F; // 0-3 => push-pull, 4-7 => open-drain 163 | P0 = 0xF0; 164 | P0SKIP = 0xFF; 165 | 166 | // P1 => GPIO 167 | P1MDIN = 0xFF; 168 | P1MDOUT = 0x00; // open-drain 169 | P1 = 0xFF; 170 | P1SKIP = 0xFF; 171 | 172 | // P2 = GPIO 173 | P2MDIN = 0xFF; 174 | P2MDOUT = 0x00; // open-drain 175 | P2 = 0xFF; 176 | P2SKIP = 0xFF; 177 | 178 | // P3 179 | P3MDIN = 0xFF; 180 | P3MDOUT = 0xFF; 181 | P3 = 0x00; 182 | 183 | XBR0 = 0x00; 184 | XBR2 = 0x00; 185 | XBR1 = 0x40; // Enable crossbar 186 | } 187 | 188 | void timer_init(){ 189 | TMR3CN = 0x00; // Stop Timer3; Clear TF3; 190 | CKCON &= ~0xC0; // Timer3 clocked based on T3XCLK; 191 | TMR3RL = (0x10000 - (SYSCLK/12/100)); // Re-initialize reload value (100Hz, 10ms) 192 | TMR3 = 0xFFFF; // Set to reload immediately 193 | EIE1 |= 0x80; // Enable Timer3 interrupts(ET3) 194 | TMR3CN |= 0x04; // Start Timer3(TR3) 195 | } 196 | 197 | /** 198 | * interrupt routine invoked when timer3 overflow 199 | * 200 | */ 201 | void interrupt_timer3() __interrupt (INTERRUPT_TIMER3) { 202 | TMR3CN &= ~0x80; // Clear interrupt 203 | global_ms += 10; 204 | tickcount++; 205 | timeout_10ms++; 206 | sys_state |= SYS_PERIODIC_ACTIVE; 207 | } 208 | 209 | unsigned char _sdcc_external_startup(){ 210 | PCA0MD &= ~0x40; ///< Disable Watchdog timer 211 | return 0; 212 | } 213 | -------------------------------------------------------------------------------- /firmware/f38x_flash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "f38x_flash.h" 33 | #include "c8051f380.h" 34 | #include "main.h" 35 | #include "util.h" 36 | 37 | static __bit ea_orig; 38 | static __xdata u8 FLSCL_orig, VDM0CN_orig, RSTSRC_orig; 39 | 40 | /* 41 | * @see http://community.silabs.com/t5/8-bit-MCU-Knowledge-Base/FLASH-Corruption/ta-p/110449 42 | * @see http://community.silabs.com/t5/8-bit-MCU-Knowledge-Base/All-about-the-VDD-Monitor/ta-p/110805 43 | */ 44 | 45 | static void prologue(){ 46 | ea_orig = EA; // Preserve EA 47 | EA = 0; // Disable interrupts 48 | 49 | FLSCL_orig = FLSCL & 0x90; 50 | if(SYSCLK > 25000000UL){ // check clock speed 51 | FLSCL = (FLSCL_orig | 0x10); 52 | } 53 | 54 | VDM0CN_orig = VDM0CN; 55 | if(!(VDM0CN & 0x80)){ 56 | VDM0CN = (VDM0CN_orig | 0x80); // Enable VDD monitor 57 | wait_us(100); 58 | } 59 | RSTSRC_orig = RSTSRC & 0xA6; 60 | RSTSRC = (RSTSRC_orig | 0x02); // Enable VDD monitor as a reset source; do not use a bit-wise OP 61 | } 62 | 63 | static void epilogue(){ 64 | RSTSRC = RSTSRC_orig; 65 | VDM0CN = VDM0CN_orig; 66 | FLSCL = FLSCL_orig; 67 | EA = ea_orig; // Restore interrupts 68 | } 69 | 70 | #define set_keys() { \ 71 | FLKEY = 0xA5; \ 72 | FLKEY = 0xF1; \ 73 | } 74 | 75 | #define write_byte(addr, byte) { \ 76 | *((u8 __xdata *)addr) = byte; \ 77 | } 78 | 79 | #define read_byte(addr) *((u8 __code *)(addr)) 80 | 81 | static u8 check_erased(flash_address_t addr, u16 size){ 82 | u8 already_erased = TRUE; 83 | while(size--){ 84 | if(read_byte(addr) != 0xFF){ 85 | already_erased = FALSE; 86 | break; 87 | } 88 | addr++; 89 | } 90 | return already_erased; 91 | } 92 | 93 | void flash_erase_page(flash_address_t addr){ 94 | #if 1 95 | addr &= ~((flash_address_t)FLASH_PAGESIZE - 1); 96 | if(check_erased(addr, FLASH_PAGESIZE)){return;} 97 | #endif 98 | 99 | prologue(); 100 | 101 | set_keys(); 102 | PSCTL |= 0x03; // PSWE = 1, PSEE = 1 103 | write_byte(addr, 0); 104 | PSCTL &= ~0x03; // PSWE = 0, PSEE = 0 105 | 106 | epilogue(); 107 | } 108 | 109 | u16 flash_write(flash_address_t dst, u8 *src, u16 size){ 110 | u16 size_orig = size; 111 | u8 b[2]; 112 | do{ 113 | if(size == 0){break;} 114 | prologue(); 115 | #if 0 116 | do{ 117 | b[0] = *(src++); 118 | set_keys(); 119 | PSCTL |= 0x01; // PSWE = 1 120 | write_byte(dst, b[0]); 121 | PSCTL &= ~0x01; // PSWE = 0 122 | dst++; 123 | }while(--size); 124 | #elif 1 125 | if(dst & 0x1){ // odd 126 | b[0] = *(src++); 127 | PSCTL |= 0x01; // PSWE = 1 128 | set_keys(); 129 | write_byte(dst, b[0]); 130 | PSCTL &= ~0x01; // PSWE = 0 131 | dst++; 132 | size--; 133 | } 134 | PFE0CN |= 0x01; 135 | while(size >= 2){ 136 | u16 dst_odd = dst + 1; 137 | b[0] = *(src++); 138 | b[1] = *(src++); 139 | PSCTL |= 0x01; // PSWE = 1 140 | set_keys(); 141 | write_byte(dst, b[0]); 142 | set_keys(); 143 | write_byte(dst_odd, b[1]); 144 | PSCTL &= ~0x01; // PSWE = 0 145 | dst = dst_odd + 1; 146 | size -= 2; 147 | } 148 | PFE0CN &= ~0x01; 149 | if(size > 0){ 150 | b[0] = *src; 151 | PSCTL |= 0x01; // PSWE = 1 152 | set_keys(); 153 | write_byte(dst, b[0]); 154 | PSCTL &= ~0x01; // PSWE = 0 155 | } 156 | #endif 157 | epilogue(); 158 | }while(0); 159 | return size_orig; 160 | } 161 | 162 | static void page_copy(flash_address_t dst, flash_address_t src){ 163 | flash_erase_page(dst); 164 | flash_write(dst, (u8 __code *)src, FLASH_PAGESIZE); 165 | } 166 | 167 | u16 flash_update(flash_address_t dst, u8 *src, u16 size){ 168 | flash_address_t dst_align = dst & ~((flash_address_t)FLASH_PAGESIZE - 1); 169 | u16 size_orig = size; 170 | 171 | if((size > 0) && (dst_align != dst)){ // first page 172 | u16 copy1_size = dst - dst_align; 173 | u16 copy2_size = FLASH_PAGESIZE - copy1_size; 174 | u16 copy3_size; 175 | if(copy2_size > size){ 176 | copy3_size = copy2_size - size; 177 | copy2_size = size; 178 | }else{ 179 | copy3_size = 0; 180 | } 181 | 182 | // check requirement for copy 183 | if(check_erased(dst_align, copy1_size) 184 | && check_erased(dst_align + FLASH_PAGESIZE - copy3_size, copy3_size)){ 185 | copy1_size = 0; 186 | copy3_size = 0; 187 | }else{ 188 | page_copy(FLASH_SCRATCH_PAGE, dst_align); 189 | } 190 | 191 | flash_erase_page(dst_align); 192 | flash_write(dst_align, (u8 __code *)FLASH_SCRATCH_PAGE, copy1_size); 193 | flash_write(dst, src, copy2_size); 194 | dst += copy2_size; 195 | src += copy2_size; 196 | size -= copy2_size; 197 | flash_write(dst, (u8 __code *)(FLASH_SCRATCH_PAGE + FLASH_PAGESIZE - copy3_size), copy3_size); 198 | } 199 | 200 | while(size >= FLASH_PAGESIZE){ // updating intermediate pages every page 201 | flash_erase_page(dst); 202 | flash_write(dst, src, FLASH_PAGESIZE); 203 | dst += FLASH_PAGESIZE; 204 | src += FLASH_PAGESIZE; 205 | size -= FLASH_PAGESIZE; 206 | } 207 | 208 | if(size > 0){ // last page 209 | u16 copy_size = FLASH_PAGESIZE - size; 210 | if(check_erased(dst + size, copy_size)){ 211 | copy_size = 0; 212 | }else{ 213 | page_copy(FLASH_SCRATCH_PAGE, dst); 214 | } 215 | 216 | flash_erase_page(dst); 217 | flash_write(dst, src, size); 218 | dst += size; 219 | flash_write(dst, (u8 __code *)(FLASH_SCRATCH_PAGE + size), copy_size); 220 | } 221 | 222 | return size_orig; 223 | } 224 | -------------------------------------------------------------------------------- /firmware/usb_descriptor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef _USB_DESCRIPTOR_H_ 33 | #define _USB_DESCRIPTOR_H_ 34 | 35 | #include "type.h" 36 | #include "f38x_usb.h" 37 | 38 | /** 39 | * Standard Device Descriptor Type Definition 40 | */ 41 | typedef struct { 42 | BYTE bLength; // Size of this Descriptor in Bytes 43 | BYTE bDescriptorType; // Descriptor Type (=1) 44 | WORD bcdUSB; // USB Spec Release Number in BCD 45 | BYTE bDeviceClass; // Device Class Code 46 | BYTE bDeviceSubClass; // Device Subclass Code 47 | BYTE bDeviceProtocol; // Device Protocol Code 48 | BYTE bMaxPacketSize0; // Maximum Packet Size for EP0 49 | WORD idVendor; // Vendor ID 50 | WORD idProduct; // Product ID 51 | WORD bcdDevice; // Device Release Number in BCD 52 | BYTE iManufacturer; // Index of String Desc for Manufacturer 53 | BYTE iProduct; // Index of String Desc for Product 54 | BYTE iSerialNumber; // Index of String Desc for SerNo 55 | BYTE bNumConfigurations; // Number of possible Configurations 56 | } device_descriptor_t; // End of Device Descriptor Type 57 | 58 | /** 59 | * Standard Configuration Descriptor Type Definition 60 | */ 61 | typedef struct { 62 | BYTE bLength; // Size of this Descriptor in Bytes 63 | BYTE bDescriptorType; // Descriptor Type (=2) 64 | WORD_t wTotalLength; // Total Length of Data for this Conf 65 | BYTE bNumInterfaces; // No of Interfaces supported by this Conf 66 | BYTE bConfigurationValue; // Designator Value for *this* Configuration 67 | BYTE iConfiguration; // Index of String Desc for this Conf 68 | BYTE bmAttributes; // Configuration Characteristics (see below) 69 | BYTE bMaxPower; // Max. Power Consumption in this Conf (*2mA) 70 | } configuration_descriptor_t; // End of Configuration Descriptor Type 71 | 72 | /** 73 | * Standard Interface Descriptor Type Definition 74 | */ 75 | typedef struct { 76 | BYTE bLength; // Size of this Descriptor in Bytes 77 | BYTE bDescriptorType; // Descriptor Type (=4) 78 | BYTE bInterfaceNumber; // Number of *this* Interface (0..) 79 | BYTE bAlternateSetting; // Alternative for this Interface (if any) 80 | BYTE bNumEndpoints; // No of EPs used by this IF (excl. EP0) 81 | BYTE bInterfaceClass; // Interface Class Code 82 | BYTE bInterfaceSubClass; // Interface Subclass Code 83 | BYTE bInterfaceProtocol; // Interface Protocol Code 84 | BYTE iInterface; // Index of String Desc for this Interface 85 | } interface_descriptor_t; // End of Interface Descriptor Type 86 | 87 | /** 88 | * Standard Endpoint Descriptor Type Definition 89 | */ 90 | typedef struct { 91 | BYTE bLength; // Size of this Descriptor in Bytes 92 | BYTE bDescriptorType; // Descriptor Type (=5) 93 | BYTE bEndpointAddress; // Endpoint Address (Number + Direction) 94 | BYTE bmAttributes; // Endpoint Attributes (Transfer Type) 95 | WORD_t wMaxPacketSize; // Max. Endpoint Packet Size 96 | BYTE bInterval; // Polling Interval (Interrupt) ms 97 | } endpoint_descriptor_t; // End of Endpoint Descriptor Type 98 | 99 | typedef struct { 100 | BYTE bLength; // Size of this Descriptor in Bytes 101 | BYTE bDescriptorType; // Descriptor Type (=11) 102 | BYTE bFirstInterface; // 103 | BYTE bInterfaceCount; // 104 | BYTE bFunctionClass; // Function Class Code 105 | BYTE bFunctionSubClass; // Function Subclass Code 106 | BYTE bFunctionProtocol; // Function Protocol Code 107 | BYTE iInterface; // Index of String Desc for this function 108 | } interface_association_descriptor_t; 109 | 110 | #define config_length_total(n_interfaces, n_endpoints) \ 111 | (sizeof(configuration_descriptor_t) \ 112 | + (sizeof(interface_descriptor_t) * n_interfaces) \ 113 | + (sizeof(endpoint_descriptor_t) * n_endpoints)) 114 | #define iad_length() sizeof(interface_association_descriptor_t) 115 | 116 | // Standard Descriptor Types @see USB spec. chapter.9 117 | #define DSC_TYPE_DEVICE 0x01 // Device Descriptor 118 | #define DSC_TYPE_CONFIG 0x02 // Configuration Descriptor 119 | #define DSC_TYPE_STRING 0x03 // String Descriptor 120 | #define DSC_TYPE_INTERFACE 0x04 // Interface Descriptor 121 | #define DSC_TYPE_ENDPOINT 0x05 // Endpoint Descriptor 122 | #define DSC_TYPE_IASSOC 0x0B // Interface Association Descriptor 123 | 124 | // Endpoint transfer type 125 | #define DSC_EP_CONTROL 0x00 126 | #define DSC_EP_ISOC 0x01 127 | #define DSC_EP_BULK 0x02 128 | #define DSC_EP_INTERRUPT 0x03 129 | 130 | // HID Descriptor Types 131 | #define DSC_HID 0x21 // HID Class Descriptor 132 | #define DSC_HID_REPORT 0x22 // HID Report Descriptor 133 | 134 | // HID Request Codes 135 | #define GET_REPORT 0x01 // Code for Get Report 136 | #define GET_IDLE 0x02 // Code for Get Idle 137 | #define GET_PROTOCOL 0x03 // Code for Get Protocol 138 | #define SET_REPORT 0x09 // Code for Set Report 139 | #define SET_IDLE 0x0A // Code for Set Idle 140 | #define SET_PROTOCOL 0x0B // Code for Set Protocol 141 | 142 | // These are created in usb_descriptor.c 143 | extern const device_descriptor_t DESC_DEVICE; 144 | extern const configuration_descriptor_t DESC_CONFIG; 145 | extern const __code BYTE * __code DESC_STRINGs[3]; 146 | 147 | #endif /* _USB_DESCRIPTOR_H_ */ 148 | -------------------------------------------------------------------------------- /firmware/f38x_usb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #ifndef _USB_ISR_H_ 33 | #define _USB_ISR_H_ 34 | 35 | #include "c8051f380.h" 36 | #include "main.h" 37 | #include 38 | 39 | // Define wIndex bitmaps 40 | #define is_EP_IN(ep_address) ((ep_address) & (0x80)) 41 | #define EP_NUMBER(ep_address) ((ep_address) & ~(0x80)) 42 | #define IN_EP1 0x81 // Index values used by Set and Clear feature 43 | #define OUT_EP1 0x01 // commands for Endpoint_Halt 44 | #define IN_EP2 0x82 45 | #define OUT_EP2 0x02 46 | #define IN_EP3 0x83 47 | #define OUT_EP3 0x03 48 | 49 | // Define wValue bitmaps for Standard Feature Selectors 50 | #define DEVICE_REMOTE_WAKEUP 0x01 // Remote wakeup feature(not used) 51 | #define ENDPOINT_HALT 0x00 // Endpoint_Halt feature selector 52 | 53 | // Device Request Direction (bmRequestType bit7) 54 | #define DRD_MASK 0x80 // Mask for device request direction 55 | #define DRD_OUT 0x00 // OUT: host to device 56 | #define DRD_IN 0x80 // IN: device to host 57 | 58 | // Device Request Type (bmRequestType bit 6-5) 59 | #define DRT_MASK 0x60 // Mask for device request type 60 | #define DRT_STD 0x00 // Standard device request 61 | #define DRT_CLASS 0x20 // Class specific request 62 | #define DRT_VENDOR 0x40 // Vendor specific request 63 | 64 | // Device Request Recipient (bmRequestType bit4-0) 65 | #define DRR_MASK 0x1F // Mask for device request recipient 66 | #define DRR_DEVICE 0x00 // Device 67 | #define DRR_INTERFACE 0x01 // Interface 68 | #define DRR_ENDPOINT 0x02 // Endpoint 69 | 70 | // Define bmRequestType bitmaps 71 | #define OUT_DEVICE (DRD_OUT | DRT_STD | DRR_DEVICE) 72 | #define IN_DEVICE (DRD_IN | DRT_STD | DRR_DEVICE) 73 | #define OUT_INTERFACE (DRD_OUT | DRT_STD | DRR_INTERFACE) 74 | #define IN_INTERFACE (DRD_IN | DRT_STD | DRR_INTERFACE) 75 | #define OUT_ENDPOINT (DRD_OUT | DRT_STD | DRR_ENDPOINT) 76 | #define IN_ENDPOINT (DRD_IN | DRT_STD | DRR_ENDPOINT) 77 | 78 | #define OUT_CL_INTERFACE (DRD_OUT | DRT_CLASS | DRR_INTERFACE) 79 | #define IN_CL_INTERFACE (DRD_IN | DRT_CLASS | DRR_INTERFACE) 80 | 81 | #define OUT_VR_INTERFACE (DRD_OUT | DRT_VENDOR | DRR_INTERFACE) 82 | #define IN_VR_INTERFACE (DRD_IN | DRT_VENDOR | DRR_INTERFACE) 83 | 84 | // Setup Packet Type Definition 85 | typedef __xdata struct { 86 | BYTE bmRequestType; // Request recipient, type, and direction 87 | BYTE bRequest; // Specific standard request number 88 | WORD_t wValue; // varies according to request 89 | WORD_t wIndex; // varies according to request 90 | WORD_t wLength; // Number of bytes to transfer 91 | } ep0_setup_t; 92 | extern ep0_setup_t ep0_setup; 93 | 94 | typedef __xdata struct { 95 | BYTE *buf; 96 | unsigned int size; 97 | __code void (*callback)(); 98 | } ep0_data_t; 99 | extern ep0_data_t ep0_data; 100 | 101 | extern volatile __bit ep0_request_completed; 102 | 103 | #define ep0_register_data(_ptr, _size) { \ 104 | ep0_data.buf = _ptr; \ 105 | ep0_data.size = _size; \ 106 | ep0_data.callback = NULL; \ 107 | } 108 | #define ep0_reserve_data(_ptr, _size, _func) { \ 109 | ep0_data.buf = _ptr; \ 110 | ep0_data.size = _size; \ 111 | ep0_data.callback = _func; \ 112 | } 113 | 114 | // Define Endpoint States 115 | #define EP_IDLE 0x00 // This signifies Endpoint Idle State 116 | #define EP_TX 0x01 // Endpoint Transmit State 117 | #define EP_RX 0x02 // Endpoint Receive State 118 | #define EP_HALT 0x03 // Endpoint Halt State (return stalls) 119 | #define EP_STALL 0x04 // Endpoint Stall (send procedural stall next status phase) 120 | #define EP_ADDRESS 0x05 // Endpoint Address (change FADDR during next status phase) 121 | 122 | #define EP_OWNED_BY_USER 0x80 // Endpoint state owned by user 123 | #define ep_strip_owner(state) ((state) & ~EP_OWNED_BY_USER) 124 | 125 | extern BYTE __xdata usb_ep_stat[7]; 126 | #define DIR_IN 0x00 127 | #define DIR_OUT 0x04 128 | #define usb_ep0_status usb_ep_stat[0] 129 | #define usb_ep_status(dir, ep_number) \ 130 | usb_ep_stat[((dir == DIR_OUT) ? (3 + ep_number) : (ep_number))] 131 | 132 | unsigned int usb_write(BYTE* ptr_buf, unsigned int count, unsigned char index); 133 | unsigned int usb_fill(BYTE buf, unsigned int count, unsigned char index); 134 | unsigned int usb_read(BYTE* ptr_buf, unsigned int count, unsigned char index); 135 | unsigned int usb_skip(unsigned int count, unsigned char index); 136 | void usb_flush(unsigned char index); 137 | unsigned int usb_count_ep_out(unsigned char index); 138 | 139 | void usb_status_lock(unsigned char dir, unsigned char ep_index); 140 | void usb_status_unlock(unsigned char dir, unsigned char ep_index); 141 | void usb_stall(unsigned char dir, unsigned char ep_index, __code void(*)()); 142 | void usb_clear_halt(unsigned char dir, unsigned char ep_index); 143 | void usb0_init(); 144 | 145 | // Define device states 146 | typedef __xdata enum { 147 | DEV_ATTACHED = 0x00, // Device is in Attached State 148 | DEV_POWERED = 0x01, // Device is in Powered State 149 | DEV_DEFAULT = 0x02, // Device is in Default State 150 | DEV_ADDRESS = 0x03, // Device is in Addressed State 151 | DEV_CONFIGURED = 0x04, // Device is in Configured State 152 | DEV_SUSPENDED = 0x05, // Device is in Suspended State 153 | } usb_state_t; 154 | extern usb_state_t usb_state; 155 | 156 | typedef enum { 157 | USB_INACTIVE, 158 | USB_CABLE_CONNECTED, 159 | USB_CDC_READY, 160 | USB_CDC_ACTIVE, 161 | } usb_mode_t; 162 | extern volatile usb_mode_t usb_mode; 163 | 164 | extern volatile __xdata BYTE usb_frame_num; 165 | 166 | void usb_polling(); 167 | 168 | void usb_isr() __interrupt (INTERRUPT_USB0); 169 | 170 | #ifdef USE_ASM_FOR_SFR_MANIP 171 | #define CRITICAL_USB0(func) \ 172 | { \ 173 | {__asm anl _EIE1,SHARP ~0x02 __endasm; } \ 174 | { \ 175 | func; \ 176 | } \ 177 | {__asm orl _EIE1,SHARP 0x02 __endasm; } \ 178 | } 179 | #else 180 | #define CRITICAL_USB0(func) \ 181 | { \ 182 | EIE1 &= ~(0x02); \ 183 | { \ 184 | func; \ 185 | } \ 186 | EIE1 |= (0x02); \ 187 | } 188 | #endif 189 | 190 | #endif /* _USB_ISR_H_ */ 191 | -------------------------------------------------------------------------------- /firmware/gpib_io.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "gpib_io.h" 33 | #include "c8051f380.h" 34 | #include "main.h" 35 | #include "gpib.h" 36 | 37 | #define TE 0x10 38 | #define SC 0x20 39 | #define DC 0x40 40 | #define PE 0x80 41 | 42 | #define SRQ 0x01 43 | #define ATN 0x02 44 | #define EOI 0x04 45 | #define DAV 0x08 46 | #define NRFD 0x10 47 | #define NDAC 0x20 48 | #define IFC 0x40 49 | #define REN 0x80 50 | 51 | #ifdef USE_ASM_FOR_SFR_MANIP 52 | #define p0_hiz(port) {__asm orl _P0,SHARP (port) __endasm; } 53 | #define p0_low(port) {__asm anl _P0,SHARP ~(port) __endasm; } 54 | #define p2_hiz(port) {__asm orl _P2,SHARP (port) __endasm; } 55 | #define p2_low(port) {__asm anl _P2,SHARP ~(port) __endasm; } 56 | #else 57 | #define p0_hiz(port) (P0 |= (port)) 58 | #define p0_low(port) (P0 &= ~(port)) 59 | #define p2_hiz(port) (P2 |= (port)) 60 | #define p2_low(port) (P2 &= ~(port)) 61 | #endif 62 | 63 | static __bit is_talker; 64 | 65 | static void set_talker(){ 66 | if(!is_talker){ 67 | is_talker = TRUE; 68 | p2_hiz(EOI | DAV | NRFD | NDAC); 69 | p0_hiz(TE | PE); /* R[NDAC,NRFD], T[Data,DAV] */ 70 | } 71 | } 72 | 73 | static void set_listener(){ 74 | if(is_talker){ 75 | is_talker = FALSE; 76 | P1 = 0xFF; /* Float all data lines */ 77 | p2_hiz(EOI | DAV | NRFD | NDAC); 78 | p0_low(TE | PE); /* R[Data,DAV], T[NDAC,NRFD] */ 79 | p2_low(NRFD | NDAC); 80 | } 81 | } 82 | 83 | // Puts all the GPIB pins into their correct initial states. 84 | void gpib_io_init(){ 85 | // Initialize as a listener 86 | is_talker = TRUE; 87 | set_listener(); 88 | 89 | p2_hiz(ATN | IFC | SRQ | REN); 90 | if(gpib_config.is_controller){ 91 | p2_low(REN); 92 | p0_low(DC); // T[ATN], R[SRQ] 93 | p0_hiz(SC); // T[REN,IFC] 94 | }else{ 95 | p0_hiz(DC); // T[SRQ], R[ATN] 96 | p0_low(SC); // R[REN,IFC] 97 | } 98 | } 99 | 100 | static __xdata u8 timeout_10ms_max; 101 | 102 | void gpib_io_set_timeout(){ 103 | if(gpib_config.timeout_ms == 0){timeout_10ms_max = 0xFF;} // if 0, wait forever 104 | else{ 105 | u16 div10 = (gpib_config.timeout_ms + 9) / 10; 106 | if(div10 >= 0xFF){timeout_10ms_max = 0xFE;} // max timeout is 0xFE * 10 = 2540 ms 107 | timeout_10ms_max = (u8)(div10); 108 | } 109 | } 110 | 111 | u8 gpib_uniline(enum uniline_message_t msg){ 112 | switch(msg){ 113 | case GPIB_UNI_CMD_START: p2_low(ATN); break; 114 | case GPIB_UNI_CMD_END: p2_hiz(ATN); break; 115 | case GPIB_UNI_BUS_CLEAR_START: p2_low(IFC); break; 116 | case GPIB_UNI_BUS_CLEAR_END: p2_hiz(IFC); break; 117 | case GPIB_UNI_CHECK_SRQ_ASSERT: return !(P2 & SRQ); 118 | case GPIB_UNI_SRQ_ASSERT: p2_low(SRQ); break; 119 | case GPIB_UNI_SRQ_DEASSERT: p2_hiz(SRQ); break; 120 | } 121 | return 0; 122 | } 123 | 124 | static u8 wait_p2(u8 state, u8 mask){ 125 | timeout_10ms = 0; 126 | do{ 127 | if((P2 & mask) == state){return 0;} 128 | }while(timeout_10ms_max >= timeout_10ms); 129 | return 1; // timeout 130 | } 131 | 132 | static u8 putchar_internal(u8 c, u8 flags){ 133 | 134 | P1 = (c ^ 0xFF); // Put the byte on the data lines 135 | if(flags & GPIB_WRITE_USE_EOI){ 136 | p2_low(EOI); // Assert EOI 137 | } 138 | 139 | // Make sure that NRFD is high 140 | if(wait_p2(NRFD, NRFD)){ 141 | gpib_io_init(); 142 | return 0; 143 | } 144 | p2_low(DAV); // Inform listeners that the data is ready to be read 145 | 146 | // Wait for NDAC to go high, all listeners have accepted the byte 147 | if(wait_p2(NDAC, NDAC)){ 148 | gpib_io_init(); 149 | return 0; 150 | } 151 | p2_hiz(DAV | EOI); // Byte has been accepted by all, indicate byte is no longer valid 152 | 153 | return 1; 154 | } 155 | 156 | u8 gpib_putchar(char c, u8 flags){ 157 | 158 | set_talker(); 159 | if(putchar_internal(c, flags) == 0){return 0;} 160 | 161 | return 1; 162 | } 163 | 164 | u16 gpib_write(char *buf, u16 length, u8 flags){ 165 | u16 remain = length; 166 | u8 flags_without_eoi = flags & ~(GPIB_WRITE_USE_EOI); 167 | 168 | if(length == 0){return 0;} 169 | 170 | set_talker(); 171 | do{ // Loop through each character, write to bus 172 | if(putchar_internal(*buf++, (remain >= 1) ? flags_without_eoi : flags) == 0){ 173 | return length - remain; 174 | } 175 | }while(--remain); 176 | 177 | return length - remain; 178 | } 179 | 180 | static int getchar_internal(){ 181 | int res; 182 | 183 | // Assuming both NDAC and NRFD are LOW. 184 | 185 | // Raise NRFD, telling the talker we are ready for the next byte 186 | p2_hiz(NRFD); 187 | // Wait for DAV to go low (talker informing us the byte is ready) 188 | if(wait_p2(0, DAV)){ 189 | gpib_io_init(); 190 | return -1; // timeout 191 | } 192 | // Assert NRFD, informing talker to not change the data lines 193 | p2_low(NRFD); 194 | 195 | // Read port, and flip all bits since GPIB uses negative logic. 196 | res = (u8)(P1 ^ 0xFF); 197 | if(!(P2 & EOI)){res += 0x100;} // END 198 | if(!(P2 & ATN)){res += 0x200;} // CMD 199 | 200 | // Un-assert NDAC, informing talker that we have accepted the byte 201 | p2_hiz(NDAC); 202 | // Wait for DAV to go high (talker knows that we have read the byte) 203 | if(wait_p2(DAV, DAV)){ 204 | gpib_io_init(); 205 | return -1; // timeout 206 | } 207 | // Low NDAC to prepare for next byte 208 | p2_low(NDAC); 209 | 210 | return res; 211 | } 212 | 213 | int gpib_getchar(){ 214 | set_listener(); 215 | return getchar_internal(); 216 | } 217 | 218 | u16 gpib_read(void (*push)(char), u8 flags){ 219 | u16 read_count = 0; 220 | int res; 221 | char c; 222 | __bit last_char_is_cr = FALSE; 223 | 224 | // Make correspond receiving and transmitting terminators, different from Prologic impl. 225 | u8 terminator 226 | = (flags & GPIB_READ_UNTIL_EOI) ? 3 : gpib_config.eos; 227 | 228 | set_listener(); 229 | while(1){ 230 | res = getchar_internal(); 231 | if(GPIB_GETCHAR_IS_ERROR(res)){break;} 232 | read_count++; 233 | c = GPIB_GETCHAR_TO_DATA(res); 234 | push(c); 235 | if(GPIB_GETCHAR_IS_EOI(res)){ 236 | if(gpib_config.eot){ 237 | push(gpib_config.eot_char); 238 | } 239 | break; 240 | } 241 | if(c == '\r'){ 242 | if(terminator == 1){break;} 243 | last_char_is_cr = TRUE; 244 | }else{ 245 | if(c == '\n'){ 246 | if((terminator == 2) 247 | || ((last_char_is_cr) && (terminator == 0))){break;} 248 | } 249 | last_char_is_cr = FALSE; 250 | } 251 | } 252 | 253 | return read_count; 254 | } 255 | -------------------------------------------------------------------------------- /firmware/parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "parser.h" 33 | 34 | #include 35 | 36 | #if !defined(LOCAL_TEST) 37 | #define LOCAL_TEST 0 38 | #endif 39 | 40 | #if LOCAL_TEST 41 | #include 42 | #endif 43 | 44 | const __code char * __code command_str[] = { 45 | "addr", 46 | "auto", 47 | "clr", 48 | "eoi", 49 | "eos", 50 | "eot_enable", 51 | "eot_char", 52 | "ifc", 53 | "llo", 54 | "loc", 55 | "lon", 56 | "mode", 57 | "read", 58 | "read_tmo_ms", 59 | "rst", 60 | "savecfg", 61 | "spoll", 62 | "srq", 63 | "status", 64 | "trg", 65 | "ver", 66 | "help", 67 | "debug", 68 | }; 69 | 70 | static enum command_t check_cmd(__xdata char *str, u8 len){ 71 | #if LOCAL_TEST 72 | { 73 | int i; 74 | printf("check_cmd: "); 75 | for(i = 0; i < len; ++i){ 76 | putchar(str[i]); 77 | } 78 | printf("\n"); 79 | } 80 | #endif 81 | #define check_str(cmd) { \ 82 | if(memcmp(command_str[cmd], str, len) == 0){ \ 83 | return cmd; \ 84 | } \ 85 | } 86 | switch(len){ 87 | case 3: 88 | check_str(CMD_CLR); 89 | check_str(CMD_EOI); 90 | check_str(CMD_EOS); 91 | check_str(CMD_IFC); 92 | check_str(CMD_LLO); 93 | check_str(CMD_LOC); 94 | check_str(CMD_LON); 95 | check_str(CMD_RST); 96 | check_str(CMD_SRQ); 97 | check_str(CMD_TRG); 98 | check_str(CMD_VER); 99 | break; 100 | case 4: 101 | check_str(CMD_ADDR); 102 | check_str(CMD_AUTO); 103 | check_str(CMD_MODE); 104 | check_str(CMD_READ); 105 | check_str(CMD_HELP); 106 | break; 107 | case 5: 108 | check_str(CMD_SPOLL); 109 | check_str(CMD_DEBUG); 110 | break; 111 | case 6: 112 | check_str(CMD_STATUS); 113 | break; 114 | case 7: 115 | check_str(CMD_SAVECFG); 116 | break; 117 | case 8: 118 | check_str(CMD_EOT_CHAR); 119 | break; 120 | case 10: 121 | check_str(CMD_EOT_ENABLE); 122 | break; 123 | case 11: 124 | check_str(CMD_READ_TMO_MS); 125 | break; 126 | } 127 | #undef check_str 128 | return CMD_ERROR; 129 | } 130 | 131 | static int check_arg(__xdata char *str, u8 len){ 132 | int res; 133 | #if defined(__SDCC) || defined(SDCC) || LOCAL_TEST 134 | int i; 135 | for(res = 0, i = 0; i < len; ++i){ 136 | int v = str[i] - '0'; 137 | if((v < 0) || (v > 9)){return ARG_ERR;} 138 | res *= 10; 139 | res += v; 140 | } 141 | #else 142 | char *end; 143 | str[len] = '\0'; 144 | res = strtol(str, &end, 0); 145 | if((((__xdata char *)end) - str) != len){ 146 | return ARG_ERR; 147 | } 148 | #endif 149 | return res; 150 | } 151 | 152 | static __xdata enum { 153 | THROUGH, 154 | ON_FIRST_CHAR_PLUS, 155 | ON_COMMAND_OR_ARG, 156 | } state = THROUGH; 157 | static __bit on_escape = FALSE; 158 | static __bit last_char_is_cr = FALSE; 159 | 160 | void parser_reset(){ 161 | state = THROUGH; 162 | on_escape = FALSE; 163 | last_char_is_cr = FALSE; 164 | } 165 | 166 | #define PARSED_INFO_BUFFERD_ARGS \ 167 | (sizeof(((parsed_info_t *)(0))->arg) / sizeof(((parsed_info_t *)(0))->arg[0])) 168 | 169 | /* Parse Prologix protocol and run command */ 170 | void parse(char c){ 171 | static __xdata char buf[16]; 172 | static __xdata u8 buf_index; 173 | static parsed_info_t parsed_info; 174 | enum {CHAR_NORMAL, CHAR_PLUS, CHAR_TERMINATOR, CHAR_SEPARATOR} c_attr = CHAR_NORMAL; 175 | __bit current_char_is_cr = FALSE; 176 | 177 | if(on_escape){ 178 | on_escape = FALSE; 179 | }else{ 180 | switch(c){ 181 | case 0x1B: //'\e': // sdcc do not support '\e' 182 | on_escape = TRUE; 183 | return; 184 | case '+': 185 | c_attr = CHAR_PLUS; 186 | break; 187 | case '\r': 188 | current_char_is_cr = TRUE; 189 | c_attr = CHAR_TERMINATOR; 190 | break; 191 | case '\n': 192 | if(last_char_is_cr){ 193 | last_char_is_cr = FALSE; 194 | return; 195 | } // reduce crlf. 196 | c_attr = CHAR_TERMINATOR; 197 | break; 198 | case ' ': 199 | c_attr = CHAR_SEPARATOR; 200 | break; 201 | } 202 | } 203 | 204 | last_char_is_cr = current_char_is_cr; 205 | 206 | switch(state){ 207 | case ON_FIRST_CHAR_PLUS: 208 | if(c_attr == CHAR_PLUS){ 209 | state = ON_COMMAND_OR_ARG; 210 | buf_index = 0; 211 | parsed_info.args = -1; 212 | break; 213 | } 214 | state = THROUGH; 215 | case THROUGH: 216 | parsed_info.cmd = CMD_TALK; 217 | if(c_attr == CHAR_PLUS){ 218 | state = ON_FIRST_CHAR_PLUS; 219 | }else{ 220 | if(c_attr == CHAR_TERMINATOR){ 221 | parsed_info.args = 0; 222 | }else{ 223 | parsed_info.args = 1; 224 | parsed_info.arg[0] = c; 225 | } 226 | run_command(&parsed_info); 227 | } 228 | break; 229 | case ON_COMMAND_OR_ARG: 230 | if(c_attr == CHAR_PLUS){break;} 231 | if(c_attr == CHAR_NORMAL){ 232 | if(buf_index < (sizeof(buf) - 1)){ 233 | buf[buf_index++] = c; 234 | } 235 | break; 236 | } 237 | 238 | // TERMINATOR or SEPARATOR 239 | if(buf_index > 0){ 240 | if(parsed_info.args < 0){ 241 | // check command in buf. 242 | parsed_info.cmd = check_cmd(buf, buf_index); 243 | }else{ 244 | // check arg in buf. 245 | while(parsed_info.args <= PARSED_INFO_BUFFERD_ARGS){ 246 | if((parsed_info.cmd == CMD_READ) && (parsed_info.args == 0)){ 247 | if((buf_index == 3) && (memcmp(buf, "eoi", buf_index) == 0)){ 248 | parsed_info.arg[parsed_info.args] = ARG_EOI; 249 | break; 250 | } 251 | } 252 | parsed_info.arg[parsed_info.args] = check_arg(buf, buf_index); 253 | break; 254 | } 255 | } 256 | buf_index = 0; 257 | parsed_info.args++; 258 | } 259 | 260 | if(c_attr == CHAR_TERMINATOR){ 261 | state = THROUGH; 262 | //if(parsed_info.cmd == CMD_ERROR){break;} 263 | run_command(&parsed_info); 264 | } 265 | break; 266 | } 267 | } 268 | 269 | #if LOCAL_TEST /* for local test */ 270 | 271 | #include 272 | 273 | void run_command(parsed_info_t *info){ 274 | printf("exec: %d, %d\n", info->cmd, info->args); 275 | if(info->cmd == CMD_TALK){ 276 | printf("exec talk"); 277 | if(info->args > 0){ 278 | char c = (char)(info->arg[0]); 279 | printf(" %c(%d)", isprint(c) ? c : ' ', c); 280 | } 281 | printf("\n"); 282 | }else{ 283 | int i; 284 | int args = sizeof(info->arg) / sizeof(info->arg[0]); 285 | 286 | if(args > info->args){args = info->args;} 287 | if(args == 0){return;} 288 | 289 | printf("exec with arg:"); 290 | for(i = 0; i < args; ++i){ 291 | printf( " %d", info->arg[i]); 292 | } 293 | printf("\n"); 294 | } 295 | } 296 | 297 | int main(int argc, char *argv[]){ 298 | 299 | if(argc == 1){ 300 | char c; 301 | while((c = getchar()) != EOF){ 302 | printf("\nin: %c(%d)\n", isprint(c) ? c : ' ', c); 303 | parse(c); 304 | } 305 | printf("\nin: %c(%d)\n", ' ', '\n'); 306 | parse('\n'); 307 | return; 308 | } 309 | 310 | int i, j; 311 | for(j = 1; j < argc; j++){ 312 | if(j > 1){ 313 | printf("\nin: %c(%d)\n", ' ', ' '); 314 | parse(' '); 315 | } 316 | for(i = 0; i < strlen(argv[j]); ++i){ 317 | printf("\nin: %c(%d)\n", isprint(argv[j][i]) ? argv[j][i] : ' ', argv[j][i]); 318 | parse(argv[j][i]); 319 | } 320 | } 321 | if(argc > 1){ 322 | printf("\nin: %c(%d)\n", ' ', '\n'); 323 | parse('\n'); 324 | } 325 | 326 | return 0; 327 | } 328 | 329 | #endif 330 | -------------------------------------------------------------------------------- /firmware/usb_descriptor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "main.h" 33 | #include "usb_descriptor.h" 34 | 35 | #include "usb_cdc.h" 36 | 37 | #define DESC_DEVICE_bcdUSB 0x0200 38 | #define DESC_DEVICE_bcdDevice 0x0000 39 | #define DESC_DEVICE_iManufacturer 0x01 40 | #define DESC_DEVICE_iProduct 0x02 41 | #define DESC_DEVICE_idVendor 0x10C4 // Silicon Laboratories 42 | 43 | /* 44 | * Descriptor Declarations for CDC-ACM 45 | */ 46 | const __code device_descriptor_t DESC_DEVICE = { 47 | sizeof(device_descriptor_t), // bLength(0x12) 48 | DSC_TYPE_DEVICE, // bDescriptorType 49 | {DESC_DEVICE_bcdUSB}, // bcdUSB 50 | #ifndef CDC_IS_REPLACED_BY_FTDI 51 | 0x02, // bDeviceClass (Communication Class) 52 | 0x00, // bDeviceSubClass 53 | 0x00, // bDeviceProtocol 54 | #else 55 | 0x00, // bDeviceClass (defined at interface level) 56 | 0x00, // bDeviceSubClass 57 | 0x00, // bDeviceProtocol 58 | #endif 59 | PACKET_SIZE_EP0, // bMaxPacketSize0 60 | #ifndef CDC_IS_REPLACED_BY_FTDI 61 | {DESC_DEVICE_idVendor}, // idVendor 62 | {0x8A5F}, // idProduct 63 | {DESC_DEVICE_bcdDevice}, // bcdDevice 64 | #else 65 | {0x0403}, // idVendor => FTDI 66 | {0x6001}, // idProduct => FT232R 67 | {0x0600}, // bcdDevice => (FT232R) 68 | #endif 69 | DESC_DEVICE_iManufacturer, // iManufacturer 70 | DESC_DEVICE_iProduct, // iProduct 71 | 0x04, // iSerialNumber 72 | 0x01 // bNumConfigurations 73 | }; //end of DEVICE 74 | 75 | #define DESC_CONFIG_bConfigurationValue 0x01 76 | #define DESC_CONFIG_iConfiguration 0x00 77 | #define DESC_CONFIG_bmAttributes 0x80 78 | #define DESC_CONFIG_MaxPower 0xFA // 500mA 79 | 80 | const __code configuration_descriptor_t DESC_CONFIG = { 81 | sizeof(configuration_descriptor_t),// Length(0x09) 82 | DSC_TYPE_CONFIG, // Type 83 | #ifndef CDC_IS_REPLACED_BY_FTDI 84 | {config_length_total(2, 3) // + ((interface : 2) + (endpoint : 3)) 85 | + cdc_config_length()}, // + cdc 86 | 0x02, // NumInterfaces(C) 87 | #else 88 | {config_length_total(1, 2)}, // + ((interface : 1) + (endpoint : 2)) 89 | 0x01, // NumInterfaces(C(FTDI)) 90 | #endif 91 | DESC_CONFIG_bConfigurationValue, // bConfigurationValue 92 | DESC_CONFIG_iConfiguration, // iConfiguration 93 | DESC_CONFIG_bmAttributes, // bmAttributes 94 | DESC_CONFIG_MaxPower // MaxPower 95 | }; //end of CONFIG 96 | 97 | #ifndef CDC_IS_REPLACED_BY_FTDI 98 | const __code interface_descriptor_t DESC_INTERFACE1 = { // Communication Class 99 | sizeof(interface_descriptor_t),// bLength 100 | DSC_TYPE_INTERFACE, // bDescriptorType 101 | 0x00, // bInterfaceNumber 102 | 0x00, // bAlternateSetting 103 | 0x01, // bNumEndpoints 104 | 0x02, // bInterfaceClass (Communication Class) 105 | 0x02, // bInterfaceSubClass (Abstract Control Model) 106 | 0x01, // bInterfaceProcotol (V.25ter, Common AT commands) 107 | 0x00 // iInterface 108 | }; // end of INTERFACE1 109 | 110 | const __code cdc_descriptor_t DESC_CDC = { 111 | { // Header Functional Descriptor 112 | sizeof(cdc_header_func_descriptor_t), 113 | DSC_TYPE_CS_INTERFACE, // bDescriptorType (CS_INTERFACE) 114 | DSC_SUBTYPE_CS_HEADER_FUNC, // bDescriptorSubtype (Header Functional) 115 | {0x0110} // bcdCDC (CDC spec release number, 1.1) 116 | }, 117 | { // Abstract Control Management Functional Descriptor 118 | sizeof(cdc_abst_control_mana_descriptor_t), 119 | DSC_TYPE_CS_INTERFACE, // bDescriptorType (CS_INTERFACE) 120 | DSC_SUBTYPE_CS_ABST_CNTRL, // bDescriptorSubtype (Abstract Control Management) 121 | 0x06 // bmCapabilities (Supports Send_Break, Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State) 122 | }, 123 | { // Union Functional Descriptor 124 | sizeof(cdc_union_func_descriptor_t), 125 | DSC_TYPE_CS_INTERFACE, // bDescriptorType (CS_INTERFACE) 126 | DSC_SUBTYPE_CS_UNION_FUNC, // bDescriptorSubtype (Union Functional) 127 | 0x00, // bMasterInterface (Interface number master interface in the union) 128 | 0x01 // bSlaveInterface0 (Interface number slave interface in the union) 129 | }, 130 | { // Call Management Functional Descriptor 131 | sizeof(cdc_call_man_func_descriptor_t), 132 | DSC_TYPE_CS_INTERFACE, // bDescriptorType (CS_INTERFACE) 133 | DSC_SUBTYPE_CS_CALL_MAN, // bDescriptorSubtype (Call Management) 134 | 0x01, // bmCapabilities (only over Communication Class IF / handles itself) 135 | 0x01 // bDataInterface (Interface number of Data Class interface) 136 | } 137 | }; 138 | 139 | const __code endpoint_descriptor_t DESC_ENDPOINT1 = { 140 | sizeof(endpoint_descriptor_t), // bLength 141 | DSC_TYPE_ENDPOINT, // bDescriptorType 142 | IN_EP1, // bEndpointAddress 143 | DSC_EP_INTERRUPT, // bmAttributes 144 | {PACKET_SIZE_EP1}, // MaxPacketSize 145 | 0x10 // bInterval 146 | }; //end of ENDPOINT1 147 | #endif 148 | 149 | const interface_descriptor_t DESC_INTERFACE2 = { // Data Interface Class 150 | sizeof(interface_descriptor_t),// bLength 151 | DSC_TYPE_INTERFACE, // bDescriptorType 152 | #ifndef CDC_IS_REPLACED_BY_FTDI 153 | 0x01, // bInterfaceNumber 154 | #else 155 | 0x00, // bInterfaceNumber 156 | #endif 157 | 0x00, // bAlternateSetting 158 | 0x02, // bNumEndpoints 159 | #ifndef CDC_IS_REPLACED_BY_FTDI 160 | 0x0A, // bInterfaceClass (Data Interface Class) 161 | 0x00, // bInterfaceSubClass 162 | 0x00, // bInterfaceProcotol (No class specific protocol required) 163 | #else 164 | 0xFF, // bInterfaceClass (Data Interface Class) 165 | 0xFF, // bInterfaceSubClass 166 | 0xFF, // bInterfaceProcotol (No class specific protocol required) 167 | #endif 168 | 0x00 // iInterface 169 | }; //end of INTERFACE2 170 | 171 | const __code endpoint_descriptor_t DESC_ENDPOINT2 = { 172 | sizeof(endpoint_descriptor_t), // bLength 173 | DSC_TYPE_ENDPOINT, // bDescriptorType 174 | IN_EP2, // bEndpointAddress 175 | DSC_EP_BULK, // bmAttributes 176 | {PACKET_SIZE_EP2}, // MaxPacketSize 177 | 0 // bInterval 178 | }; //end of ENDPOINT2 179 | 180 | const __code endpoint_descriptor_t DESC_ENDPOINT3 = { 181 | sizeof(endpoint_descriptor_t), // bLength 182 | DSC_TYPE_ENDPOINT, // bDescriptorType 183 | OUT_EP2, // bEndpointAddress 184 | DSC_EP_BULK, // bmAttributes 185 | {PACKET_SIZE_EP2}, // MaxPacketSize 186 | 0 // bInterval 187 | }; //end of ENDPOINT3 188 | 189 | const __code BYTE DESC_STRING1[] = { 190 | sizeof(DESC_STRING1), DSC_TYPE_STRING, 191 | 'n', 0, 192 | 'a', 0, 193 | 'r', 0, 194 | 'u', 0, 195 | 'o', 0, 196 | 'k', 0, 197 | 'a', 0, 198 | '.', 0, 199 | 'o', 0, 200 | 'r', 0, 201 | 'g', 0, 202 | }; //end of String1_Desc 203 | 204 | const __code BYTE DESC_STRING2[] = { 205 | sizeof(DESC_STRING2), DSC_TYPE_STRING, 206 | 'g', 0, 207 | 'p', 0, 208 | 'i', 0, 209 | 'b', 0, 210 | '-', 0, 211 | 'u', 0, 212 | 's', 0, 213 | 'b', 0, 214 | }; //end of String2_Desc 215 | 216 | const __code BYTE DESC_STRING3[] = { 217 | sizeof(DESC_STRING3), DSC_TYPE_STRING, 218 | 'C', 0, 219 | 'D', 0, 220 | 'C', 0, 221 | '.', 0, 222 | 'X', 0, 223 | 'X', 0, 224 | 'X', 0, 225 | 'X', 0, 226 | }; //end of String4_Desc 227 | 228 | const __code BYTE * __code DESC_STRINGs[3] = { 229 | DESC_STRING1, 230 | DESC_STRING2, 231 | DESC_STRING3, 232 | }; 233 | -------------------------------------------------------------------------------- /firmware/usb_cdc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | 35 | #include "c8051f380.h" 36 | #include "main.h" 37 | #include "f38x_usb_register.h" 38 | #include "f38x_usb.h" 39 | 40 | #include "usb_cdc.h" 41 | #include "util.h" 42 | 43 | // bitmap for set_line_state 44 | #define CDC_DTR 0x01 45 | #define CDC_RTS 0x02 46 | 47 | // bitmap for update_line_state 48 | #define CDC_DCD 0x01 // 49 | #define CDC_DSR 0x02 // data set ready 50 | #define CDC_BREAK 0x04 // break reception 51 | #define CDC_RI 0x08 // ring indicator 52 | #define CDC_FRAME 0x10 // frame error 53 | #define CDC_PARITY 0x20 // parity error 54 | #define CDC_OVRRUN 0x40 // overrun error 55 | #define CDC_CTS 0x80 // clear to send 56 | 57 | static u16 cdc_rx_size(); 58 | 59 | void cdc_polling(){ 60 | static __xdata u8 previous_frame_num = usb_frame_num & 0xF0; 61 | u8 current_frame_num = usb_frame_num & 0xF0; // per 16 frames 62 | 63 | if(previous_frame_num == current_frame_num){ 64 | return; 65 | } 66 | previous_frame_num = current_frame_num; 67 | 68 | cdc_tx(NULL, 0); // flush 69 | 70 | #ifndef CDC_IS_REPLACED_BY_FTDI 71 | /*{ 72 | // ResponseAvailable 73 | static const __code u8 buf[] = { 74 | 0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 75 | }; 76 | usb_write(buf, sizeof(buf), CDC_COM_EP_IN); 77 | }*/ 78 | { 79 | // SerialState 80 | static const __code u8 buf[] = { 81 | 0xA1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 82 | 0x03, 0x00 83 | }; 84 | usb_write(buf, sizeof(buf), CDC_COM_EP_IN); 85 | } 86 | #endif 87 | } 88 | 89 | // line coding structure and its default value 90 | static cdc_line_coding_t __xdata uart_line_coding = { 91 | {le_u32(115200)}, // baudrate 92 | 0, // stop bit: 0-1, 1-1.5, 2-2 93 | 0, // parity: 0-none, 1-odd, 2-even, 3-mark, 4-space 94 | 8 // data bits: 5,6,7,8,16 95 | }; 96 | 97 | static __xdata u8 ep0_data_buf[8]; 98 | 99 | // called at the end of data stage 100 | static void set_line_coding_complete(){ 101 | if(memcmp(&uart_line_coding, ep0_data_buf, sizeof(cdc_line_coding_t)) != 0){ 102 | memcpy(&uart_line_coding, ep0_data_buf, sizeof(cdc_line_coding_t)); 103 | } 104 | } 105 | 106 | // Line status output 107 | static volatile __bit uart_DTR = FALSE; // Line status output 108 | static volatile __bit uart_RTS = FALSE; 109 | 110 | static void set_line_state(u8 st){ 111 | uart_DTR = (st & CDC_DTR); 112 | uart_RTS = (st & CDC_RTS); 113 | } 114 | 115 | static void send_break(u16 dur){} 116 | 117 | #ifdef CDC_IS_REPLACED_BY_FTDI 118 | 119 | #define PORT_RESET 0x00 120 | #define MODEM_CTRL 0x01 121 | #define SET_FLOW_CTRL 0x02 122 | #define SET_BAUD_RATE 0x03 123 | #define SET_DATA 0x04 124 | #define GET_MODEM_STATUS 0x05 125 | #define SET_EVENT_CHAR 0x06 126 | #define SET_ERROR_CHAR 0x07 127 | #define SET_LATENCY_TIMER 0x09 128 | #define GET_LATENCY_TIMER 0x10 129 | #define READ_EEPROM 0x90 130 | #define WRITE_EEPROM 0x91 131 | #define ERACE_EEPROM 0x92 132 | 133 | /* 134 | * Ref) FT232R 135 | * 0000 : 00 40 03 04 01 60 00 00 136 | * A0 2D 08 00 00 00 98 0A @. .. `. .. .. .. .. .. 137 | * 0010 : A2 20 C2 12 23 10 05 00 138 | * 0A 03 46 00 54 00 44 00 .. .. .. .. .. .F .T .D 139 | * 0020 : 49 00 20 03 46 00 54 00 140 | * 32 00 33 00 32 00 52 00 .I .. .F .T .2 .3 .2 .R 141 | * 0030 : 20 00 55 00 53 00 42 00 142 | * 20 00 55 00 41 00 52 00 .. .U .S .B .. .U .A .R 143 | * 0040 : 54 00 12 03 41 00 36 00 144 | * 52 00 48 00 47 00 55 00 .T .. .A .6 .R .H .G .U 145 | * 0050 : 37 00 53 00 00 00 01 00 146 | * 00 00 00 00 00 00 00 00 .7 .S .. .. .. .. .. .. 147 | * 0060 : 00 00 00 00 00 00 00 00 148 | * 00 00 00 00 00 00 00 00 .. .. .. .. .. .. .. .. 149 | * 0070 : 00 00 00 00 00 00 00 00 150 | * 00 00 00 00 00 00 E2 18 .. .. .. .. .. .. .. .. 151 | * 0080 : 29 04 D6 FB 00 00 75 E2 152 | * 0F 60 42 00 00 00 00 00 .. .. .. .u `. .B .. .. 153 | * 0090 : 00 00 00 00 00 00 00 00 154 | * 36 41 51 51 5A 4C 55 55 .. .. .. .. A6 QQ LZ UU 155 | */ 156 | 157 | static const __code unsigned char ftdi_rom[] = { 158 | 0x00, 0x40, 0xC4, 0x10, 0x97, 0x01, 0x00, 0x00, // 0x08 159 | 0xA0, 0x2D, 0x08, 0x00, 0x00, 0x00, 0x98, 0x0E, // 0x10 160 | 0xA6, 0x12, 0xB8, 0x10, 0x23, 0x10, 0x05, 0x00, // 0x18 161 | 0x0E, 0x03, 0x66, 0x00, 0x65, 0x00, 0x6E, 0x00, // 0x20 162 | 0x72, 0x00, 0x69, 0x00, 0x72, 0x00, 0x12, 0x03, // 0x28 163 | 0x53, 0x00, 0x79, 0x00, 0x6C, 0x00, 0x70, 0x00, // 0x30 164 | 0x68, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, // 0x38 165 | 0x10, 0x03, 0x41, 0x00, 0x36, 0x00, 0x52, 0x00, // 0x40 166 | 0x48, 0x00, 0x47, 0x00, 0x37, 0x00, 0x53, 0x00, // 0x48 167 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 170 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 171 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 172 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x91, // 0x80 174 | 175 | 0x23, 0x04, 0xDC, 0xFB, 0x00, 0x00, 0xD8, 0x07, 176 | 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 178 | 0x33, 0x41, 0x37, 0x4F, 0x46, 0x30, 0x55, 0x36, 179 | 180 | /* 181 | 0x00, 0x6c, 0x6f, 0x67, 0x2e, 0x64, 0x61, 0x74, // 0x88 182 | 0x00, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, // 0x90 183 | 0x64, 0x61, 0x74, 0x00, 0x12, 0x01, 0x00, 0x02, // 0x98 184 | 0xef, 0x02, 0x01, 0x40, 0xc4, 0x10, 0x97, 0x01, // 0xA0 185 | 0x00, 0x00, 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, // 0xA8 186 | 0x3f, 0x00, 0x02, 0x01, 0x00, 0x80, 0x0f, 0x08, // 0xB0 187 | 0x0b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, // 0xB8 188 | 0x04, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, // 0xC0 189 | 0x07, 0x05, 0x82, 0x03, 0x40, 0x00, 0x01, 0x07, // 0xC8 190 | 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x09, 0x04, // 0xD0 191 | 0x01, 0x00, 0x02, 0x08, 0x06, 0x50, 0x00, 0x07, // 0xD8 192 | 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, // 0xE0 193 | 0x03, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, // 0xE8 194 | 0x04, 0x2a, 0x03, 0x53, 0x00, 0x69, 0x00, 0x6c, // 0xF0 195 | 0x00, 0x69, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, // 0xF8 196 | 0x00, 0x20, 0x00, 0x4c, 0x00, 0x61, 0x00, 0x62, // 0x100 197 | */ 198 | }; // 128 (+ 128) bytes TODO: where is PnP flag? 199 | 200 | // HEADER0 -- Modem Status 201 | #define HEADER0_SIGN 0x01 // 0.B0..B3 Reserved 202 | #define HEADER0_CTS (1 << 4) // 0.B4 Clear to Send (CTS) 203 | #define HEADER0_DSR (1 << 5) // 0.B5 Data Set Ready (DSR) 204 | #define HEADER0_RI (1 << 6) // 0.B6 Ring Indicator (RI) 205 | #define HEADER0_RLSD (1 << 7) // 0.B7 Receive Line Signal Detect (RLSD) 206 | 207 | // HEADER1 -- Line Status 208 | #define HEADER1_DR 1 // 1.B0 Data Ready (DR) 209 | #define HEADER1_OE (1 << 1) // 1.B1 Overrun Error (OE) 210 | #define HEADER1_PE (1 << 2) // 1.B2 Parity Error (PE) 211 | #define HEADER1_FE (1 << 3) // 1.B3 Framing Error (FE) 212 | #define HEADER1_BI (1 << 4) // 1.B4 Break Interrupt (BI) 213 | #define HEADER1_THRE (1 << 5) // 1.B5 Transmitter Holding Register (THRE) 214 | #define HEADER1_TEMT (1 << 6) // 1.B6 Transmitter Empty (TEMT) 215 | #define HEADER1_FIFO (1 << 7) // 1.B7 Error in RCVR FIFO 216 | 217 | #else 218 | 219 | /** 220 | * Send_Encapsulated_Command 221 | * 222 | * Nothing to do other than unloading the data sent in the data stage. 223 | */ 224 | static void cdc_Send_Encapsulated_Command(){ 225 | if((ep0_setup.bmRequestType == OUT_CL_INTERFACE) 226 | && (ep0_setup.wValue.i == 0 ) 227 | && (ep0_setup.wLength.i <= sizeof(cdc_line_coding_t))){ 228 | 229 | ep0_reserve_data( 230 | ep0_data_buf, 231 | min(sizeof(ep0_data_buf), ep0_setup.wLength.i), 232 | NULL 233 | ); 234 | usb_ep0_status = EP_RX; 235 | ep0_request_completed = TRUE; 236 | } 237 | } 238 | 239 | /** 240 | * Get_Encapsulated_Command 241 | * 242 | * Return a zero-length packet 243 | */ 244 | static void cdc_Get_Encapsulated_Command(){ 245 | if((ep0_setup.bmRequestType == IN_CL_INTERFACE) 246 | && (ep0_setup.wValue.i == 0)){ 247 | 248 | ep0_register_data(ep0_data_buf, 0); // Send ZLP 249 | usb_ep0_status = EP_TX; 250 | ep0_request_completed = TRUE; 251 | } 252 | } 253 | 254 | /** 255 | * Set_Line_Coding 256 | * 257 | * Unload the line coding structure (7 bytes) sent in the data stage. 258 | * Apply this setting to the UART 259 | * Flush the communication buffer 260 | * 261 | * Line Coding Structure (7 bytes) 262 | * 0-3 dwDTERate Data terminal rate (baudrate), in bits per second (LSB first) 263 | * 4 bCharFormat Stop bits: 0 - 1 Stop bit, 1 - 1.5 Stop bits, 2 - 2 Stop bits 264 | * 5 bParityType Parity: 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space 265 | * 6 bDataBits Data bits: 5, 6, 7, 8, 16 266 | */ 267 | static void cdc_Set_Line_Coding(){ 268 | if((ep0_setup.bmRequestType == OUT_CL_INTERFACE) 269 | && (ep0_setup.wValue.i == 0) 270 | && (ep0_setup.wLength.i == sizeof(cdc_line_coding_t))){ 271 | 272 | ep0_reserve_data( 273 | ep0_data_buf, 274 | sizeof(cdc_line_coding_t), 275 | set_line_coding_complete 276 | ); 277 | usb_ep0_status = EP_RX; 278 | ep0_request_completed = TRUE; 279 | } 280 | } 281 | 282 | /** 283 | * Get_Line_Coding 284 | * 285 | * Return the line coding structure 286 | */ 287 | static void cdc_Get_Line_Coding(){ 288 | if((ep0_setup.bmRequestType == IN_CL_INTERFACE) 289 | && (ep0_setup.wValue.i == 0) 290 | && (ep0_setup.wLength.i == sizeof(cdc_line_coding_t))){ 291 | 292 | ep0_register_data((u8 *)(&uart_line_coding), sizeof(cdc_line_coding_t)); 293 | usb_ep0_status = EP_TX; 294 | ep0_request_completed = TRUE; 295 | } 296 | } 297 | 298 | /** 299 | * Set_ControlLine_State 300 | * 301 | * Set/reset RTS/DTR according to wValue 302 | * wValue 303 | * bit 1 RTS 304 | * bit 0 DTR 305 | */ 306 | static void cdc_Set_ControlLine_State(){ 307 | if((ep0_setup.bmRequestType == OUT_CL_INTERFACE) 308 | && (ep0_setup.wLength.i == 0)){ 309 | set_line_state(ep0_setup.wValue.c[LSB] & (CDC_RTS | CDC_DTR)); 310 | ep0_request_completed = TRUE; 311 | } 312 | } 313 | 314 | /** 315 | * Send_Break 316 | * 317 | * Send break from UART TX port, for wValue (msec) duration. 318 | * wValue 319 | * 0xFFFF: continuous break 320 | * 0x0000: stop break 321 | */ 322 | static void cdc_Send_Break(){ 323 | if ((ep0_setup.bmRequestType == OUT_CL_INTERFACE) 324 | && (ep0_setup.wLength.i == 0) ){ 325 | send_break(ep0_setup.wValue.i); 326 | ep0_request_completed = TRUE; 327 | } 328 | } 329 | 330 | #endif 331 | 332 | u16 cdc_tx(u8 *buf, u16 size){ 333 | static __bit require_ZLP = FALSE; 334 | #ifdef CDC_IS_REPLACED_BY_FTDI 335 | #define TX_BUF_HEADER 2 336 | static __xdata u8 tx_packet[CDC_DATA_EP_IN_PACKET_SIZE-1] = { 337 | (HEADER0_SIGN | HEADER0_RI), // 0x41 338 | (HEADER1_THRE | HEADER1_TEMT)}; // 0x60 339 | #else 340 | #define TX_BUF_HEADER 0 341 | static __xdata u8 tx_packet[CDC_DATA_EP_IN_PACKET_SIZE]; 342 | #endif 343 | static __xdata u8 margin = sizeof(tx_packet) - TX_BUF_HEADER; 344 | u16 written = 0; 345 | u8 retry; 346 | if(size == 0){ // flush 347 | if(margin < (sizeof(tx_packet) - TX_BUF_HEADER)){ 348 | if(usb_write(tx_packet, sizeof(tx_packet) - margin, CDC_DATA_EP_IN) > 0){ 349 | if((sizeof(tx_packet) == CDC_DATA_EP_IN_PACKET_SIZE) && (margin == 0)){ 350 | require_ZLP = TRUE; 351 | }else{ 352 | require_ZLP = FALSE; 353 | } 354 | margin = sizeof(tx_packet) - TX_BUF_HEADER; 355 | } 356 | } 357 | if(require_ZLP){ 358 | require_ZLP = FALSE; 359 | usb_write(NULL, 0, CDC_DATA_EP_IN); 360 | } 361 | return 0; 362 | } 363 | do{ 364 | if(size < margin){ 365 | memcpy(&(tx_packet[sizeof(tx_packet) - margin]), buf, size); 366 | written += size; 367 | margin -= size; 368 | break; 369 | } 370 | memcpy(&(tx_packet[sizeof(tx_packet) - margin]), buf, margin); 371 | buf += margin; 372 | size -= margin; 373 | for(retry = 0; retry < 200; ++retry){ // timeout is approximately 1ms. 374 | if(usb_write(tx_packet, sizeof(tx_packet), CDC_DATA_EP_IN)){ 375 | if(sizeof(tx_packet) == CDC_DATA_EP_IN_PACKET_SIZE){ 376 | require_ZLP = TRUE; 377 | } 378 | break; 379 | } 380 | wait_us(5); 381 | } 382 | written += margin; 383 | margin = sizeof(tx_packet) - TX_BUF_HEADER; 384 | }while(size); 385 | return written; 386 | } 387 | 388 | #ifdef CDC_IS_REPLACED_BY_FTDI 389 | static __bit cdc_rx_need_skip = 1; 390 | 391 | static u16 cdc_rx_size(){ 392 | 393 | // The first byte is a control byte. 394 | u16 stored = usb_count_ep_out(CDC_DATA_EP_OUT); 395 | if(cdc_rx_need_skip){ 396 | switch(stored){ 397 | //case 1: 398 | //usb_skip(1, CDC_DATA_EP_OUT); 399 | case 0: 400 | return 0; 401 | default: 402 | //usb_skip(1, CDC_DATA_EP_OUT); 403 | //stored--; 404 | cdc_rx_need_skip = 0; 405 | } 406 | } 407 | // The first byte has been already skipped. 408 | return stored; 409 | } 410 | 411 | u16 cdc_rx(u8 *buf, u16 size){ 412 | // The first byte is a control byte. 413 | if(cdc_rx_size() <= size){ 414 | cdc_rx_need_skip = 1; 415 | } 416 | return usb_read(buf, size, CDC_DATA_EP_OUT); 417 | } 418 | #else 419 | 420 | static u16 cdc_rx_size(){ 421 | return usb_count_ep_out(CDC_DATA_EP_OUT); 422 | } 423 | 424 | u16 cdc_rx(u8 *buf, u16 size){ 425 | return usb_read(buf, size, CDC_DATA_EP_OUT); 426 | } 427 | #endif 428 | 429 | void usb_CDC_req(){ 430 | switch(ep0_setup.bRequest){ 431 | #ifdef CDC_IS_REPLACED_BY_FTDI 432 | case PORT_RESET: 433 | case SET_FLOW_CTRL: 434 | case SET_EVENT_CHAR: 435 | case SET_ERROR_CHAR: 436 | case SET_LATENCY_TIMER: 437 | case ERACE_EEPROM: 438 | ep0_request_completed = TRUE; 439 | break; 440 | case MODEM_CTRL: 441 | set_line_state(ep0_setup.wValue.c[LSB] & (CDC_RTS | CDC_DTR)); 442 | ep0_request_completed = TRUE; 443 | break; 444 | case SET_BAUD_RATE: { 445 | // TODO: bit16 support? 446 | unsigned int divisor; 447 | switch(divisor = ((ep0_setup.wValue.c[MSB] & 0xC0) >> 6)){ 448 | case 0x01: 449 | divisor = 4; 450 | break; 451 | case 0x03: 452 | divisor = 1; 453 | break; 454 | } 455 | divisor += (ep0_setup.wValue.i & 0x3FFF) << 3; 456 | uart_line_coding.baudrate.i = le_u32(24000000UL / divisor); 457 | ep0_request_completed = TRUE; 458 | break; 459 | } 460 | case SET_DATA: 461 | // USB is little endian 462 | uart_line_coding.stopbit = (ep0_setup.wValue.c[MSB] >> 3) & 0x07; 463 | uart_line_coding.parity = ep0_setup.wValue.c[MSB] & 0x07; 464 | uart_line_coding.databit = ep0_setup.wValue.c[LSB]; 465 | ep0_request_completed = TRUE; 466 | break; 467 | case GET_MODEM_STATUS: 468 | if(ep0_setup.wLength.c[LSB] <= 2){ 469 | ep0_data_buf[0] = 0x70; 470 | ep0_data_buf[1] = 0x00; 471 | ep0_register_data(ep0_data_buf, 472 | ep0_setup.wLength.c[LSB]); 473 | usb_ep0_status = EP_TX; 474 | ep0_request_completed = TRUE; 475 | } 476 | break; 477 | case GET_LATENCY_TIMER: 478 | //TODO: ep0_register_data(hoge, 1); 479 | usb_ep0_status = EP_TX; 480 | //ep0_request_completed = TRUE; 481 | break; 482 | case READ_EEPROM: 483 | ep0_register_data((u8 *)(&ftdi_rom[(ep0_setup.wIndex.i << 1)]), 484 | ep0_setup.wLength.c[LSB]); 485 | usb_ep0_status = EP_TX; 486 | ep0_request_completed = TRUE; 487 | break; 488 | case WRITE_EEPROM: 489 | //TODO: ep0_reserve_data(ep0_data_buf, ep0_setup.wLength.c[LSB], NULL); 490 | usb_ep0_status = EP_RX; 491 | //ep0_request_completed = TRUE; 492 | break; 493 | #else 494 | case SEND_ENCAPSULATED_COMMAND: 495 | cdc_Send_Encapsulated_Command(); 496 | break; 497 | case GET_ENCAPSULATED_RESPONSE: 498 | cdc_Get_Encapsulated_Command(); 499 | break; 500 | case SET_LINE_CODING: 501 | cdc_Set_Line_Coding(); 502 | break; 503 | case GET_LINE_CODING: 504 | cdc_Get_Line_Coding(); 505 | break; 506 | case SET_CONTROL_LINE_STATE: 507 | cdc_Set_ControlLine_State(); 508 | break; 509 | case SEND_BREAK: 510 | cdc_Send_Break(); 511 | break; 512 | #endif 513 | } 514 | } 515 | -------------------------------------------------------------------------------- /firmware/gpib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include "gpib.h" 33 | #include "parser.h" 34 | #include "gpib_io.h" 35 | 36 | #include "c8051f380.h" 37 | #include "usb_cdc.h" 38 | #include "util.h" 39 | #include "f38x_flash.h" 40 | 41 | #include 42 | 43 | static __code __at (0x7a00) gpib_config_struct gpib_config_saved = { 44 | {{{0},}, 0,}, // address 45 | 0, // read_after_write 46 | 0, // eoi 47 | 0, // eos 48 | 0, // eot 49 | (char)0, // eot_char 50 | 0, // listen_only 51 | 1, // is_controller 52 | (u16)10, // timeout_ms 53 | 0, // status 54 | 0, // debug 55 | }; 56 | 57 | gpib_config_t gpib_config; 58 | 59 | #define DEBUG_ECHO 0x01 60 | #define DEBUG_GPIB_ECHO 0x02 61 | #define DEBUG_VERBOSE 0x04 62 | 63 | #define print_str(str) write(str, sizeof(str) - 1) 64 | static void print_terminator(u16 (*write)(char *buf, u16 len)){ 65 | switch(gpib_config.eos){ 66 | case 0: print_str("\r\n"); break; 67 | case 1: print_str("\r"); break; 68 | default: print_str("\n"); break; 69 | } 70 | } 71 | #undef print_str 72 | 73 | static u16 (*write_func)(char *, u16) = (u16 (*)(char *, u16))cdc_tx; 74 | static void push_func(char c){write_func(&c, 1);} 75 | 76 | #define print_str(str) write_func(str, sizeof(str) - 1) 77 | static void print_header(){ 78 | print_str("++"); 79 | } 80 | 81 | static void print_space(){ 82 | print_str(" "); 83 | } 84 | #undef print_str 85 | 86 | static void print_u16(u16 v){ 87 | char buf[5]; 88 | u8 i = sizeof(buf); 89 | while(1){ 90 | buf[--i] = '0' + (v % 10); 91 | if(v < 10){break;} 92 | v /= 10; 93 | } 94 | write_func(&buf[i], sizeof(buf) - i); 95 | } 96 | 97 | static void print_address(enum commant_t cmd, __xdata address_t *address){ 98 | u8 i; 99 | if(gpib_config.debug & DEBUG_VERBOSE){ 100 | print_header(); 101 | write_func(command_str[cmd], strlen(command_str[cmd])); 102 | print_space(); 103 | } 104 | for(i = 0; i < address->valid_items; ++i){ 105 | if(i > 0){print_space();} 106 | print_u16(address->item[i][0]); 107 | if(gpib_config.address.item[i][1] > 0){ 108 | print_space(); 109 | print_u16(address->item[i][1]); 110 | } 111 | } 112 | print_terminator(write_func); 113 | } 114 | 115 | static void print_1arg(enum commant_t cmd, u16 arg1){ 116 | if(gpib_config.debug & DEBUG_VERBOSE){ 117 | print_header(); 118 | write_func(command_str[cmd], strlen(command_str[cmd])); 119 | print_space(); 120 | } 121 | print_u16(arg1); 122 | print_terminator(write_func); 123 | } 124 | 125 | static void dump_config(){ 126 | print_address(CMD_ADDR, &gpib_config.address); 127 | print_1arg(CMD_AUTO, gpib_config.read_after_write); 128 | print_1arg(CMD_EOI, gpib_config.eoi); 129 | print_1arg(CMD_EOS, gpib_config.eos); 130 | print_1arg(CMD_EOT_ENABLE, gpib_config.eot); 131 | print_1arg(CMD_EOT_CHAR, (u8)(gpib_config.eot_char)); 132 | print_1arg(CMD_LON, gpib_config.listen_only); 133 | print_1arg(CMD_MODE, gpib_config.is_controller); 134 | print_1arg(CMD_READ_TMO_MS, gpib_config.timeout_ms); 135 | print_1arg(CMD_STATUS, gpib_config.status); 136 | } 137 | 138 | #define renew_arg0(type) \ 139 | static u8 renew_arg0_ ## type(parsed_info_t *info, __xdata type *res, type max){ \ 140 | if((info->args > 0) && (info->arg[0] >= 0) && (info->arg[0] <= max)){ \ 141 | type tmp = (type)info->arg[0]; \ 142 | if(*res != tmp){ \ 143 | *res = tmp; \ 144 | return 1; \ 145 | } \ 146 | } \ 147 | return 0; \ 148 | } 149 | renew_arg0(u8) 150 | renew_arg0(u16) 151 | 152 | static u8 check_address(__xdata int *buf, u8 size, u8 *res){ 153 | u8 changes = 0; 154 | if((size > 0) && (buf[0] >= 0) && (buf[0] <= 30)){ 155 | res[0] = buf[0]; 156 | changes++; 157 | if((size > 1) && (buf[1] >= 96) && (buf[1] <= 126)){ 158 | res[1] = buf[1]; 159 | changes++; 160 | }else{ 161 | res[1] = 0; 162 | } 163 | } 164 | return changes; 165 | } 166 | 167 | static __xdata address_t *get_address(parsed_info_t *info){ 168 | static __xdata address_t address; 169 | u8 i = 0; 170 | address.valid_items = 0; 171 | while(info->args > 0){ 172 | u8 captured = check_address(&(info->arg[i]), (u8)info->args, address.item[address.valid_items]); 173 | if(captured == 0){ 174 | captured = 1; // skip invalid argument. 175 | }else{ 176 | address.valid_items++; 177 | } 178 | i += captured; 179 | info->args -= captured; 180 | } 181 | return (address.valid_items > 0) ? &address : NULL; 182 | } 183 | 184 | enum gpib_command_t { 185 | GPIB_CMD_DCL = 0x14, 186 | GPIB_CMD_UNL = 0x3F, 187 | GPIB_CMD_UNT = 0x5F, 188 | GPIB_CMD_GET = 0x08, 189 | GPIB_CMD_SDC = 0x04, 190 | GPIB_CMD_LLO = 0x11, 191 | GPIB_CMD_GTL = 0x01, 192 | GPIB_CMD_SPE = 0x18, 193 | GPIB_CMD_SPD = 0x19, 194 | }; 195 | #define GPIB_CMD_LAD(x) (x | 0x20) 196 | #define GPIB_CMD_IS_LAD_OR_UNL(x) ((x & 0x60) == 0x20) 197 | #define GPIB_CMD_TAD(x) (x | 0x40) 198 | #define GPIB_CMD_IS_TAD_OR_UNT(x) ((x & 0x60) == 0x40) 199 | 200 | static void gpib_cmd(u8 cmd, __xdata address_t *new_listener){ 201 | gpib_uniline(GPIB_UNI_CMD_START); 202 | if(new_listener){ 203 | u8 i; 204 | gpib_putchar(GPIB_CMD_UNL, 0); 205 | for(i = 0; i < new_listener->valid_items; i++){ 206 | gpib_putchar(GPIB_CMD_LAD(new_listener->item[i][0]), 0); 207 | if(new_listener->item[i][1] != 0){ 208 | gpib_putchar(new_listener->item[i][1], 0); 209 | } 210 | } 211 | } 212 | gpib_putchar(cmd, 0); 213 | gpib_uniline(GPIB_UNI_CMD_END); 214 | } 215 | 216 | static u16 gpib_write_auto_eoi(char *buf, u16 length){ 217 | return gpib_write(buf, length, 218 | gpib_config.eoi ? GPIB_WRITE_USE_EOI : 0); 219 | } 220 | 221 | static __bit talking; 222 | static void force_end_talking(){ 223 | if(talking){ 224 | talking = FALSE; 225 | print_terminator(gpib_write_auto_eoi); 226 | } 227 | } 228 | 229 | static __bit talkable_as_device; 230 | static __bit listening_as_device; 231 | static __bit serial_polling_as_device; 232 | 233 | static void device_init(){ 234 | talkable_as_device = FALSE; 235 | listening_as_device = gpib_config.listen_only ? TRUE : FALSE; 236 | serial_polling_as_device = FALSE; 237 | if(gpib_config.status & 0x40){ 238 | gpib_uniline(GPIB_UNI_SRQ_ASSERT); // SRQ 239 | } 240 | } 241 | 242 | void run_command(parsed_info_t *info){ 243 | u8 not_query = (!(gpib_config.debug & DEBUG_VERBOSE)) && (info->args > 0); 244 | switch(info->cmd){ 245 | case CMD_ADDR: { 246 | __xdata address_t *new_address = get_address(info); 247 | if(new_address){ 248 | memcpy(&(gpib_config.address), new_address, sizeof(address_t)); 249 | } 250 | if(not_query){break;} 251 | print_address(CMD_ADDR, &gpib_config.address); // return current address 252 | break; 253 | } 254 | case CMD_AUTO: 255 | renew_arg0_u8(info, &gpib_config.read_after_write, 1); 256 | if(not_query){break;} 257 | print_1arg(CMD_AUTO, gpib_config.read_after_write); // return current auto 258 | break; 259 | case CMD_CLR: 260 | if(gpib_config.is_controller){ 261 | force_end_talking(); 262 | gpib_cmd(GPIB_CMD_SDC, &gpib_config.address); 263 | } 264 | break; 265 | case CMD_EOI: 266 | renew_arg0_u8(info, &gpib_config.eoi, 1); 267 | if(not_query){break;} 268 | print_1arg(CMD_EOI, gpib_config.eoi); // return current eoi 269 | break; 270 | case CMD_EOS: 271 | renew_arg0_u8(info, &gpib_config.eos, 3); 272 | if(not_query){break;} 273 | print_1arg(CMD_EOS, gpib_config.eos); // return current eos 274 | break; 275 | case CMD_EOT_ENABLE: 276 | renew_arg0_u8(info, &gpib_config.eot, 1); 277 | if(not_query){break;} 278 | print_1arg(CMD_EOT_ENABLE, gpib_config.eot); // return current eot 279 | break; 280 | case CMD_EOT_CHAR: 281 | renew_arg0_u8(info, (__xdata char *)&gpib_config.eot_char, 255); 282 | if(not_query){break;} 283 | print_1arg(CMD_EOT_CHAR, (u8)gpib_config.eot_char); // return current eos_char 284 | break; 285 | case CMD_IFC: 286 | if(gpib_config.is_controller){ 287 | force_end_talking(); 288 | gpib_uniline(GPIB_UNI_BUS_CLEAR_START); 289 | wait_ms(1); 290 | gpib_uniline(GPIB_UNI_BUS_CLEAR_END); 291 | } 292 | break; 293 | case CMD_LLO: 294 | if(gpib_config.is_controller){ 295 | force_end_talking(); 296 | gpib_cmd(GPIB_CMD_LLO, NULL); 297 | } 298 | break; 299 | case CMD_LOC: 300 | if(gpib_config.is_controller){ 301 | force_end_talking(); 302 | gpib_cmd(GPIB_CMD_GTL, &gpib_config.address); 303 | } 304 | break; 305 | case CMD_LON: 306 | renew_arg0_u8(info, &gpib_config.listen_only, 1); 307 | if(gpib_config.listen_only){listening_as_device = TRUE;} 308 | if(not_query){break;} 309 | print_1arg(CMD_LON, gpib_config.listen_only); // return current los 310 | break; 311 | case CMD_MODE: 312 | if(renew_arg0_u8(info, &gpib_config.is_controller, 1)){ 313 | force_end_talking(); 314 | gpib_io_init(); 315 | if(!gpib_config.is_controller){device_init();} 316 | } 317 | if(not_query){break;} 318 | print_1arg(CMD_MODE, gpib_config.is_controller); // return current mode 319 | break; 320 | case CMD_READ: // Different from Prologix impl. 321 | if(!gpib_config.is_controller){break;} 322 | force_end_talking(); 323 | gpib_uniline(GPIB_UNI_CMD_START); 324 | gpib_putchar(GPIB_CMD_UNL, 0); 325 | gpib_putchar(GPIB_CMD_LAD(0), 0); // listener, it's me. 326 | gpib_putchar(GPIB_CMD_TAD(gpib_config.address.item[0][0]), 0); // talker 327 | gpib_uniline(GPIB_UNI_CMD_END); 328 | if((info->args > 0) && (info->arg[0] == ARG_EOI)){ 329 | gpib_read(push_func, GPIB_READ_UNTIL_EOI); 330 | }else{ 331 | gpib_read(push_func, 0); 332 | } 333 | sys_state |= SYS_GPIB_LISTENED; 334 | break; 335 | case CMD_READ_TMO_MS: 336 | if(renew_arg0_u16(info, &gpib_config.timeout_ms, 3000)){ 337 | gpib_io_set_timeout(); 338 | } 339 | if(not_query){break;} 340 | print_1arg(CMD_READ_TMO_MS, gpib_config.timeout_ms); 341 | break; 342 | case CMD_RST: 343 | RSTSRC = 0x10; // RSTSRC.4(SWRSF) = 1 causes software reset 344 | break; 345 | case CMD_SAVECFG: 346 | // Different from Prologic command, savecfg is performing one-shot save. 347 | flash_update((flash_address_t)(void __code *)&gpib_config_saved, 348 | (u8 *)&gpib_config, sizeof(gpib_config)); 349 | if(gpib_config.debug & DEBUG_VERBOSE){dump_config();} 350 | break; 351 | case CMD_SPOLL: { 352 | if(gpib_config.is_controller){ 353 | u8 buf[2]; 354 | int stb; 355 | 356 | force_end_talking(); 357 | gpib_uniline(GPIB_UNI_CMD_START); 358 | gpib_putchar(GPIB_CMD_SPE, 0); 359 | memcpy(buf, gpib_config.address.item[0], sizeof(gpib_config.address.item[0])); 360 | check_address(&(info->arg[0]), (u8)info->args, buf); 361 | buf[0] = GPIB_CMD_TAD(buf[0]); 362 | gpib_write(buf, (buf[1] == 0 ? 1 : 2), 0); 363 | gpib_uniline(GPIB_UNI_CMD_END); 364 | 365 | stb = gpib_getchar(); 366 | if(!GPIB_GETCHAR_IS_ERROR(stb)){ 367 | print_1arg(CMD_SPOLL, GPIB_GETCHAR_TO_DATA(stb)); 368 | } 369 | 370 | buf[0] = GPIB_CMD_UNT; 371 | buf[1] = GPIB_CMD_SPD; 372 | gpib_uniline(GPIB_UNI_CMD_START); 373 | gpib_write(buf, 2, 0); 374 | gpib_uniline(GPIB_UNI_CMD_END); 375 | } 376 | break; 377 | } 378 | case CMD_SRQ: { 379 | if(gpib_config.is_controller){ 380 | print_1arg(CMD_SRQ, gpib_uniline(GPIB_UNI_CHECK_SRQ_ASSERT)); 381 | } 382 | break; 383 | } 384 | case CMD_STATUS: 385 | if(renew_arg0_u8(info, &gpib_config.status, 0xFF)){ 386 | if(!gpib_config.is_controller){ 387 | gpib_uniline((gpib_config.status & 0x40) 388 | ? GPIB_UNI_SRQ_ASSERT : GPIB_UNI_SRQ_DEASSERT); // SRQ 389 | } 390 | } 391 | if(not_query){break;} 392 | print_1arg(CMD_STATUS, gpib_config.status); 393 | break; 394 | case CMD_TRG: 395 | if(!gpib_config.is_controller){break;} 396 | force_end_talking(); 397 | if(info->args == 0){ 398 | gpib_cmd(GPIB_CMD_GET, &gpib_config.address); 399 | }else{ 400 | __xdata address_t *new_address = get_address(info); 401 | if(new_address){ 402 | gpib_cmd(GPIB_CMD_GET, new_address); 403 | } 404 | } 405 | break; 406 | #define print_str(str) write_func(str, sizeof(str) - 1) 407 | case CMD_VER: 408 | if(gpib_config.debug & DEBUG_VERBOSE){ 409 | print_header(); 410 | write_func(command_str[CMD_VER], strlen(command_str[CMD_VER])); 411 | print_space(); 412 | } 413 | print_str("Fenrir GPIB-USB 1.0 (Prologix version 6.0 compatible)"); 414 | print_terminator(write_func); 415 | break; 416 | #undef print_str 417 | case CMD_HELP: { 418 | u8 i; 419 | if(gpib_config.debug & DEBUG_VERBOSE){ 420 | print_header(); 421 | write_func(command_str[CMD_HELP], strlen(command_str[CMD_HELP])); 422 | print_space(); 423 | } 424 | for(i = 0; i < sizeof(command_str) / sizeof(command_str[0]); ++i){ 425 | if(i > 0){print_space();} 426 | write_func(command_str[i], strlen(command_str[i])); 427 | } 428 | print_terminator(write_func); 429 | break; 430 | } 431 | case CMD_DEBUG: 432 | renew_arg0_u8(info, &gpib_config.debug, 0xFF); 433 | if(not_query){break;} 434 | print_1arg(CMD_DEBUG, gpib_config.debug); // return current debug 435 | break; 436 | case CMD_TALK: { 437 | static __xdata char buf; 438 | if(talking){ 439 | if(gpib_config.debug & DEBUG_GPIB_ECHO){ 440 | push_func(buf); // print character to be tried to write 441 | } 442 | if(info->args == 0){ // terminator 443 | if(gpib_config.eos == 3){ 444 | gpib_putchar(buf, gpib_config.eoi ? GPIB_WRITE_USE_EOI : 0); 445 | }else{ 446 | gpib_putchar(buf, 0); 447 | print_terminator(gpib_write_auto_eoi); 448 | } 449 | talking = FALSE; 450 | if(gpib_config.read_after_write){ 451 | info->cmd = CMD_READ; 452 | // info->args = 0; 453 | run_command(info); // valid only for controller. 454 | } 455 | }else{ 456 | talking = (gpib_putchar(buf, 0) > 0); 457 | buf = (u8)(info->arg[0]); 458 | } 459 | sys_state |= SYS_GPIB_TALKED; 460 | }else if(info->args > 0){ // ignore terminator when not talking. 461 | if(gpib_config.is_controller){ // controller 462 | gpib_cmd(GPIB_CMD_TAD(0), &gpib_config.address); // talker, it's me. 463 | talking = TRUE; 464 | }else if(talkable_as_device){ // device 465 | talking = TRUE; 466 | } 467 | buf = (u8)(info->arg[0]); 468 | } 469 | break; 470 | } 471 | } 472 | } 473 | 474 | void gpib_init(){ 475 | memcpy(&gpib_config, &gpib_config_saved, sizeof(gpib_config)); 476 | gpib_io_init(); 477 | gpib_io_set_timeout(); 478 | parser_reset(); 479 | 480 | talking = FALSE; 481 | device_init(); 482 | } 483 | 484 | void gpib_polling(){ 485 | static __xdata char buf[16]; 486 | static __xdata u8 remain = 0; 487 | static __xdata char * __xdata c; 488 | 489 | sys_state &= ~(SYS_GPIB_TALKED | SYS_GPIB_LISTENED); 490 | 491 | // parse cdc_rx stream 492 | if(remain == 0){ 493 | remain = (u8)cdc_rx(buf, sizeof(buf)); 494 | c = buf; 495 | } 496 | for(; remain > 0; remain--, c++){ 497 | if(gpib_config.debug & DEBUG_ECHO){push_func(*c);} 498 | parse(*c); 499 | } 500 | 501 | if((!gpib_config.is_controller) && (!talking)){ // device mode 502 | do{ 503 | static __bit last_char_is_cr = FALSE; 504 | int res = gpib_getchar(); 505 | 506 | // transfer to routine to parse cdc_rx stream due to error(timeout etc.) 507 | if(GPIB_GETCHAR_IS_ERROR(res)){break;} 508 | 509 | if(GPIB_GETCHAR_IS_CMD(res)){ 510 | u8 cmd = GPIB_GETCHAR_TO_DATA(res); 511 | last_char_is_cr = FALSE; 512 | if(GPIB_CMD_IS_TAD_OR_UNT(cmd)){ 513 | cmd &= 0x1F; 514 | if(cmd == (GPIB_CMD_UNT & 0x1F)){ // UNT 515 | talkable_as_device = FALSE; 516 | }else if((!gpib_config.listen_only) 517 | && (cmd == gpib_config.address.item[0][0])){ 518 | talkable_as_device = TRUE; 519 | 520 | // transfer to routine to parse cdc_rx stream because controller request sending data. 521 | if(!serial_polling_as_device){break;} 522 | 523 | if(gpib_putchar(gpib_config.status, 0)){ 524 | gpib_config.status &= ~(0x40); 525 | gpib_uniline(GPIB_UNI_SRQ_DEASSERT); 526 | } 527 | } 528 | }else if(GPIB_CMD_IS_LAD_OR_UNL(cmd)){ 529 | cmd &= 0x1F; 530 | if(cmd == (GPIB_CMD_UNL & 0x1F)){ // UNL 531 | if(!gpib_config.listen_only){listening_as_device = FALSE;} 532 | }else if(cmd == gpib_config.address.item[0][0]){ 533 | listening_as_device = TRUE; 534 | } 535 | }else{ 536 | switch(cmd){ 537 | //case GPIB_CMD_GTL: break; 538 | //case GPIB_CMD_SDC: break; 539 | //case GPIB_CMD_GET: break; 540 | //case GPIB_CMD_LLO: break; 541 | //case GPIB_CMD_DCL: break; 542 | case GPIB_CMD_SPE: 543 | serial_polling_as_device = TRUE; 544 | break; 545 | case GPIB_CMD_SPD: 546 | serial_polling_as_device = FALSE; 547 | break; 548 | } 549 | } 550 | }else{ 551 | // @see much similarity to gpib_read() 552 | char c = GPIB_GETCHAR_TO_DATA(res); 553 | if(listening_as_device){ 554 | sys_state |= SYS_GPIB_LISTENED; 555 | push_func(c); 556 | } 557 | 558 | if(GPIB_GETCHAR_IS_EOI(res)){ 559 | if(listening_as_device && gpib_config.eot){push_func(gpib_config.eot_char);} 560 | break; 561 | }else if(c == '\r'){ 562 | if(gpib_config.eos == 1){break;} 563 | last_char_is_cr = TRUE; 564 | }else{ 565 | if(c == '\n'){ 566 | if((gpib_config.eos == 2) 567 | || ((last_char_is_cr) && (gpib_config.eos == 0))){break;} 568 | } 569 | last_char_is_cr = FALSE; 570 | } 571 | } 572 | }while(1); 573 | } 574 | 575 | write_func(NULL, 0); // flush buffer 576 | 577 | if(gpib_config.is_controller){ 578 | sys_state |= SYS_GPIB_CONTROLLER; 579 | }else{ 580 | sys_state &= ~SYS_GPIB_CONTROLLER; 581 | } 582 | } 583 | -------------------------------------------------------------------------------- /firmware/f38x_usb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | 35 | #include "c8051f380.h" 36 | #include "main.h" 37 | #include "f38x_usb_register.h" 38 | #include "f38x_usb.h" 39 | #include "usb_descriptor.h" 40 | 41 | #include "usb_std_req.h" 42 | #include "usb_other_req.h" 43 | 44 | #include "usb_cdc.h" 45 | 46 | #include "util.h" 47 | 48 | // Holds the current USB State 49 | usb_state_t usb_state; 50 | 51 | ep0_setup_t ep0_setup; 52 | ep0_data_t ep0_data; 53 | volatile __bit ep0_request_completed; 54 | 55 | // Holds the status for each endpoint 56 | BYTE __xdata usb_ep_stat[7]; 57 | 58 | static __xdata unsigned int ep_out_stored[3]; 59 | #define count_ep_out(index) ep_out_stored[index - 1] 60 | 61 | static const __code unsigned int ep_size[] = { 62 | PACKET_SIZE_EP0, 63 | PACKET_SIZE_EP1, 64 | PACKET_SIZE_EP2, 65 | PACKET_SIZE_EP3 66 | }; 67 | 68 | static __code void(* __xdata stall_callbacks[6])(); 69 | 70 | #define EP_INDEX_2_LINER_INDEX(dir, ep_index) \ 71 | ((dir == DIR_IN) ? (ep_index - 1) : (ep_index + 2)) 72 | 73 | // consider into both interrupt and user invoked cases 74 | #ifdef USE_ASM_FOR_SFR_MANIP 75 | #define CRITICAL_USB0_SPECIAL(func) \ 76 | { \ 77 | BYTE eie1_backup = EIE1; \ 78 | {__asm anl _EIE1,SHARP ~0x02 __endasm; } \ 79 | { \ 80 | func; \ 81 | } \ 82 | if(eie1_backup & 0x02){ \ 83 | {__asm orl _EIE1,SHARP 0x02 __endasm; } \ 84 | } \ 85 | } 86 | #else 87 | #define CRITICAL_USB0_SPECIAL(func) \ 88 | { \ 89 | BYTE eie1_backup = EIE1; \ 90 | EIE1 &= ~(0x02); \ 91 | { \ 92 | func; \ 93 | } \ 94 | if(eie1_backup & 0x02){EIE1 |= 0x02;} \ 95 | } 96 | #endif 97 | 98 | /** 99 | * Read from the selected endpoint FIFO 100 | * 101 | * @param ptr_data read data destination 102 | * @param index target EP index 103 | * @param u_num_bytes number of bytes to unload 104 | * @return number to read 105 | */ 106 | static unsigned int fifo_read_C( 107 | BYTE* ptr_data, 108 | unsigned int u_num_bytes, 109 | unsigned char index){ 110 | 111 | // Check if >0 bytes requested, 112 | if(u_num_bytes){ 113 | 114 | unsigned int read_count = u_num_bytes; 115 | 116 | // Set address and auto-read to initiate first read 117 | USB0ADR = (FIFO_EP0 + index) | 0xC0; 118 | 119 | // Wait for BUSY->'0' (data ready) 120 | while(USB0ADR & 0x80); 121 | 122 | // Unload from the selected FIFO 123 | if(ptr_data){ 124 | 125 | while(--read_count){ 126 | // Copy data byte 127 | *(ptr_data++) = USB0DAT; 128 | 129 | // Wait for BUSY->'0' (data ready) 130 | while(USB0ADR & 0x80); 131 | } 132 | 133 | // Clear auto-read 134 | USB0ADR &= ~0x40; 135 | 136 | // Copy data byte 137 | *(ptr_data++) = USB0DAT; 138 | }else{ 139 | volatile BYTE c; 140 | while(--read_count){ 141 | // Copy data byte 142 | c = USB0DAT; 143 | 144 | // Wait for BUSY->'0' (data ready) 145 | while(USB0ADR & 0x80); 146 | } 147 | 148 | // Clear auto-read 149 | USB0ADR &= ~0x40; 150 | 151 | // Copy data byte 152 | c = USB0DAT; 153 | } 154 | } 155 | 156 | return u_num_bytes; 157 | } 158 | #define fifo0_read_C(ptr_data, u_num_bytes) \ 159 | fifo_read_C(ptr_data, u_num_bytes, 0) 160 | 161 | typedef struct { 162 | BYTE *array; 163 | BYTE c; 164 | } write_target_t; 165 | 166 | /** 167 | * Write to the selected endpoint FIFO 168 | * 169 | * @param target write data source 170 | * @param u_num_bytes number of bytes to unload 171 | * @param addr target address 172 | * @return number to write 173 | */ 174 | static unsigned int fifo_write_C( 175 | write_target_t *target, 176 | unsigned int u_num_bytes, 177 | unsigned char index){ 178 | 179 | if(u_num_bytes > ep_size[index]){ 180 | u_num_bytes = ep_size[index]; 181 | } 182 | 183 | // If >0 bytes requested, 184 | if(u_num_bytes){ 185 | unsigned int remain = u_num_bytes; 186 | 187 | BYTE *ptr = target->array; 188 | 189 | // Wait for BUSY->'0' (register available) 190 | while(USB0ADR & 0x80); 191 | 192 | // Set address (mask out bits7-6) 193 | USB0ADR = (FIFO_EP0 + index); 194 | 195 | if(ptr){ 196 | // Write to the selected FIFO 197 | while(remain--){ 198 | USB0DAT = *(ptr++); 199 | } 200 | target->array = ptr; // advance pointer 201 | }else{ 202 | // Write to the selected FIFO 203 | BYTE c = target->c; 204 | while(remain--){ 205 | USB0DAT = c; 206 | } 207 | } 208 | } 209 | 210 | return u_num_bytes; 211 | } 212 | #define fifo0_write_C(target, u_num_bytes) \ 213 | fifo_write_C(target, u_num_bytes, 0) 214 | 215 | /** 216 | * Handle IN 1-3 Endpoint interrupts, which are generated when 217 | * 1. An IN packet is successfully transferred to the host. 218 | * 2. Software writes 1 to the FLUSH bit (EINCSRL.3) when the target FIFO is not empty. 219 | * 3. Hardware generates a STALL condition. 220 | * 221 | * @param ep_index Index of Endpoint 222 | */ 223 | static void usb_handle_in(unsigned char ep_index){ 224 | 225 | BYTE control_reg; 226 | 227 | // Set index to EP ep_index 228 | POLL_WRITE_BYTE(INDEX, ep_index); 229 | 230 | // Read contol register for EP ep_index 231 | POLL_READ_BYTE(EINCSR1, control_reg); 232 | 233 | // Clear sent stall and flush FIFO if last packet returned a stall 234 | if(control_reg & rbInSTSTL){ 235 | __code void (*callback_func)() 236 | = stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_IN, ep_index)]; 237 | POLL_WRITE_BYTE(EINCSR1, 238 | (control_reg & (rbInCLRDT | ~rbInSTSTL))); 239 | if(callback_func){callback_func();} 240 | } 241 | } 242 | 243 | /** 244 | * Handle OUT Endpoint interrupts, which are generated when 245 | * 1. Hardware sets the OPRDY bit (EINCSRL.0) to 1. 246 | * 2. Hardware generates a STALL condition. 247 | * 248 | * @param ep_index Index of Endpoint 249 | * 250 | */ 251 | static void usb_handle_out(unsigned char ep_index){ 252 | BYTE control_reg; 253 | 254 | // Set index 255 | POLL_WRITE_BYTE(INDEX, ep_index); 256 | POLL_READ_BYTE(EOUTCSR1, control_reg); 257 | 258 | // Clear sent stall bit if last packet was a stall 259 | if(control_reg & rbOutSTSTL){ 260 | __code void (*callback_func)() 261 | = stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_OUT, ep_index)]; 262 | POLL_WRITE_BYTE(EOUTCSR1, 263 | (control_reg & (rbOutCLRDT | ~rbOutSTSTL))); 264 | if(callback_func){callback_func();} 265 | } 266 | 267 | // Otherwise read received packet from host 268 | else if(control_reg & rbOutOPRDY){ 269 | BYTE b1, b2; 270 | POLL_READ_BYTE(EOUTCNTH, b1); 271 | POLL_READ_BYTE(EOUTCNTL, b2); 272 | count_ep_out(ep_index) = ((((unsigned int)b1) << 8) | b2); 273 | } 274 | } 275 | 276 | /** 277 | * Decode Incoming Setup requests 278 | * Load data packets on fifo while in transmit mode 279 | * 280 | */ 281 | static void handle_setup(){ 282 | // Temporary storage for EP control register 283 | BYTE control_reg; 284 | 285 | // Set Index to Endpoint Zero 286 | POLL_WRITE_BYTE(INDEX, EP0_IDX); 287 | 288 | // Read control register 289 | POLL_READ_BYTE(E0CSR, control_reg); 290 | 291 | // Handle Status Phase of Set Address command 292 | if(usb_ep0_status == EP_ADDRESS){ 293 | POLL_WRITE_BYTE(FADDR, ep0_setup.wValue.c[LSB]); 294 | usb_ep0_status = EP_IDLE; 295 | } 296 | 297 | // If last packet was a sent stall, reset STSTL 298 | // bit and return EP0 to idle state 299 | if (control_reg & rbSTSTL){ 300 | POLL_WRITE_BYTE(E0CSR, 0); 301 | usb_ep0_status = EP_IDLE; 302 | return; 303 | } 304 | 305 | // If last setup transaction was ended prematurely then set 306 | if(control_reg & rbSUEND){ 307 | POLL_WRITE_BYTE(E0CSR, rbDATAEND); 308 | 309 | // Serviced Setup End bit and return EP0 to idle state 310 | POLL_WRITE_BYTE(E0CSR, rbSSUEND); 311 | usb_ep0_status = EP_IDLE; 312 | } 313 | 314 | // If Endpoint 0 is in idle mode 315 | if(usb_ep0_status == EP_IDLE){ 316 | 317 | // Make sure that EP 0 has an Out Packet ready from host 318 | // although if EP0 is idle, this should always be the case 319 | if(control_reg & rbOPRDY){ 320 | 321 | fifo0_read_C((BYTE *)&ep0_setup, 8); 322 | 323 | ep0_request_completed = FALSE; 324 | 325 | // Call correct subroutine to handle each kind of standard request 326 | switch(ep0_setup.bmRequestType & DRT_MASK){ 327 | // Standard device request 328 | case DRT_STD: usb_standard_request(); break; 329 | case DRT_CLASS: usb_class_request(); break; 330 | case DRT_VENDOR: usb_vendor_request(); break; 331 | } 332 | 333 | // Set index back to endpoint 0 334 | POLL_WRITE_BYTE(INDEX, EP0_IDX); 335 | 336 | if(!ep0_request_completed){ 337 | // Send stall to host if invalid request 338 | POLL_WRITE_BYTE(E0CSR, rbSDSTL); 339 | // Put the endpoint in stall status 340 | usb_ep0_status = EP_STALL; 341 | return; 342 | } 343 | 344 | // Indicate setup packet has been serviced 345 | control_reg = rbSOPRDY; 346 | if(usb_ep0_status == EP_IDLE){ 347 | control_reg |= rbDATAEND; 348 | } 349 | POLL_WRITE_BYTE(E0CSR, control_reg); 350 | } 351 | } 352 | 353 | // See if the endpoint has data to transmit to host 354 | switch(usb_ep0_status){ 355 | case EP_TX: { 356 | // Make sure you don't overwrite last packet 357 | if (control_reg & rbINPRDY){break;} 358 | 359 | // Read control register 360 | POLL_READ_BYTE(E0CSR, control_reg); 361 | 362 | // Check to see if Setup End or Out Packet received, if so 363 | // do not put any new data on FIFO 364 | if((control_reg & rbSUEND) && (control_reg & rbOPRDY)){break;} 365 | 366 | // Add In Packet ready flag to E0CSR bitmask 367 | control_reg = rbINPRDY; 368 | 369 | { 370 | unsigned int written; 371 | 372 | write_target_t target; 373 | target.array = ep0_data.buf; 374 | 375 | written = fifo0_write_C(&target, ep0_data.size); 376 | 377 | if(ep0_data.size > written){ 378 | 379 | ep0_data.size -= written; 380 | ep0_data.buf = target.array; // Get advanced data pointer 381 | }else if(written < ep_size[0]){ 382 | // check whether the last write size is less than maximum packet size, which requires additional ZLP 383 | 384 | if(ep0_data.callback){ep0_data.callback();} 385 | 386 | // Add Data End bit to bitmask 387 | control_reg |= rbDATAEND; 388 | 389 | // Return EP 0 to idle state 390 | usb_ep0_status = EP_IDLE; 391 | } 392 | } 393 | 394 | // Write mask to E0CSR 395 | POLL_WRITE_BYTE(E0CSR, control_reg); 396 | 397 | break; 398 | } 399 | case EP_RX: { 400 | // Verify packet was received 401 | if(control_reg & rbOPRDY){ 402 | 403 | BYTE recieved; 404 | 405 | control_reg = rbSOPRDY; 406 | 407 | // get data bytes on the FIFO 408 | POLL_READ_BYTE(E0CNT, recieved); 409 | 410 | // Empty the FIFO 411 | // FIFO must be read out just the size it has, 412 | // otherwise the FIFO pointer on the SIE goes out of synch. 413 | fifo0_read_C((BYTE*)ep0_data.buf, recieved); 414 | 415 | if(ep0_data.size > recieved){ 416 | // Update the scheduled number to be received 417 | ep0_data.size -= recieved; 418 | 419 | // Advance the pointer 420 | ep0_data.buf += recieved; 421 | }else{ 422 | // Meet the end of the data stage 423 | ep0_data.size = 0; 424 | 425 | // Signal end of data stage 426 | control_reg |= rbDATAEND; 427 | 428 | usb_ep0_status = EP_IDLE; 429 | 430 | ep0_data.callback(); 431 | } 432 | 433 | POLL_WRITE_BYTE(E0CSR, control_reg); 434 | } 435 | break; 436 | } 437 | } 438 | } 439 | 440 | /** 441 | * Resume normal USB operation 442 | * 443 | * Add code to turn on anything turned off when entering suspend mode 444 | */ 445 | static void resume(){ 446 | 447 | } 448 | 449 | /** 450 | * Enter suspend mode after suspend signalling is present on the bus 451 | * 452 | * Add power-down features here if you wish to 453 | * reduce power consumption during suspend mode 454 | */ 455 | static void suspend(){ 456 | 457 | } 458 | 459 | volatile __xdata BYTE usb_frame_num; 460 | 461 | /** 462 | * Set state to default 463 | * Clear USB Inhibit bit 464 | */ 465 | static void reset(){ 466 | // Set device state to default 467 | usb_state = DEV_DEFAULT; 468 | 469 | // Set default Endpoint Status 470 | usb_ep0_status = EP_IDLE; 471 | 472 | // clear EP1-3 states, stall callback funcs, and out counters 473 | { 474 | unsigned char ep_index; 475 | for(ep_index = 1; ep_index <= 3; ep_index++){ 476 | usb_ep_stat[ep_index] = EP_HALT; 477 | stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_IN, ep_index)] = NULL; 478 | stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_OUT, ep_index)] = NULL; 479 | count_ep_out(ep_index) = 0; 480 | } 481 | } 482 | 483 | usb_frame_num = 0; 484 | 485 | // Clear USB inhibit bit to enable USB suspend detection 486 | POLL_WRITE_BYTE(POWER, 0x01); 487 | 488 | // initialize class 489 | usb_class_init(); 490 | } 491 | 492 | static void enable_phy(){ 493 | #ifdef _USB_LOW_SPEED_ 494 | USB0XCN = 0xC0; // Enable transceiver; select low speed 495 | POLL_WRITE_BYTE(CLKREC, 0xA0); // Enable clock recovery; single-step mode disabled; low speed mode enabled 496 | #else 497 | USB0XCN = 0xE0; // Enable transceiver; select full speed 498 | POLL_WRITE_BYTE(CLKREC, 0x80); // Enable clock recovery, single-step mode disabled 499 | #endif /* _USB_LOW_SPEED_ */ 500 | reset(); 501 | EIE1 |= 0x02; // Enable USB0 Interrupts 502 | } 503 | 504 | /** 505 | * USB Initialization 506 | * 507 | * Initialize USB0 508 | * Enable USB0 interrupts 509 | * Enable USB0 transceiver 510 | * Enable USB0 with suspend detection 511 | */ 512 | void usb0_init(){ 513 | POLL_WRITE_BYTE(POWER, 0x08); // Force Asynchronous USB Reset 514 | POLL_WRITE_BYTE(IN1IE, 0x0F); // Enable Endpoint 0-3 in interrupts 515 | POLL_WRITE_BYTE(OUT1IE, 0x0F); // Enable Endpoint 0-3 out interrupts 516 | POLL_WRITE_BYTE(CMIE, 0x07); // Enable Reset, Resume, and Suspend interrupts 517 | 518 | if(REG01CN & 0x40){ 519 | usb_mode = USB_CABLE_CONNECTED; 520 | enable_phy(); 521 | wait_ms(100); 522 | }else{ 523 | usb_mode = USB_INACTIVE; 524 | } 525 | } 526 | 527 | /** 528 | * Top-level USB ISR 529 | * 530 | * Called after any USB type interrupt, this handler determines which type 531 | * of interrupt occurred, and calls the specific routine to handle it. 532 | * 533 | */ 534 | void usb_isr() __interrupt (INTERRUPT_USB0) { 535 | BYTE bCommon, bIn, bOut; 536 | POLL_READ_BYTE(CMINT, bCommon); // Read all interrupt registers 537 | POLL_READ_BYTE(IN1INT, bIn); // this read also clears the register 538 | POLL_READ_BYTE(OUT1INT, bOut); 539 | 540 | // Handle Resume interrupt 541 | if(bCommon & rbRSUINT){resume();} 542 | 543 | // Handle Setup packet received 544 | // or packet transmitted if Endpoint 0 is transmit mode 545 | if(bIn & rbEP0){handle_setup();} 546 | 547 | { 548 | unsigned char ep_index, ep_mask = 0x02; 549 | for(ep_index = 1; ep_index <= 3; ep_index++, ep_mask <<= 1){ 550 | 551 | // Handle In packet received 552 | if(bIn & ep_mask){usb_handle_in(ep_index);} 553 | 554 | // Handle Out packet received, take data off OUT endpoint 555 | if(bOut & ep_mask){usb_handle_out(ep_index);} 556 | } 557 | } 558 | 559 | // Handle Start of Frame interrupt 560 | //if(bCommon & rbSOF){} 561 | 562 | // Handle Suspend interrupt 563 | if(bCommon & rbSUSINT){suspend();} 564 | 565 | // Handle Reset interrupt 566 | if(bCommon & rbRSTINT){reset();} 567 | } 568 | 569 | volatile usb_mode_t usb_mode; 570 | 571 | static unsigned int usb_tx( 572 | write_target_t *target, 573 | unsigned int count, 574 | unsigned char index){ 575 | unsigned int count_orig = count, add; 576 | do{ 577 | add = 0; 578 | CRITICAL_USB0_SPECIAL( 579 | BYTE control_reg; 580 | 581 | // Check endpoint is not halted 582 | if(ep_strip_owner(usb_ep_status(DIR_IN, index)) != EP_HALT){ 583 | 584 | // Set index to EP ep_index 585 | POLL_WRITE_BYTE(INDEX, index); 586 | 587 | // Read control register for EP ep_index 588 | POLL_READ_BYTE(EINCSR1, control_reg); 589 | 590 | // Register data for transmission 591 | if(!(control_reg & (rbInSDSTL | rbInFLUSH | rbInINPRDY))){ 592 | 593 | // Clear underrun bit if it was set 594 | //if(control_reg & rbInUNDRUN){} // TODO 595 | 596 | // Put new data on FIFO 597 | add = fifo_write_C(target, count, index); 598 | 599 | // Set In Packet ready bit, indicating fresh data on FIFO 600 | POLL_WRITE_BYTE(EINCSR1, rbInINPRDY); 601 | } 602 | } 603 | ); 604 | 605 | if(!add){break;} 606 | count -= add; 607 | }while(count); 608 | return count_orig - count; 609 | } 610 | 611 | unsigned int usb_write( 612 | BYTE* ptr_buf, 613 | unsigned int count, 614 | unsigned char index){ 615 | write_target_t target; 616 | target.array = ptr_buf; 617 | return usb_tx(&target, count, index); 618 | } 619 | 620 | unsigned int usb_fill( 621 | BYTE c, 622 | unsigned int count, 623 | unsigned char index){ 624 | write_target_t target = {NULL, c}; 625 | return usb_tx(&target, count, index); 626 | } 627 | 628 | unsigned int usb_count_ep_out(unsigned char index){ 629 | unsigned int res; 630 | CRITICAL_USB0_SPECIAL( 631 | res = count_ep_out(index); 632 | ); 633 | return res; 634 | } 635 | 636 | unsigned int usb_read( 637 | BYTE* ptr_buf, 638 | unsigned int count, 639 | unsigned char index){ 640 | CRITICAL_USB0_SPECIAL( 641 | if(count_ep_out(index) < count){ 642 | count = count_ep_out(index); 643 | } 644 | count = fifo_read_C(ptr_buf, count, index); 645 | count_ep_out(index) -= count; 646 | if((count > 0) && (count_ep_out(index) == 0)){ 647 | POLL_WRITE_BYTE(INDEX, index); 648 | POLL_WRITE_BYTE(EOUTCSR1, 0); 649 | } 650 | ); 651 | return count; 652 | } 653 | 654 | unsigned int usb_skip( 655 | unsigned int count, 656 | unsigned char index){ 657 | return usb_read(NULL, count, index); 658 | } 659 | 660 | void usb_flush(unsigned char index){ 661 | // Clear Out Packet ready bit 662 | usb_read(NULL, ep_size[index], index); 663 | } 664 | 665 | void usb_status_lock(unsigned char dir, unsigned char ep_index){ 666 | CRITICAL_USB0_SPECIAL( 667 | usb_ep_status(dir, ep_index) |= EP_OWNED_BY_USER; 668 | ); 669 | } 670 | 671 | void usb_status_unlock(unsigned char dir, unsigned char ep_index){ 672 | CRITICAL_USB0_SPECIAL( 673 | usb_ep_status(dir, ep_index) &= ~EP_OWNED_BY_USER; 674 | ); 675 | } 676 | 677 | void usb_stall(unsigned char dir, unsigned char ep_index, 678 | __code void(*callback)()){ 679 | CRITICAL_USB0_SPECIAL( 680 | usb_ep_status(dir, ep_index) 681 | = (usb_ep_status(dir, ep_index) & EP_OWNED_BY_USER) | EP_HALT; 682 | 683 | // Set index to EP ep_index 684 | POLL_WRITE_BYTE(INDEX, ep_index); 685 | 686 | // send a stall immediately 687 | if(dir == DIR_IN){ 688 | POLL_WRITE_BYTE(EINCSR1, rbInSDSTL); 689 | stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_IN, ep_index)] = callback; 690 | }else{ 691 | POLL_WRITE_BYTE(EOUTCSR1, rbOutSDSTL); 692 | stall_callbacks[EP_INDEX_2_LINER_INDEX(DIR_OUT, ep_index)] = callback; 693 | } 694 | ); 695 | } 696 | 697 | void usb_clear_halt(unsigned char dir, unsigned char ep_index){ 698 | CRITICAL_USB0_SPECIAL( 699 | usb_ep_status(dir, ep_index) 700 | = (usb_ep_status(dir, ep_index) & EP_OWNED_BY_USER) | EP_IDLE; 701 | 702 | // Set index to EP ep_index 703 | POLL_WRITE_BYTE(INDEX, ep_index); 704 | 705 | // clear flag 706 | if(dir == DIR_IN){ 707 | POLL_WRITE_BYTE(EINCSR1, 0); 708 | }else{ 709 | POLL_WRITE_BYTE(EOUTCSR1, 0); 710 | } 711 | ); 712 | } 713 | 714 | void usb_polling(){ 715 | 716 | switch(usb_mode){ 717 | case USB_INACTIVE: 718 | if(REG01CN & 0x40){ 719 | usb_mode = USB_CABLE_CONNECTED; 720 | enable_phy(); 721 | } 722 | return; 723 | case USB_CABLE_CONNECTED: 724 | break; 725 | case USB_CDC_READY: 726 | usb_mode = USB_CDC_ACTIVE; 727 | break; 728 | case USB_CDC_ACTIVE: 729 | cdc_polling(); 730 | break; 731 | } 732 | 733 | CRITICAL_USB0_SPECIAL( 734 | POLL_READ_BYTE(FRAMEL, usb_frame_num); 735 | ); 736 | 737 | if(!(REG01CN & 0x40)){ 738 | EIE1 &= ~0x02; // Disable USB0 Interrupts 739 | USB0XCN = 0; 740 | usb_mode = USB_INACTIVE; 741 | } 742 | } 743 | -------------------------------------------------------------------------------- /firmware/c8051f380.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, M.Naruoka (fenrir) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * - Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * - Neither the name of the naruoka.org nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | */ 31 | 32 | /*----------------------------------------------------------------------------- 33 | C8051F380.H 34 | 35 | Header file for Silabs C8051F380/1/2/3/4/5/6 and C8051F387 devices. 36 | -----------------------------------------------------------------------------*/ 37 | 38 | 39 | #ifndef __C8051F380_H__ 40 | #define __C8051F380_H__ 41 | 42 | /* SFRPage 0x00 and SFRPage 0x0F Registers */ 43 | __sfr __at (0x80) P0 ; /* Port 0 Latch */ 44 | __sfr __at (0x81) SP ; /* Stack Pointer */ 45 | __sfr __at (0x82) DPL ; /* Data Pointer Low */ 46 | __sfr __at (0x83) DPH ; /* Data Pointer High */ 47 | __sfr __at (0x84) EMI0TC ; /* External Memory Interface Timing */ 48 | __sfr __at (0x85) EMI0CF ; /* External Memory Interface Configuration */ 49 | __sfr __at (0x86) OSCLCN ; /* Internal Low-Frequency Oscillator Control */ 50 | __sfr __at (0x87) PCON ; /* Power Control */ 51 | __sfr __at (0x88) TCON ; /* Timer/Counter Control */ 52 | __sfr __at (0x89) TMOD ; /* Timer/Counter Mode */ 53 | __sfr __at (0x8A) TL0 ; /* Timer/Counter 0 Low */ 54 | __sfr __at (0x8B) TL1 ; /* Timer/Counter 1 Low */ 55 | __sfr __at (0x8C) TH0 ; /* Timer/Counter 0 High */ 56 | __sfr __at (0x8D) TH1 ; /* Timer/Counter 1 High */ 57 | __sfr __at (0x8E) CKCON ; /* Clock Control */ 58 | __sfr __at (0x8F) PSCTL ; /* Program Store R/W Control */ 59 | __sfr __at (0x90) P1 ; /* Port 1 Latch */ 60 | __sfr __at (0x91) TMR3CN ; /* Timer/Counter 3 Control (page 0) */ 61 | __sfr __at (0x92) TMR3RLL ; /* Timer/Counter 3 Reload Low (page 0) */ 62 | __sfr __at (0x93) TMR3RLH ; /* Timer/Counter 3 Reload High (page 0) */ 63 | __sfr __at (0x94) TMR3L ; /* Timer/Counter 3 Low */ 64 | __sfr __at (0x95) TMR3H ; /* Timer/Counter 3 High */ 65 | __sfr __at (0x96) USB0ADR ; /* USB0 Indirect Address Register */ 66 | __sfr __at (0x97) USB0DAT ; /* USB0 Data Register */ 67 | __sfr __at (0x91) TMR4CN ; /* Timer/Counter 4 Control (page F) */ 68 | __sfr __at (0x92) TMR4RLL ; /* Timer/Counter 4 Reload Low (page F) */ 69 | __sfr __at (0x93) TMR4RLH ; /* Timer/Counter 4 Reload High (page F) */ 70 | __sfr __at (0x98) SCON0 ; /* UART0 Control */ 71 | __sfr __at (0x99) SBUF0 ; /* UART0 Data Buffer */ 72 | __sfr __at (0x9A) CPT1CN ; /* Comparator 1 Control */ 73 | __sfr __at (0x9B) CPT0CN ; /* Comparator 0 Control */ 74 | __sfr __at (0x9C) CPT1MD ; /* Comparator 1 Mode */ 75 | __sfr __at (0x9D) CPT0MD ; /* Comparator 0 Mode */ 76 | __sfr __at (0x9E) CPT1MX ; /* Comparator 1 Mux */ 77 | __sfr __at (0x9F) CPT0MX ; /* Comparator 0 Mux */ 78 | __sfr __at (0xA0) P2 ; /* Port 2 Latch */ 79 | __sfr __at (0xA1) SPI0CFG ; /* SPI0 Configuration */ 80 | __sfr __at (0xA2) SPI0CKR ; /* SPI0 Clock rate control */ 81 | __sfr __at (0xA3) SPI0DAT ; /* SPI0 Data Buffer */ 82 | __sfr __at (0xA4) P0MDOUT ; /* Port 0 Output Mode */ 83 | __sfr __at (0xA5) P1MDOUT ; /* Port 1 Output Mode */ 84 | __sfr __at (0xA6) P2MDOUT ; /* Port 2 Output Mode */ 85 | __sfr __at (0xA7) P3MDOUT ; /* Port 3 Output Mode */ 86 | __sfr __at (0xA8) IE ; /* Interrupt Enable */ 87 | __sfr __at (0xA9) CLKSEL ; /* Clock Select */ 88 | __sfr __at (0xAA) EMI0CN ; /* EMIF control */ 89 | __sfr __at (0xAA) _XPAGE ; /* XDATA/PDATA PAGE */ 90 | __sfr __at (0xAC) SBCON1 ; /* UART1 Baud Rate Generator Control */ 91 | __sfr __at (0xAE) P4MDOUT ; /* Port 4 Mode */ 92 | __sfr __at (0xAF) PFE0CN ; /* Prefetch Engine Control */ 93 | __sfr __at (0xB0) P3 ; /* Port 3 Latch */ 94 | __sfr __at (0xB1) OSCXCN ; /* External Oscillator Control */ 95 | __sfr __at (0xB2) OSCICN ; /* Internal Oscillator Control */ 96 | __sfr __at (0xB3) OSCICL ; /* Internal Oscillator Calibration */ 97 | __sfr __at (0xB4) SBRLL1 ; /* UART1 Baud Rate Generator Low */ 98 | __sfr __at (0xB5) SBRLH1 ; /* UART1 Baud Rate Generator High */ 99 | __sfr __at (0xB6) FLSCL ; /* Flash Scale */ 100 | __sfr __at (0xB7) FLKEY ; /* Flash Lock and Key */ 101 | __sfr __at (0xB8) IP ; /* Interrupt Priority */ 102 | __sfr __at (0xB9) CLKMUL ; /* Clock Multiplier (page 0) */ 103 | __sfr __at (0xBA) AMX0N ; /* AMUX0 Negative Channel Select */ 104 | __sfr __at (0xBB) AMX0P ; /* AMUX0 Positive Channel Select */ 105 | __sfr __at (0xBC) ADC0CF ; /* ADC0 Configuration (page 0) */ 106 | __sfr __at (0xBD) ADC0L ; /* ADC0 Low */ 107 | __sfr __at (0xBE) ADC0H ; /* ADC0 High */ 108 | __sfr __at (0xBF) SFRPAGE ; /* SFR Page Select */ 109 | __sfr __at (0xB9) SMBTC ; /* SMBus0/1 Timing Control (page F) */ 110 | __sfr __at (0xC0) SMB0CN ; /* SMBus0 Control (page 0) */ 111 | __sfr __at (0xC1) SMB0CF ; /* SMBus0 Configuration (page 0) */ 112 | __sfr __at (0xC2) SMB0DAT ; /* SMBus0 Data (page 0) */ 113 | __sfr __at (0xC3) ADC0GTL ; /* ADC0 Greater-Than Compare Low */ 114 | __sfr __at (0xC4) ADC0GTH ; /* ADC0 Greater-Than Compare High */ 115 | __sfr __at (0xC5) ADC0LTL ; /* ADC0 Less-Than Compare Word Low */ 116 | __sfr __at (0xC6) ADC0LTH ; /* ADC0 Less-Than Compare Word High */ 117 | __sfr __at (0xC7) P4 ; /* Port 4 Latch */ 118 | __sfr __at (0xC0) SMB1CN ; /* SMBus1 Control (page F) */ 119 | __sfr __at (0xC1) SMB1CF ; /* SMBus1 Configuration (page F) */ 120 | __sfr __at (0xC2) SMB1DAT ; /* SMBus1 Data (page F) */ 121 | __sfr __at (0xC8) TMR2CN ; /* Timer/Counter 2 Control (page 0) */ 122 | __sfr __at (0xC9) REG01CN ; /* Regulator Control (page 0) */ 123 | __sfr __at (0xCA) TMR2RLL ; /* Timer/Counter 2 Reload Low (page 0) */ 124 | __sfr __at (0xCB) TMR2RLH ; /* Timer/Counter 2 Reload High (page 0) */ 125 | __sfr __at (0xCC) TMR2L ; /* Timer/Counter 2 Low (page 0) */ 126 | __sfr __at (0xCD) TMR2H ; /* Timer/Counter 2 High (page 0) */ 127 | __sfr __at (0xCE) SMB0ADM ; /* SMBus0 Address Mask (page 0) */ 128 | __sfr __at (0xCF) SMB0ADR ; /* SMBus0 Address (page 0) */ 129 | __sfr __at (0xC8) TMR5CN ; /* Timer/Counter 5 Control (page F) */ 130 | __sfr __at (0xCA) TMR5RLL ; /* Timer/Counter 5 Reload Low (page F) */ 131 | __sfr __at (0xCB) TMR5RLH ; /* Timer/Counter 5 Reload High (page F) */ 132 | __sfr __at (0xCC) TMR5L ; /* Timer/Counter 5 Low (page F) */ 133 | __sfr __at (0xCD) TMR5H ; /* Timer/Counter 5 High (page F) */ 134 | __sfr __at (0xCE) SMB1ADM ; /* SMBus1 Address Mask (page F) */ 135 | __sfr __at (0xCF) SMB1ADR ; /* SMBus1 Address (page F) */ 136 | __sfr __at (0xD0) PSW ; /* Program Status Word */ 137 | __sfr __at (0xD1) REF0CN ; /* Voltage Reference Control */ 138 | __sfr __at (0xD2) SCON1 ; /* UART1 Control */ 139 | __sfr __at (0xD3) SBUF1 ; /* UART1 Data Buffer */ 140 | __sfr __at (0xD4) P0SKIP ; /* Port 0 Skip */ 141 | __sfr __at (0xD5) P1SKIP ; /* Port 1 Skip */ 142 | __sfr __at (0xD6) P2SKIP ; /* Port 2 Skip */ 143 | __sfr __at (0xD7) USB0XCN ; /* USB0 Transceiver Control */ 144 | __sfr __at (0xD8) PCA0CN ; /* PCA0 Control */ 145 | __sfr __at (0xD9) PCA0MD ; /* PCA0 Mode */ 146 | __sfr __at (0xDA) PCA0CPM0 ; /* PCA Module 0 Mode Register */ 147 | __sfr __at (0xDB) PCA0CPM1 ; /* PCA Module 1 Mode Register */ 148 | __sfr __at (0xDC) PCA0CPM2 ; /* PCA Module 2 Mode Register */ 149 | __sfr __at (0xDD) PCA0CPM3 ; /* PCA Module 3 Mode Register */ 150 | __sfr __at (0xDE) PCA0CPM4 ; /* PCA Module 4 Mode Register */ 151 | __sfr __at (0xDF) P3SKIP ; /* Port 3 Skip */ 152 | __sfr __at (0xE0) ACC ; /* Accumulator */ 153 | __sfr __at (0xE1) XBR0 ; /* Port I/O Crossbar Control 0 */ 154 | __sfr __at (0xE2) XBR1 ; /* Port I/O Crossbar Control 1 */ 155 | __sfr __at (0xE3) XBR2 ; /* Port I/O Crossbar Control 2 */ 156 | __sfr __at (0xE4) IT01CF ; /* INT0/INT1 Configuration (page 0) */ 157 | __sfr __at (0xE5) SMOD1 ; /* UART1 Mode */ 158 | __sfr __at (0xE6) EIE1 ; /* Extended Interrupt Enable 2 */ 159 | __sfr __at (0xE7) EIE2 ; /* Extended Interrupt Enable 2 */ 160 | __sfr __at (0xE4) CKCON1 ; /* Clock Control 1 (page F) */ 161 | __sfr __at (0xE8) ADC0CN ; /* ADC0 Control */ 162 | __sfr __at (0xE9) PCA0CPL1 ; /* PCA0 Capture 2 Low */ 163 | __sfr __at (0xEA) PCA0CPH1 ; /* PCA0 Capture 2 High */ 164 | __sfr __at (0xEB) PCA0CPL2 ; /* PCA0 Capture 3 Low */ 165 | __sfr __at (0xEC) PCA0CPH2 ; /* PCA0 Capture 3 High */ 166 | __sfr __at (0xED) PCA0CPL3 ; /* PCA0 Capture 4 Low */ 167 | __sfr __at (0xEE) PCA0CPH3 ; /* PCA0 Capture 4 High */ 168 | __sfr __at (0xEF) RSTSRC ; /* Reset Source Configuration/Status */ 169 | __sfr __at (0xF0) B ; /* B Register */ 170 | __sfr __at (0xF1) P0MDIN ; /* Port 0 Input Mode */ 171 | __sfr __at (0xF2) P1MDIN ; /* Port 1 Input Mode */ 172 | __sfr __at (0xF3) P2MDIN ; /* Port 2 Input Mode */ 173 | __sfr __at (0xF4) P3MDIN ; /* Port 3 Input Mode */ 174 | __sfr __at (0xF5) P4MDIN ; /* Port 4 Input Mode */ 175 | __sfr __at (0xF6) EIP1 ; /* External Interrupt Priority 1 */ 176 | __sfr __at (0xF7) EIP2 ; /* External Interrupt Priority 2 */ 177 | __sfr __at (0xF8) SPI0CN ; /* SPI0 Control */ 178 | __sfr __at (0xF9) PCA0L ; /* PCA0 Counter Low */ 179 | __sfr __at (0xFA) PCA0H ; /* PCA0 Counter High */ 180 | __sfr __at (0xFB) PCA0CPL0 ; /* PCA0 Capture 0 Low */ 181 | __sfr __at (0xFC) PCA0CPH0 ; /* PCA0 Capture 0 High */ 182 | __sfr __at (0xFD) PCA0CPL4 ; /* PCA0 Capture 4 Low */ 183 | __sfr __at (0xFE) PCA0CPH4 ; /* PCA0 Capture 4 High */ 184 | __sfr __at (0xFF) VDM0CN ; /* VDD Monitor Control */ 185 | 186 | /* 16-Bit Register definitions */ 187 | __sfr16 __at (0x8382) DP ; /* Data pointer */ 188 | __sfr16 __at (0x9392) TMR3RL ; /* Timer 3 reload register */ 189 | __sfr16 __at (0x9392) TMR4RL ; /* Timer 4 reload register (page F) */ 190 | __sfr16 __at (0x9594) TMR3 ; /* Timer 3 register */ 191 | __sfr16 __at (0x9594) TMR4 ; /* Timer 4 register (page F) */ 192 | __sfr16 __at (0xB5B4) SBRL1 ; /* UART1 Baud Rate Generator */ 193 | __sfr16 __at (0xBEBD) ADC0 ; /* ADC 0 data */ 194 | __sfr16 __at (0xC4C3) ADC0GT ; /* ADC 0 greater than compare */ 195 | __sfr16 __at (0xC6C5) ADC0LT ; /* ADC 0 less than compare */ 196 | __sfr16 __at (0xCBCA) TMR2RL ; /* Timer\Counter 2 reload data */ 197 | __sfr16 __at (0xCBCA) TMR5RL ; /* Timer\Counter 5 reload data (page F) */ 198 | __sfr16 __at (0xCDCC) TMR2 ; /* Timer\Counter 2 data */ 199 | __sfr16 __at (0xCDCC) TMR5 ; /* Timer\Counter 5 data */ 200 | __sfr16 __at (0xEAE9) PCA0CP1 ; /* PCA module 1 capture/compare data */ 201 | __sfr16 __at (0xECEB) PCA0CP2 ; /* PCA module 2 capture/compare data */ 202 | __sfr16 __at (0xEEED) PCA0CP3 ; /* PCA module 3 capture/compare data */ 203 | __sfr16 __at (0xFAF9) PCA0 ; /* PCA 0 counter data */ 204 | __sfr16 __at (0xFCFB) PCA0CP0 ; /* PCA 0 capture data */ 205 | __sfr16 __at (0xFEFD) PCA0CP4 ; /* PCA 4 capture data */ 206 | 207 | /* Bit Definitions for SFRPage 0x00 and SFRPage 0x0F Registers */ 208 | /* TCON 0x88 */ 209 | __sbit __at (0x8F) TF1 ; /* Timer 1 Overflow Flag */ 210 | __sbit __at (0x8E) TR1 ; /* Timer 1 On/Off Control */ 211 | __sbit __at (0x8D) TF0 ; /* Timer 0 Overflow Flag */ 212 | __sbit __at (0x8C) TR0 ; /* Timer 0 On/Off Control */ 213 | __sbit __at (0x8B) IE1 ; /* Ext. Interrupt 1 Edge Flag */ 214 | __sbit __at (0x8A) IT1 ; /* Ext. Interrupt 1 Type */ 215 | __sbit __at (0x89) IE0 ; /* Ext. Interrupt 0 Edge Flag */ 216 | __sbit __at (0x88) IT0 ; /* Ext. Interrupt 0 Type */ 217 | 218 | /* SCON0 0x98 */ 219 | __sbit __at (0x9F) S0MODE ; /* Serial Port 0 Operation Mode */ 220 | /* Bit 6 unused */ 221 | __sbit __at (0x9D) MCE0 ; /* Multiprocessor Communication Enable */ 222 | __sbit __at (0x9C) REN0 ; /* UART0 RX Enable */ 223 | __sbit __at (0x9B) TB80 ; /* Ninth Transmission Bit */ 224 | __sbit __at (0x9A) RB80 ; /* Ninth Receive Bit */ 225 | __sbit __at (0x99) TI0 ; /* UART0 TX Interrupt Flag */ 226 | __sbit __at (0x98) RI0 ; /* UART0 RX Interrupt Flag */ 227 | 228 | /* IE 0xA8 */ 229 | __sbit __at (0xAF) EA ; /* Global Interrupt Enable */ 230 | __sbit __at (0xAE) ESPI0 ; /* SPI0 Interrupt Enable */ 231 | __sbit __at (0xAD) ET2 ; /* Timer 2 Interrupt Enable */ 232 | __sbit __at (0xAC) ES0 ; /* UART0 Interrupt Enable */ 233 | __sbit __at (0xAB) ET1 ; /* Timer 1 Interrupt Enable */ 234 | __sbit __at (0xAA) EX1 ; /* External Interrupt 1 Enable */ 235 | __sbit __at (0xA9) ET0 ; /* Timer 0 Interrupt Enable */ 236 | __sbit __at (0xA8) EX0 ; /* External Interrupt 0 Enable */ 237 | 238 | /* IP 0xB8 */ 239 | /* Bit 7 unused */ 240 | __sbit __at (0xBE) PSPI0 ; /* SPI0 Interrupt Priority */ 241 | __sbit __at (0xBD) PT2 ; /* Timer 2 Priority */ 242 | __sbit __at (0xBC) PS0 ; /* UART0 Priority */ 243 | __sbit __at (0xBB) PT1 ; /* Timer 1 Priority */ 244 | __sbit __at (0xBA) PX1 ; /* External Interrupt 1 Priority */ 245 | __sbit __at (0xB9) PT0 ; /* Timer 0 Priority */ 246 | __sbit __at (0xB8) PX0 ; /* External Interrupt 0 Priority */ 247 | 248 | /* SMB0CN 0xC0 SFR Page=0 */ 249 | __sbit __at (0xC7) MASTER0 ; /* SMBus0 Master/Slave Indicator */ 250 | __sbit __at (0xC6) TXMODE0 ; /* SMBus0 Transmit Mode Indicator */ 251 | __sbit __at (0xC5) STA0 ; /* SMBus0 Start Flag */ 252 | __sbit __at (0xC4) STO0 ; /* SMBus0 Stop Flag */ 253 | __sbit __at (0xC3) ACKRQ0 ; /* SMBus0 Acknowledge Request */ 254 | __sbit __at (0xC2) ARBLOST0 ; /* SMBus0 Arbitration Lost Indicator */ 255 | __sbit __at (0xC1) ACK0 ; /* SMBus0 Acknowledge */ 256 | __sbit __at (0xC0) SI0 ; /* SMBus0 Interrupt Flag */ 257 | 258 | /* SMB1CN 0xC0 SFR Page=F */ 259 | __sbit __at (0xC7) MASTER1 ; /* SMBus1 Master/Slave Indicator */ 260 | __sbit __at (0xC6) TXMODE1 ; /* SMBus1 Transmit Mode Indicator */ 261 | __sbit __at (0xC5) STA1 ; /* SMBus1 Start Flag */ 262 | __sbit __at (0xC4) STO1 ; /* SMBus1 Stop Flag */ 263 | __sbit __at (0xC3) ACKRQ1 ; /* SMBus1 Acknowledge Request */ 264 | __sbit __at (0xC2) ARBLOST1 ; /* SMBus1 Arbitration Lost Indicator */ 265 | __sbit __at (0xC1) ACK1 ; /* SMBus1 Acknowledge */ 266 | __sbit __at (0xC0) SI1 ; /* SMBus1 Interrupt Flag */ 267 | 268 | /* TMR2CN 0xC8 SFR Page=0 */ 269 | __sbit __at (0xCF) TF2H ; /* Timer 2 High-Byte Overflow Flag */ 270 | __sbit __at (0xCE) TF2L ; /* Timer 2 Low-Byte Overflow Flag */ 271 | __sbit __at (0xCD) TF2LEN ; /* Timer 2 Low-Byte Flag Enable */ 272 | __sbit __at (0xCC) TF2CEN ; /* Timer 2 Capture Enable */ 273 | __sbit __at (0xCB) T2SPLIT ; /* Timer 2 Split-Mode Enable */ 274 | __sbit __at (0xCA) TR2 ; /* Timer2 Run Enable */ 275 | __sbit __at (0xC9) T2CSS ; /* Timer 2 Capture Source Select */ 276 | __sbit __at (0xC8) T2XCLK ; /* Timer 2 Clk/8 Clock Source */ 277 | 278 | /* TMR2CN 0xC8 SFR Page=F */ 279 | __sbit __at (0xCF) TF5H ; /* Timer 5 High-Byte Overflow Flag */ 280 | __sbit __at (0xCE) TF5L ; /* Timer 5 Low-Byte Overflow Flag */ 281 | __sbit __at (0xCD) TF5LEN ; /* Timer 5 Low-Byte Flag Enable */ 282 | /* Bit 4 unused */ 283 | __sbit __at (0xCB) T5SPLIT ; /* Timer 5 Split-Mode Enable */ 284 | __sbit __at (0xCA) TR5 ; /* Timer 5 Run Enable */ 285 | /* Bit 1 unused */ 286 | __sbit __at (0xC8) T5XCLK ; /* Timer 5 Clk/8 Clock Source */ 287 | 288 | /* PSW 0xD0 */ 289 | __sbit __at (0xD7) CY ; /* Carry Flag */ 290 | __sbit __at (0xD6) AC ; /* Auxiliary Carry Flag */ 291 | __sbit __at (0xD5) F0 ; /* User Flag 0 */ 292 | __sbit __at (0xD4) RS1 ; /* Register Bank Select 1 */ 293 | __sbit __at (0xD3) RS0 ; /* Register Bank Select 0 */ 294 | __sbit __at (0xD2) OV ; /* Overflow Flag */ 295 | __sbit __at (0xD1) F1 ; /* User Flag 1 */ 296 | __sbit __at (0xD0) PARITY ; /* Accumulator Parity Flag */ 297 | 298 | /* PCA0CN 0xD8 */ 299 | __sbit __at (0xDF) CF ; /* PCA0 Counter Overflow Flag */ 300 | __sbit __at (0xDE) CR ; /* PCA0 Counter Run Control Bit */ 301 | /* Bit 5 unused */ 302 | __sbit __at (0xDC) CCF4 ; /* PCA0 Module 4 Capture/Compare Flag */ 303 | __sbit __at (0xDB) CCF3 ; /* PCA0 Module 3 Capture/Compare Flag */ 304 | __sbit __at (0xDA) CCF2 ; /* PCA0 Module 2 Capture/Compare Flag */ 305 | __sbit __at (0xD9) CCF1 ; /* PCA0 Module 1 Capture/Compare Flag */ 306 | __sbit __at (0xD8) CCF0 ; /* PCA0 Module 0 Capture/Compare Flag */ 307 | 308 | /* ADC0CN 0xE8 */ 309 | __sbit __at (0xEF) AD0EN ; /* ADC0 Enable */ 310 | __sbit __at (0xEE) AD0TM ; /* ADC0 Track Mode Bit */ 311 | __sbit __at (0xED) AD0INT ; /* ADC0 Conversion Complete Interrupt Flag */ 312 | __sbit __at (0xEC) AD0BUSY ; /* ADC0 Busy Flag */ 313 | __sbit __at (0xEB) AD0WINT ; /* ADC0 Window Compare Interrupt Flag */ 314 | __sbit __at (0xEA) AD0CM2 ; /* ADC0 Start Of Conversion Mode Bit 2 */ 315 | __sbit __at (0xE9) AD0CM1 ; /* ADC0 Start Of Conversion Mode Bit 1 */ 316 | __sbit __at (0xE8) AD0CM0 ; /* ADC0 Start Of Conversion Mode Bit 0 */ 317 | 318 | /* SPI0CN 0xF8 */ 319 | __sbit __at (0xFF) SPIF ; /* SPI0 Interrupt Flag */ 320 | __sbit __at (0xFE) WCOL ; /* SPI0 Write Collision Flag */ 321 | __sbit __at (0xFD) MODF ; /* SPI0 Mode Fault Flag */ 322 | __sbit __at (0xFC) RXOVRN ; /* SPI0 RX Overrun Flag */ 323 | __sbit __at (0xFB) NSSMD1 ; /* SPI0 Slave Select Mode 1 */ 324 | __sbit __at (0xFA) NSSMD0 ; /* SPI0 Slave Select Mode 0 */ 325 | __sbit __at (0xF9) TXBMT ; /* SPI0 TX Buffer Empty Flag */ 326 | __sbit __at (0xF8) SPIEN ; /* SPI0 Enable */ 327 | 328 | //----------------------------------------------------------------------------- 329 | // Interrupt Priorities 330 | //----------------------------------------------------------------------------- 331 | 332 | #define INTERRUPT_INT0 0 // External Interrupt 0 333 | #define INTERRUPT_TIMER0 1 // Timer 0 Overflow 334 | #define INTERRUPT_INT1 2 // External Interrupt 1 335 | #define INTERRUPT_TIMER1 3 // Timer 1 Overflow 336 | #define INTERRUPT_UART0 4 // UART0 337 | #define INTERRUPT_TIMER2 5 // Timer 2 Overflow 338 | #define INTERRUPT_SPI0 6 // SPI0 339 | #define INTERRUPT_SMBUS0 7 // SMBus0 Interface 340 | #define INTERRUPT_USB0 8 // SMBus0 Interface 341 | #define INTERRUPT_ADC0_WINDOW 9 // ADC0 Window Comparison 342 | #define INTERRUPT_ADC0_EOC 10 // ADC0 End Of Conversion 343 | #define INTERRUPT_PCA0 11 // PCA0 Peripheral 344 | #define INTERRUPT_COMPARATOR0 12 // Comparator 0 Comparison 345 | #define INTERRUPT_COMPARATOR1 13 // Comparator 1 Comparison 346 | #define INTERRUPT_TIMER3 14 // Timer 3 Overflow 347 | #define INTERRUPT_VBUS 15 // VBus Interrupt 348 | #define INTERRUPT_UART1 16 // UART1 349 | #define INTERRUPT_SMBUS1 18 // SMBus1 Interface 350 | #define INTERRUPT_TIMER4 19 // Timer 4 Overflow 351 | #define INTERRUPT_TIMER5 20 // Timer 5 Overflow 352 | 353 | #endif /* #define __C8051F380_H__ */ 354 | --------------------------------------------------------------------------------