diff --git a/.gitmodules b/.gitmodules index e378912..5d22636 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "third_party/fx2lib-linux-headers"] path = third_party/fx2lib-linux-headers url = https://github.com/mithro/fx2lib-linux-headers +[submodule "third_party/libfx2"] + path = third_party/libfx2 + url = https://github.com/whitequark/libfx2.git diff --git a/.travis.yml b/.travis.yml index 76e0569..555bad7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ addons: install: - export BOARD="$B" && echo "BOARD='$BOARD'" - - export TARGETS="$T" && echo "TARGETS='$TARGETS'" + - export DIR="$D" && echo "DIR='$DIR'" - make conda - export PATH=$PWD/conda/bin:$PATH - which sdcc @@ -16,36 +16,18 @@ install: - ./.travis/setup.sh script: - - make $TARGETS + - make -C $DIR jobs: fail_fast: true include: #----------------------------------------- - # Video targets + # audio #----------------------------------------- - stage: Build - env: B=opsis T="firmware-fx2" + env: B=opsis D="examples/audio" - stage: Build - env: B=atlys T="firmware-fx2" - - #----------------------------------------- - # Audio targets - #----------------------------------------- - - stage: Build - env: B=opsis T="firmware-audio-fx2" - - stage: Build - env: B=atlys T="firmware-audio-fx2" - - stage: Build - env: B=fx2miniboard T="firmware-audio-fx2" - - #----------------------------------------- - # Unconfigured targets - #----------------------------------------- - - stage: Build - env: B=opsis T="firmware-unconfigured" - - stage: Build - env: B=atlys T="firmware-unconfigured" + env: B=atlys D="examples/audio" #----------------------------------------- # Build and deploy docs diff --git a/common/common.mk b/common/common.mk index 4344bb9..5d3abfa 100644 --- a/common/common.mk +++ b/common/common.mk @@ -1,114 +1,43 @@ -# -# Copyright (C) 2009-2012 Chris McClelland -# Copyright 2015 Joel Stanley -# Copyright 2017 Kyle Robbertze -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# +# configuration +BOARD ?= opsis +MODEL ?= small +SYNCDELAYLEN ?= 4 -# To build the firmware you will need: -# SDCC from http://sdcc.sourceforge.net -# Git from https://git-scm.com/ -# -# To build a firmware suitable for loading into RAM: -# make -# -# To build a firmware suitable for loading from EEPROM: -# make FLAGS="-DEEPROM" -# -# To load a firmware: -# make load -# You will need HDMI2USB-mode-switch from -# https://github.com/timvideos/HDMI2USB-mode-switch -# -# Common rules +# use conda enviorment if it exists MAKEFILE_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) export PATH := $(MAKEFILE_PATH)../conda/bin:$(PATH) -LIBS ?= $(FX2LIBDIR)/lib/fx2.lib -INCS += -I sdcc -I$(FX2LIBDIR)/include -I. -I$(COMMON_DIR)/boards - -# Settings specific for the TimVideo hdmi2usb firmware -BOARD ?= opsis -FLAGS +=-DDEBUG -DBOARD_$(BOARD) - -# Must only be hex numbers -FIRMWARE_VERSION := $(shell date +%Y%m%d) - -CC_OBJS := $(CC_SRCS:%.c=%.rel) -AS_OBJS := $(AS_SRCS:%.a51=%.rel) - -CC := sdcc -AS8051 := sdas8051 -AS := $(AS8051) - -CFLAGS += -DDATE=0x$(FIRMWARE_VERSION) -mmcs51 $(FLAGS) -CFLAGS += --std-c99 -DSDCC -Wa"-p" --xram-size 0x0200 - -# Use make V=1 for a verbose build. -ifndef V - Q_CC=@echo ' CC ' $@; - Q_AS=@echo ' AS ' $@; - Q_LINK=@echo ' LINK ' $@; - Q_RM=@echo ' CLEAN '; - Q_OBJCOPY=@echo ' OBJCOPY ' $@; - Q_GEN=@echo ' GEN ' $@; +CFLAGS = +CFLAGS += --std-sdcc99 +CFLAGS += -Wa"-p" +CFLAGS += --xram-size 0x0200 +CFLAGS += -DSYNCDELAYLEN=$(SYNCDELAYLEN) + +# should to override previously set flags +FLAGS ?= +CFLAGS += $(FLAGS) + +# set USB IDs depending on board +ifeq (${BOARD},atlys) + VID := 1D50 + PID := 60B7 + DID := 0002 +else + ifeq (${BOARD},opsis) + VID := 2A19 + PID := 5442 + DID := 0002 + else + $(error "Unknown board type '$(BOARD)'") + endif endif -.PHONY: all clean distclean check check-descriptors check_int2jt load - -all: $(TARGET).hex - -check_int2jt: $(TARGET).hex - @export REQUESTED=$(shell grep "INT2JT=" $(TARGET).map | sed -e's/INT2JT=//'); \ - export ACTUAL=$(shell grep "C:.*INT2JT" $(TARGET).map | sed -e's/C: *0*\([^ ]*\) _INT2JT.*/0x\1/' | tr A-Z a-z ); \ - if [ "$$REQUESTED" != "$$ACTUAL" ]; then \ - echo "INT2JT at $$ACTUAL but requested $$REQUESTED"; \ - exit 1; \ - fi - -check: check_int2jt - -clean: - $(Q_RM)$(RM) *.adb *.asm *.cdb *.iic *.lk *.lnk *.lst *.omf *.map \ - *.mem *.rel *.rst *.sym descriptors_strings.* a.out date.h \ - date.inc progOffsets.h version_data.h version_data.c ${TARGET}.hex - cd $(FX2LIBDIR) && make clean - -distclean: clean - $(RM) -r $(FX2LIBDIR) - -load: $(TARGET).hex - hdmi2usb-mode-switch --load-fx2-firmware $(TARGET).hex - -$(CC_SRCS) $(AS_SRCS): $(FX2LIBDIR)/lib/fx2.lib - -$(FX2LIBDIR)/lib/fx2.lib: $(FX2LIBDIR)/.git - cd $(dir $@) && make -j1 - -# We depend on a file inside the directory as git creates an -# empty dir for us. -# -# Note that although we have the variable FX2LIBDIR, the submodule -# magic will always check it out in fx2lib/ -$(FX2LIBDIR)/.git: ../.gitmodules - git submodule sync --recursive -- $$(dirname $@) - git submodule update --recursive --init $$(dirname $@) - touch $@ -r ../.gitmodules +CFLAGS += -DVID=0x$(VID) -DPID=0x$(PID) -DDID=0x$(DID) -$(TARGET).hex: $(CC_OBJS) $(AS_OBJS) - $(Q_LINK)$(CC) $(CFLAGS) -o $@ $+ $(LIBS) +LIBFX2DIR ?= ../third_party/libfx2 +# variable required by libfx2 build system +LIBFX2 = $(LIBFX2DIR)/firmware/library +include $(LIBFX2)/fx2rules.mk -%.rel: %.a51 - $(Q_AS)$(AS) -logs $? +# force proper dependecy to automatically build libfx2 +$(LIBFX2)/lib/$(MODEL)/fx2.lib: $(LIBFX2)/.stamp diff --git a/common/uac.c b/common/uac.c new file mode 100644 index 0000000..733c0ab --- /dev/null +++ b/common/uac.c @@ -0,0 +1,175 @@ +#include "uac.h" + +extern usb_descriptor_set_c usb_descriptor_set; + +// keeps track of current alternate setting of streaming interface +__xdata uint8_t uac_as_alt_setting = 0; +// store the interface numbers for set/get interface handlers +__xdata static uint8_t if_num_ctrl; +__xdata static uint8_t if_num_streaming; + +bool uac_handle_usb_set_interface(uint8_t interface, uint8_t alt_setting) { + if (interface == if_num_ctrl && alt_setting == 0) { + usb_reset_data_toggles(&usb_descriptor_set, interface, alt_setting); + return true; + } + if (interface == if_num_streaming && (alt_setting == 0 || alt_setting == 1)) { + // I belive we do not need to reset our endpoint configuration regsiters, as host should know + // that in alt_setting 0 there are no endpoints associated with this interface, so host will + // not send any IN requests + uac_as_alt_setting = alt_setting; + usb_reset_data_toggles(&usb_descriptor_set, interface, alt_setting); + return true; + } + return false; // not handled +} + +bool uac_handle_usb_get_interface(uint8_t interface) { + if (interface == if_num_ctrl) { + EP0BUF[0] = 0; // only 1 alternate setting + SETUP_EP0_BUF(1); + } + if (interface == if_num_ctrl) { + EP0BUF[0] = uac_as_alt_setting; + SETUP_EP0_BUF(1); + } + return false; // not handled +} + +void uac_config(struct uac_configuration *config) { + if_num_ctrl = config->if_num_ctrl; + if_num_streaming = config->if_num_ctrl + 1; + // interface numbers + ((__xdata struct usb_desc_interface *) &usb_uac_std_ac_interface)->bInterfaceNumber = if_num_ctrl; + ((__xdata struct usb_desc_interface *) &usb_uac_std_streaming_interface_alt0)->bInterfaceNumber = if_num_streaming; + ((__xdata struct usb_desc_interface *) &usb_uac_std_streaming_interface_alt1)->bInterfaceNumber = if_num_streaming; + ((__xdata struct usb_desc_uac1_ac_header *) &usb_uac_ac_header)->baInterfaceNr[0] = if_num_streaming; + // endpoint numbers + ((__xdata struct usb_desc_endpoint *) &usb_uac_audio_endpoint)->bEndpointAddress = config->ep_addr_streaming | USB_DIR_IN; + // strings + ((__xdata struct usb_desc_uac_input_terminal *) &usb_uac_input_terminal)->iChannelNames = config->i_str_channel_left; +} + +/*** Descriptors **************************************************************/ + +usb_desc_interface_c usb_uac_std_ac_interface = { + .bLength = sizeof(struct usb_desc_interface), + .bDescriptorType = USB_DESC_INTERFACE, + .bInterfaceNumber = 0, // uac_config + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + +#define LENGTH_uac_input_terminal (sizeof(struct usb_desc_uac_input_terminal)) +usb_desc_uac_input_terminal_c usb_uac_input_terminal = { + .bLength = LENGTH_uac_input_terminal, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_INPUT_TERMINAL, + .bTerminalID = 1, + .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE, + .bAssocTerminal = 0, + .bNrChannels = 2, // stereo + .wChannelConfig = (UAC_CHANNEL_LEFT | UAC_CHANNEL_RIGHT), + .iChannelNames = 0, // uvc_config // first channel name, other channels must have consequetive indices + .iTerminal = 0, +}; + +#define LENGTH_uac_output_terminal (sizeof(struct usb_desc_uac1_output_terminal)) +usb_desc_uac1_output_terminal_c usb_uac_output_terminal = { + .bLength = LENGTH_uac_output_terminal, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, + .bTerminalID = 2, + .wTerminalType = UAC_OUTPUT_TERMINAL_STREAMING, + .bAssocTerminal = 0, + .bSourceID = 1, // connected to input terminal + .iTerminal = 0, +}; + +#define LENGTH_uac_ac_header (sizeof(struct usb_desc_uac1_ac_header) + 1) +usb_desc_uac1_ac_header_c usb_uac_ac_header = { + .bLength = LENGTH_uac_ac_header, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_MS_HEADER, + .bcdADC = UAC_BCD_V10, + .wTotalLength = // this descriptor + all unit and terminal descriptors + LENGTH_uac_ac_header + + LENGTH_uac_input_terminal + + LENGTH_uac_output_terminal, + .bInCollection = 1, // one interface in collection + .baInterfaceNr = { 0 }, // uac_config // streaing interface +}; + +// Setting 0 of streaming interface, no endpoints which means this is a zero-bandwidth +// setting to allow host to temporarily disable audio in case of bandiwdth problems +usb_desc_interface_c usb_uac_std_streaming_interface_alt0 = { + .bLength = sizeof(struct usb_desc_interface), + .bDescriptorType = USB_DESC_INTERFACE, + .bInterfaceNumber = 0, // uac_config + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + +// Setting 1 of streaming interface, regular operation +usb_desc_interface_c usb_uac_std_streaming_interface_alt1 = { + .bLength = sizeof(struct usb_desc_interface), + .bDescriptorType = USB_DESC_INTERFACE, + .bInterfaceNumber = 0, // uac_config + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + +usb_desc_uac1_as_header_c usb_uac_as_header = { + .bLength = sizeof(struct usb_desc_uac1_as_header), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_AS_GENERAL, + .bTerminalLink = 2, // connected to output terminal + .bDelay = 1, + .wFormatTag = UAC_FORMAT_TYPE_I_PCM, +}; + +usb_desc_uac_format_type_i_discrete_c usb_uac_format = { + .bLength = sizeof(struct usb_desc_uac_format_type_i_discrete) + 3, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_FORMAT_TYPE, + .bFormatType = UAC_FORMAT_TYPE_I, + .bNrChannels = 2, + .bSubframeSize = 2, + .bBitResolution = 16, + .bSamFreqType = 1, + .tSamFreq = {{0x40, 0x1F, 0x00}}, // 8000Hz, little endian +}; + +/*** UAC: endpoints ***********************************************************/ + +usb_desc_audio_endpoint_c usb_uac_audio_endpoint = { + .bLength = sizeof(struct usb_desc_audio_endpoint), + .bDescriptorType = USB_DESC_ENDPOINT, + .bEndpointAddress = 0, // uac_config + .bmAttributes = USB_XFER_ISOCHRONOUS, + .wMaxPacketSize = 512, + .bInterval = 4, + .bRefresh = 0, + .bSynchAddress = 0, +}; + +usb_desc_uac_iso_endpoint_c usb_uac_iso_endpoint = { + .bLength = sizeof(struct usb_desc_uac_iso_endpoint), + .bDescriptorType = USB_DT_CS_ENDPOINT, + .bDescriptorSubtype = UAC_AS_GENERAL, + .bmAttributes = 0, + .bLockDelayUnits = 0, + .wLockDelay = 0, +}; diff --git a/common/uac.h b/common/uac.h new file mode 100644 index 0000000..59b9405 --- /dev/null +++ b/common/uac.h @@ -0,0 +1,48 @@ +#ifndef UAC_H +#define UAC_H + +#include +#include "uac_defs.h" + +// control and streaming interface +#define UAC_NUM_INTERFACES 2 + +// UAC descriptors +extern usb_desc_interface_c usb_uac_std_ac_interface; +extern usb_desc_uac_input_terminal_c usb_uac_input_terminal; +extern usb_desc_uac1_output_terminal_c usb_uac_output_terminal; +extern usb_desc_uac1_ac_header_c usb_uac_ac_header; +extern usb_desc_interface_c usb_uac_std_streaming_interface_alt0; +extern usb_desc_interface_c usb_uac_std_streaming_interface_alt1; +extern usb_desc_uac1_as_header_c usb_uac_as_header; +extern usb_desc_uac_format_type_i_discrete_c usb_uac_format; +extern usb_desc_audio_endpoint_c usb_uac_audio_endpoint; +extern usb_desc_uac_iso_endpoint_c usb_uac_iso_endpoint; + +// TODO: { .generic = (struct usb_desc_generic *) &usb_uac_if_assoc }, +// Marco for adding descriptors to usb_configuration_c +#define UAC_DESCRIPTORS_LIST \ + { .interface = &usb_uac_std_ac_interface }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_ac_header }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_input_terminal }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_output_terminal }, \ + { .interface = &usb_uac_std_streaming_interface_alt0 }, \ + { .interface = &usb_uac_std_streaming_interface_alt1 }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_as_header }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_format }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_audio_endpoint }, \ + { .generic = (struct usb_desc_generic *) &usb_uac_iso_endpoint }, + +struct uac_configuration { + uint8_t if_num_ctrl; + // if_num_streaming = if_num_ctrl + 1 + uint8_t ep_addr_streaming; + uint8_t i_str_channel_left; // index of left channel string + // i_str_channel_right = i_str_channel_left + 1 +}; + +void uac_config(struct uac_configuration *config); +bool uac_handle_usb_set_interface(uint8_t interface, uint8_t alt_setting); +bool uac_handle_usb_get_interface(uint8_t interface); + +#endif /* UAC_H */ diff --git a/common/uac_defs.h b/common/uac_defs.h new file mode 100644 index 0000000..ac34996 --- /dev/null +++ b/common/uac_defs.h @@ -0,0 +1,311 @@ +#ifndef UAC_DEFS_H +#define UAC_DEFS_H + +/* USB Audio Class */ + +#include "usb_defs.h" + +// TODO: this has been extracted from linux headers, but should be organised better, +// we also need one naming convention corresponding to that in libfx2 +enum { + /* bInterfaceProtocol values to denote the version of the standard used */ + UAC_VERSION_1 = 0x00, + UAC_VERSION_2 = 0x20, + + USB_CLASS_AUDIO = 0x01, + + /* A.2 Audio Interface Subclass Codes */ + USB_SUBCLASS_AUDIOCONTROL = 0x01, + USB_SUBCLASS_AUDIOSTREAMING = 0x02, + USB_SUBCLASS_MIDISTREAMING = 0x03, + + /* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ + UAC_HEADER = 0x01, + UAC_INPUT_TERMINAL = 0x02, + UAC_OUTPUT_TERMINAL = 0x03, + UAC_MIXER_UNIT = 0x04, + UAC_SELECTOR_UNIT = 0x05, + UAC_FEATURE_UNIT = 0x06, + UAC1_PROCESSING_UNIT = 0x07, + UAC1_EXTENSION_UNIT = 0x08, + + /* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ + UAC_AS_GENERAL = 0x01, + UAC_FORMAT_TYPE = 0x02, + UAC_FORMAT_SPECIFIC = 0x03, + + /* A.7 Processing Unit Process Types */ + UAC_PROCESS_UNDEFINED = 0x00, + UAC_PROCESS_UP_DOWNMIX = 0x01, + UAC_PROCESS_DOLBY_PROLOGIC = 0x02, + UAC_PROCESS_STEREO_EXTENDER = 0x03, + UAC_PROCESS_REVERB = 0x04, + UAC_PROCESS_CHORUS = 0x05, + UAC_PROCESS_DYN_RANGE_COMP = 0x06, + + /* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ + UAC_EP_GENERAL = 0x01, + + /* A.9 Audio Class-Specific Request Codes */ + UAC_SET_ = 0x00, + UAC_GET_ = 0x80, + + UAC__CUR = 0x1, + UAC__MIN = 0x2, + UAC__MAX = 0x3, + UAC__RES = 0x4, + UAC__MEM = 0x5, + + UAC_SET_CUR = (UAC_SET_ | UAC__CUR), + UAC_GET_CUR = (UAC_GET_ | UAC__CUR), + UAC_SET_MIN = (UAC_SET_ | UAC__MIN), + UAC_GET_MIN = (UAC_GET_ | UAC__MIN), + UAC_SET_MAX = (UAC_SET_ | UAC__MAX), + UAC_GET_MAX = (UAC_GET_ | UAC__MAX), + UAC_SET_RES = (UAC_SET_ | UAC__RES), + UAC_GET_RES = (UAC_GET_ | UAC__RES), + UAC_SET_MEM = (UAC_SET_ | UAC__MEM), + UAC_GET_MEM = (UAC_GET_ | UAC__MEM), + + UAC_GET_STAT = 0xff, + + /* A.10 Control Selector Codes */ + + /* A.10.1 Terminal Control Selectors */ + UAC_TERM_COPY_PROTECT = 0x01, + + /* A.10.2 Feature Unit Control Selectors */ + UAC_FU_MUTE = 0x01, + UAC_FU_VOLUME = 0x02, + UAC_FU_BASS = 0x03, + UAC_FU_MID = 0x04, + UAC_FU_TREBLE = 0x05, + UAC_FU_GRAPHIC_EQUALIZER = 0x06, + UAC_FU_AUTOMATIC_GAIN = 0x07, + UAC_FU_DELAY = 0x08, + UAC_FU_BASS_BOOST = 0x09, + UAC_FU_LOUDNESS = 0x0a, + + /* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ + UAC_UD_ENABLE = 0x01, + UAC_UD_MODE_SELECT = 0x02, + + /* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ + UAC_DP_ENABLE = 0x01, + UAC_DP_MODE_SELECT = 0x02, + + /* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ + UAC_3D_ENABLE = 0x01, + UAC_3D_SPACE = 0x02, + + /* A.10.3.4 Reverberation Processing Unit Control Selectors */ + UAC_REVERB_ENABLE = 0x01, + UAC_REVERB_LEVEL = 0x02, + UAC_REVERB_TIME = 0x03, + UAC_REVERB_FEEDBACK = 0x04, + + /* A.10.3.5 Chorus Processing Unit Control Selectors */ + UAC_CHORUS_ENABLE = 0x01, + UAC_CHORUS_LEVEL = 0x02, + UAC_CHORUS_RATE = 0x03, + UAC_CHORUS_DEPTH = 0x04, + + /* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ + UAC_DCR_ENABLE = 0x01, + UAC_DCR_RATE = 0x02, + UAC_DCR_MAXAMPL = 0x03, + UAC_DCR_THRESHOLD = 0x04, + UAC_DCR_ATTACK_TIME = 0x05, + UAC_DCR_RELEASE_TIME = 0x06, + + /* A.10.4 Extension Unit Control Selectors */ + UAC_XU_ENABLE = 0x01, + + /* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ + UAC_MS_HEADER = 0x01, + UAC_MIDI_IN_JACK = 0x02, + UAC_MIDI_OUT_JACK = 0x03, + + /* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ + UAC_MS_GENERAL = 0x01, + + /* Terminals - 2.1 USB Terminal Types */ + UAC_TERMINAL_UNDEFINED = 0x100, + UAC_TERMINAL_STREAMING = 0x101, + UAC_TERMINAL_VENDOR_SPEC = 0x1FF, + + + UAC_BCD_V10 = 0x100, + UAC_CHANNEL_LEFT = 0x1, + UAC_CHANNEL_RIGHT = 0x2, + UAC_OUTPUT_TERMINAL_STREAMING = 0x101, + + USB_DT_CS_DEVICE = (USB_TYPE_CLASS | USB_DESC_DEVICE), + USB_DT_CS_CONFIG = (USB_TYPE_CLASS | USB_DESC_CONFIGURATION), + USB_DT_CS_STRING = (USB_TYPE_CLASS | USB_DESC_STRING), + USB_DT_CS_INTERFACE = (USB_TYPE_CLASS | USB_DESC_INTERFACE), + USB_DT_CS_ENDPOINT = (USB_TYPE_CLASS | USB_DESC_ENDPOINT), + + /* Terminals - 2.2 Input Terminal Types */ + UAC_INPUT_TERMINAL_UNDEFINED = 0x200, + UAC_INPUT_TERMINAL_MICROPHONE = 0x201, + UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE = 0x202, + UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE = 0x203, + UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE = 0x204, + UAC_INPUT_TERMINAL_MICROPHONE_ARRAY = 0x205, + UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY = 0x206, + + /* Terminals - 2.3 Output Terminal Types */ + UAC_OUTPUT_TERMINAL_UNDEFINED = 0x300, + UAC_OUTPUT_TERMINAL_SPEAKER = 0x301, + UAC_OUTPUT_TERMINAL_HEADPHONES = 0x302, + UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO = 0x303, + UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER = 0x304, + UAC_OUTPUT_TERMINAL_ROOM_SPEAKER = 0x305, + UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER = 0x306, + UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER = 0x307, + + /* Formats - A.1.1 Audio Data Format Type I Codes */ + UAC_FORMAT_TYPE_I_UNDEFINED = 0x0, + UAC_FORMAT_TYPE_I_PCM = 0x1, + UAC_FORMAT_TYPE_I_PCM8 = 0x2, + UAC_FORMAT_TYPE_I_IEEE_FLOAT = 0x3, + UAC_FORMAT_TYPE_I_ALAW = 0x4, + UAC_FORMAT_TYPE_I_MULAW = 0x5, + + /* Formats - A.2 Format Type Codes */ + UAC_FORMAT_TYPE_UNDEFINED = 0x0, + UAC_FORMAT_TYPE_I = 0x1, + UAC_FORMAT_TYPE_II = 0x2, + UAC_FORMAT_TYPE_III = 0x3, + UAC_EXT_FORMAT_TYPE_I = 0x81, + UAC_EXT_FORMAT_TYPE_II = 0x82, + UAC_EXT_FORMAT_TYPE_III = 0x83, +}; + + +/* 4.3.2 Class-Specific AC Interface Descriptor */ +struct usb_desc_uac1_ac_header { + uint8_t bLength; /* 8 + n */ + uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ + uint8_t bDescriptorSubtype; /* UAC_MS_HEADER */ + uint16_t bcdADC; /* 0x0100 */ + uint16_t wTotalLength; /* includes Unit and Terminal desc. */ + uint8_t bInCollection; /* n */ + uint8_t baInterfaceNr[]; /* [n] */ +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac1_ac_header) + +/* 4.5.2 Class-Specific AS Interface Descriptor */ +struct usb_desc_uac1_as_header { + uint8_t bLength; /* in bytes: 7 */ + uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ + uint8_t bDescriptorSubtype; /* AS_GENERAL */ + uint8_t bTerminalLink; /* Terminal ID of connected Terminal */ + uint8_t bDelay; /* Delay introduced by the data path */ + uint16_t wFormatTag; /* The Audio Data Format */ +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac1_as_header) + +struct usb_desc_uac1_output_terminal { + uint8_t bLength; /* in bytes: 9 */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /* Constant uniquely terminal ID */ + uint16_t wTerminalType; /* USB Audio Terminal Types */ + uint8_t bAssocTerminal; /* ID of the Input Terminal associated */ + uint8_t bSourceID; /* ID of the connected Unit or Terminal*/ + uint8_t iTerminal; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac1_output_terminal) + +/* Formats - A.1.1 Audio Data Format Type I Codes */ +struct usb_desc_uac_format_type_i_continuous { + uint8_t bLength; /* in bytes: 8 + (ns * 3) */ + uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ + uint8_t bDescriptorSubtype; /* FORMAT_TYPE */ + uint8_t bFormatType; /* FORMAT_TYPE_1 */ + uint8_t bNrChannels; /* physical channels in the stream */ + uint8_t bSubframeSize; /* */ + uint8_t bBitResolution; + uint8_t bSamFreqType; + uint8_t tLowerSamFreq[3]; + uint8_t tUpperSamFreq[3]; +}; +struct usb_desc_uac_format_type_i_discrete { + uint8_t bLength; /* in bytes: 8 + (ns * 3) */ + uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ + uint8_t bDescriptorSubtype; /* FORMAT_TYPE */ + uint8_t bFormatType; /* FORMAT_TYPE_1 */ + uint8_t bNrChannels; /* physical channels in the stream */ + uint8_t bSubframeSize; + uint8_t bBitResolution; + uint8_t bSamFreqType; + uint8_t tSamFreq[][3]; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac_format_type_i_continuous) +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac_format_type_i_discrete) + +/* 4.3.2.1 Input Terminal Descriptor */ +struct usb_desc_uac_input_terminal { + uint8_t bLength; /* in bytes: 12 */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /* Constant uniquely terminal ID */ + uint16_t wTerminalType; /* USB Audio Terminal Types */ + uint8_t bAssocTerminal; /* ID of the Output Terminal associated */ + uint8_t bNrChannels; /* Number of logical output channels */ + uint16_t wChannelConfig; + uint8_t iChannelNames; + uint8_t iTerminal; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac_input_terminal) + +/* Formats - A.2 Format Type Codes */ +struct usb_desc_uac_iso_endpoint { + uint8_t bLength; /* in bytes: 7 */ + uint8_t bDescriptorType; /* USB_DT_CS_ENDPOINT */ + uint8_t bDescriptorSubtype; /* EP_GENERAL */ + uint8_t bmAttributes; + uint8_t bLockDelayUnits; + uint16_t wLockDelay; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_uac_iso_endpoint) + +/* USB_DT_ENDPOINT: Audio Endpoint descriptor */ +struct usb_desc_audio_endpoint { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + /* NOTE: these two are _only_ in audio endpoints. */ + uint8_t bRefresh; + uint8_t bSynchAddress; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_audio_endpoint) + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_desc_dev_qualifier { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bRESERVED; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_dev_qualifier) + +#endif /* UAC_DEFS_H */ diff --git a/common/usb_defs.h b/common/usb_defs.h new file mode 100644 index 0000000..37a7870 --- /dev/null +++ b/common/usb_defs.h @@ -0,0 +1,36 @@ +#ifndef USB_DEFS_H +#define USB_DEFS_H + +#include +#include + +// Macro to easily define typedefs for descriptor structures +#define USB_DESC_CONST_CODE_TYPEDEF(desc) \ + typedef __code const struct desc \ + desc ## _c; + +enum { + // Interface association descriptor, requires proper device descriptor + // see: USB Interface Association Descriptor Device Class Code and Use Model, 1.0 + // https://www.usb.org/sites/default/files/iadclasscode_r10.pdf + USB_DEV_CLASS_MISCELLANEOUS = 0xef, + USB_DEV_SUBCLASS_COMMON = 0x02, + USB_DEV_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR = 0x01, + USB_DESC_IF_ASSOC = 0x0b, +}; + +struct usb_desc_if_assoc { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +}; + +USB_DESC_CONST_CODE_TYPEDEF(usb_desc_if_assoc) + + +#endif /* USB_DEFS_H */ diff --git a/examples/audio/Makefile b/examples/audio/Makefile new file mode 100644 index 0000000..208104d --- /dev/null +++ b/examples/audio/Makefile @@ -0,0 +1,7 @@ +TARGET = audio +LIBFX2DIR = ../../third_party/libfx2 +LIBRARIES = fx2 fx2usb fx2isrs +FLAGS = -I../../common -DDEBUG +SOURCES = main descriptors ../../common/uac + +include ../../common/common.mk diff --git a/examples/audio/README.md b/examples/audio/README.md new file mode 100644 index 0000000..801638b --- /dev/null +++ b/examples/audio/README.md @@ -0,0 +1,16 @@ +# USB audio example + +This is an example application implementing USB audio class (UAC) (see: [Universal Serial Bus Device Class Definition for Audio Devices](https://usb.org/)). + +Device descriptor uses class/subclass/protocol compatible with Interface Association Descriptors +(see: [USB Interface Association Descriptor Device Class Code and Use Model, 1.0](https://www.usb.org/sites/default/files/iadclasscode_r10.pdf)). + +There are two interfaces: + +* Audio control interface: 0 endpoints - no need for interrupt endpoint + +* Audio streaming interface (with alternate settings 0 and 1) + * alternate setting 0: no endpoints, host can use it to disable audio in case of bandwidth problems + * alternate setting 1: single isochronous endpoint + +The application provides simple audio topology consisting of a single input terminal and single output terminal. diff --git a/examples/audio/descriptors.c b/examples/audio/descriptors.c new file mode 100644 index 0000000..9069cf1 --- /dev/null +++ b/examples/audio/descriptors.c @@ -0,0 +1,56 @@ +#include +#include + +#include "uac.h" + +usb_ascii_string_c usb_strings[] = { + "TimVideos.us", + "USB Audio Class example", + "Left", + "Right", +}; + +usb_desc_device_c usb_device = { + .bLength = sizeof(struct usb_desc_device), + .bDescriptorType = USB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = USB_DEV_CLASS_MISCELLANEOUS, + .bDeviceSubClass = USB_DEV_SUBCLASS_COMMON, + .bDeviceProtocol = USB_DEV_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR, + .bMaxPacketSize0 = 64, + .idVendor = VID, // VID, PID, DID defined by compiler flags depending on BOARD + .idProduct = PID, + .bcdDevice = DID, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 0, + .bNumConfigurations = 1, +}; + +usb_configuration_c usb_config = { + { + .bLength = sizeof(struct usb_desc_configuration), + .bDescriptorType = USB_DESC_CONFIGURATION, + .bNumInterfaces = UAC_NUM_INTERFACES, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = USB_ATTR_RESERVED_1, + .bMaxPower = 250, // 500mA + }, + { + UAC_DESCRIPTORS_LIST + { 0 } + } +}; + +usb_configuration_set_c usb_configs[] = { + &usb_config, +}; + +usb_descriptor_set_c usb_descriptor_set = { + .device = &usb_device, + .config_count = ARRAYSIZE(usb_configs), + .configs = usb_configs, + .string_count = ARRAYSIZE(usb_strings), + .strings = usb_strings, +}; diff --git a/examples/audio/main.c b/examples/audio/main.c new file mode 100644 index 0000000..5e136f5 --- /dev/null +++ b/examples/audio/main.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "uac.h" + +int main() { + // Run core at 48 MHz fCLK. + CPUCS = _CLKSPD1; + + // Configure descriptors + { + __xdata struct uac_configuration config = { + .if_num_ctrl = 0, // interface numbers start from 0 + .ep_addr_streaming = 2, // use EP2 for streaming interface + .i_str_channel_left = 3, + }; + uac_config(&config); + } + + // Configure UAC endpoint: 512-byte, double buffered, ISOCHRONOUS IN + SYNCDELAY; + EP2CFG = _VALID|_DIR|_TYPE0|_BUF1; + + // Re-enumerate, to make sure our descriptors are picked up correctly. + usb_init(/*disconnect=*/true); + + while (1) { + + } +} + +/*** Reimplemented libfx2 USB handlers ****************************************/ + +// USB setup commands +void handle_usb_setup(__xdata struct usb_req_setup *req) { + STALL_EP0(); // not handled +} + +// Set active interface _alternate setting_ +bool handle_usb_set_interface(uint8_t interface, uint8_t alt_setting) { + if (uac_handle_usb_set_interface(interface, alt_setting)) + return true; + return false; // not handled +} + +// Set current interface _alternate setting_ +void handle_usb_get_interface(uint8_t interface) { + if (uac_handle_usb_get_interface(interface)) + return; + STALL_EP0(); // not handled +} diff --git a/examples/common.mk b/examples/common.mk deleted file mode 100644 index ce7a082..0000000 --- a/examples/common.mk +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright (C) 2009-2012 Chris McClelland -# Copyright (C) 2015 Joel Stanley -# Copyright (C) 2017 Kyle Robbertze -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# - -# To build the firmware you will need: -# SDCC from http://sdcc.sourceforge.net -# Git from https://git-scm.com/ -# -# To load the firmware you will need: -# HDMI2USB-mode-swtich from https://github.com/timvideos/HDMI2USB-mode-switch -# -LIBS ?= $(FX2LIBDIR)/lib/fx2.lib -INCS += -I sdcc -I$(FX2LIBDIR)/include -I. -I../../common/boards - -USE_16K ?= 1 - -CC_OBJS ?= $(CC_SRCS:%.c=%.rel) - -CC = sdcc - -CFLAGS += -mmcs51 --xram-size 0x0200 $(FLAGS) -CFLAGS += -DBOARD_$(BOARD) - -ifeq ($(USE_16K),1) - CFLAGS += --code-size 0x3e00 -else - CFLAGS += --code-size 0x1e00 -endif - -# Use make V=1 for a verbose build. -ifndef V - Q_CC=@echo ' CC ' $@; - Q_AS=@echo ' AS ' $@; - Q_LINK=@echo ' LINK ' $@; - Q_RM=@echo ' CLEAN '; - Q_OBJCOPY=@echo ' OBJCOPY ' $@; - Q_GEN=@echo ' GEN ' $@; -endif - -.PHONY: all clean - -all: $(TARGET).hex - -$(CC_SRCS): $(FX2LIBDIR)/lib/fx2.lib - -$(FX2LIBDIR)/lib/fx2.lib: $(FX2LIBDIR)/.git - cd $(dir $@) && make -j1 - - -# We depend on a file inside the directory as git creates an -# empty dir for us. -# -# Note that although we have the variable FX2LIBDIR, the submodule -# magic will always check it out in fx2lib/ -$(FX2LIBDIR)/.git: $(GITMODULESDIR) - git submodule sync --recursive -- $$(dirname $@) - git submodule update --recursive --init $$(dirname $@) - touch $@ -r $< - -$(TARGET).hex: $(CC_OBJS) - $(Q_LINK)$(CC) $(CFLAGS) -o $@ $+ $(LIBS) - -%.rel: %.c - $(Q_CC)$(CC) $(CFLAGS) -c --disable-warning 85 $(INCS) $? - -clean: - $(Q_RM)$(RM) *.iic *.asm *.lnk *.lst *.map *.mem *.rel *.rst *.sym \ - *.lk serial.hex - cd $(FX2LIBDIR) && make clean - -distclean: clean - $(RM) -r $(FX2LIBDIR) - -load: $(TARGET).hex - hdmi2usb-mode-switch --load-fx2-firmware $(TARGET).hex diff --git a/examples/lights/Makefile b/examples/lights/Makefile deleted file mode 100644 index eb1a06a..0000000 --- a/examples/lights/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (C) 2009-2012 Chris McClelland -# Copyright (C) 2015 Joel Stanley -# Copyright (C) 2017 Kyle Robbertze -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# -# To build the firmware you will need: -# SDCC from http://sdcc.sourceforge.net -# fx2lib from http://fx2lib.wiki.sourceforge.net -# -TARGET := lights -FX2LIBDIR := ../../third_party/fx2lib -GITMODULESDIR := ../../.gitmodules -BOARD ?= fx2miniboard - -CC_SRCS := lights.c - -include ../common.mk diff --git a/examples/lights/README.md b/examples/lights/README.md deleted file mode 100644 index e157a73..0000000 --- a/examples/lights/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Lights Example -This example flashes the LEDs present on the FX2LP CY7C68013A mini board. It -can be used for testing loading of firmware onto these boards. The expected -pattern is D1 turning on, then D2 250ms later, then D1 off, then D2 off and the -cycle repeats - -The firmware is built using `make` and loaded using `make load`, which uses the -[HDMI2USB-mode-switch](https://github.com/timvideos/HDMI2USB-mode-switch) -utility to load the firmware onto the FX2 chip. - -![](../../docs/lights_example.gif) diff --git a/examples/lights/TODO b/examples/lights/TODO deleted file mode 100644 index f1c8035..0000000 --- a/examples/lights/TODO +++ /dev/null @@ -1 +0,0 @@ -Make this compatible with the Atlys and Opsis boards diff --git a/examples/lights/lights.c b/examples/lights/lights.c deleted file mode 100644 index c69f3da..0000000 --- a/examples/lights/lights.c +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (C) 2009 Ubixum, Inc. -// Copyright (C) 2016 Matthew Iselin -// Copyright (C) 2017 Kyle Robbertze -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** \file lights.c - * Example firmware that flashes LEDs. - * - * On the Atlys this is LD14 (DONE), on the FX2 miniboard D1 and D2 and on the - * Opsis it is D2 - */ - -#include -#include -#include - -#include "fx2lights.h" - -void init_lights(void) { - // Set pins to port mode instead of GPIF master/slave mode - IFCONFIG &= ~(bmIFCFGMASK); - // No alternate functions -#ifdef BOARD_fx2miniboard - PORTACFG = 0x00; -#endif // BOARD_fx2miniboard -#ifdef BOARD_opsis - PORTECFG = 0x00; -#endif // BOARD_opsis -} - -void main(void) { - BYTE n=0; - - init_lights(); - - while(TRUE) { - switch(n) { - case 0: - /** - * d1 is the LED labelled LD14 on the Atlys and the LED labelled - * D1 on the FX2LP CY7C68013A mini-board. It is not connected on - * the Opsis - */ - d1on(); - break; - case 1: - /** - * d2 is the LED labelled D2 on the Numato Opsis and the LED - * labelled D2 on the FX2LP CY7C68013A mini-board. It is not - * connected on the Atlys - */ - d2on(); - break; - case 2: - d1off(); - break; - default: - d2off(); - break; - } - delay(250); - n = (n + 1) % 4; - } -} diff --git a/examples/serial/Makefile b/examples/serial/Makefile deleted file mode 100644 index 11fc546..0000000 --- a/examples/serial/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2009-2012 Chris McClelland -# Copyright (C) 2015 Joel Stanley -# Copyright (C) 2017 Kyle Robbertze -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# - -# To build the firmware you will need: -# SDCC from http://sdcc.sourceforge.net -# fx2lib from http://fx2lib.wiki.sourceforge.net -# -TARGET := serial -FX2LIBDIR := ../../third_party/fx2lib -GITMODULESDIR := ../../.gitmodules -BOARD ?= fx2miniboard - -CC_SRCS := serial.c - -include ../common.mk diff --git a/examples/serial/README.md b/examples/serial/README.md deleted file mode 100644 index 8456a2b..0000000 --- a/examples/serial/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Serial Example - -This serial example is for testing serial connections from the FX2 chip. It is -uses the same setup as the HDMI2USB firmware, which is: - - * Baud rate of 115200 - * Serial device /dev/ttyUSB0 (default on linux) - * Connections - - RXD -> PD3 - - GND -> GND - -This example prints "This is the serial example for the HDMI2USB firmware" to -the TXD pin every two seconds - -To build the firmware run `make`, which will pull in the required dependencies -and build the `serial.hex` firmware image. This can be loaded using the -[HDMI2USB-mode-switch](https://github.com/timvideos/HDMI2USB-mode-switch) -utility, which is what `make load` uses. - -Under linux serial can be read using minicom. This example was tested using the -Digilent PmodUSBUART Serial to USB adaptor. - -FIXME: Add minicom example. - -FIXME: Only the Atlys and FX2 Dev board uses bit banging, the Opsis uses the -hardware serial. - -## Wiring Diagram - -FIXME: Use real pictures in the diagram. - -![](docs/serial_diagram.png) diff --git a/examples/serial/docs/serial_diagram.png b/examples/serial/docs/serial_diagram.png deleted file mode 100644 index f82d14e..0000000 Binary files a/examples/serial/docs/serial_diagram.png and /dev/null differ diff --git a/examples/serial/serial.c b/examples/serial/serial.c deleted file mode 100644 index b9d1a52..0000000 --- a/examples/serial/serial.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 Kyle Robbertze - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -#include -#include -#include -#include - -#define PD3 0xB3 -#define BAUD 32 // FIXME: Figure out why this is 32 - -__sbit __at PD3 USART; // USART slave send from port D3 - -void usart_init(void) { - SETCPUFREQ(CLK_48M); - USART = 1; - OED |= 0xff; // Set all pins' outputs enabled -} - -void usart_send_byte(BYTE c) { - (void)c; /* argument passed in DPL */ - __asm - mov a, dpl - mov r1, #9 // Move 9 into r1 for loop to execute 8 times (byte) - clr c - loop: - mov _USART, c // Move c into USART register - rrc a // Rotate accumulator 1 bit right - mov r0, #BAUD // Indicate ready to send - djnz r0, . // Wait for r0 to be cleared - nop - djnz r1, loop // Reduce r1 and start loop again - - setb _USART // Stop bit - mov r0, #BAUD // Indicate ready to send - djnz r0, . // Wait to be sent - __endasm; -} - -void usart_send_string(const char *s) { - while (*s) { - switch (*s) { - case '\r': // Send new line and carriage return so there is less - case '\n': // configuration of serial software needed. - usart_send_byte('\n'); - usart_send_byte('\r'); - break; - default: - usart_send_byte(*s); - } - *s++; - } -} - -void main(void) { - usart_init(); - while (1) { - usart_send_string("This is the serial example for the HDMI2USB firmware\n"); - delay(2000); - } -} diff --git a/third_party/fx2lib b/third_party/fx2lib deleted file mode 160000 index a5b0c2e..0000000 --- a/third_party/fx2lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a5b0c2e54482d5e9f1806b7790e43f7fb95e6653 diff --git a/third_party/fx2lib-linux-headers b/third_party/fx2lib-linux-headers deleted file mode 160000 index 01688ae..0000000 --- a/third_party/fx2lib-linux-headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 01688aee0390146008b8592515e8bfa13cb9f046 diff --git a/third_party/libfx2 b/third_party/libfx2 new file mode 160000 index 0000000..3adb4fc --- /dev/null +++ b/third_party/libfx2 @@ -0,0 +1 @@ +Subproject commit 3adb4fc842f174b0686ed122c0309d68356edc11