├── MIOS32_FBV ├── fbv │ ├── fbv_uart.o │ ├── fbv.mk │ ├── fbv_uart.h │ └── fbv_uart.c ├── usb_midi_2x2_FBV │ ├── .svn │ │ ├── props │ │ │ └── app.c.svn-work │ │ └── entries │ ├── axefx_info.c │ ├── midimon.h │ ├── app.h │ ├── mios32_config.h │ ├── axefx_info.h │ ├── Makefile │ ├── README.txt │ ├── midimon.c │ └── app.c └── .svn │ └── entries ├── documents ├── Protocol analysis FBX.xls ├── Protocol analysis FBX.numbers └── pinout FBV.rtf └── README /MIOS32_FBV/fbv/fbv_uart.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlotech/FBV-tools/HEAD/MIOS32_FBV/fbv/fbv_uart.o -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/.svn/props/app.c.svn-work: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /documents/Protocol analysis FBX.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlotech/FBV-tools/HEAD/documents/Protocol analysis FBX.xls -------------------------------------------------------------------------------- /documents/Protocol analysis FBX.numbers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlotech/FBV-tools/HEAD/documents/Protocol analysis FBX.numbers -------------------------------------------------------------------------------- /MIOS32_FBV/fbv/fbv.mk: -------------------------------------------------------------------------------- 1 | # defines additional rules for adding Line6 FBV support 2 | 3 | # enhance include path 4 | C_INCLUDE += -I $(MIOS32_FBV_PATH)/modules/fbv 5 | 6 | 7 | # add modules to thumb sources (TODO: provide makefile option to add code to ARM sources) 8 | THUMB_SOURCE += \ 9 | $(MIOS32_FBV_PATH)/modules/fbv/fbv_uart.c 10 | 11 | 12 | # directories and files that should be part of the distribution (release) package 13 | DIST += $(MIOS32_FBV_PATH)/modules/fbv 14 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/axefx_info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * axefx_info.c 3 | * 4 | * Created on: 20-mrt-2010 5 | * Author: vincent 6 | */ 7 | 8 | #include 9 | #include "axefx_info.h" 10 | 11 | 12 | const u8 axefx_request_blocks_sysex[] = {0xF0, 0x00, 0x00, 0x7D, 0x00, 0x0E, 0xF7}; 13 | const u32 axefx_request_blocks_length = 7; 14 | 15 | const u8 axefx_request_version_sysex[] = {0xF0, 0x00, 0x00, 0x7D, 0x00, 0x08, 0x00, 0x00, 0xF7}; 16 | const u32 axefx_request_version_length = 9; 17 | 18 | const u8 axefx_request_patch_name_sysex[] = {0xF0, 0x00, 0x00, 0x7D, 0x00, 0x0F, 0xF7}; 19 | const u32 axefx_request_patch_name_length = 7; 20 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 0 5 | svn://svnmios.midibox.org/mios32/trunk/apps/usb_midi_2x2_FBX 6 | svn://svnmios.midibox.org/mios32 7 | add 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | svn:special svn:externals svn:needs-lock 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 64d6c282-3004-4abb-abc2-16bea14f3ebd 28 | 29 | Makefile 30 | file 31 | 32 | 33 | 34 | add 35 | 36 | README.txt 37 | file 38 | 39 | 40 | 41 | add 42 | 43 | app.c 44 | file 45 | 46 | 47 | 48 | add 49 | 50 | 51 | 52 | 53 | 54 | has-props 55 | has-prop-mods 56 | 57 | app.h 58 | file 59 | 60 | 61 | 62 | add 63 | 64 | midimon.c 65 | file 66 | 67 | 68 | 69 | add 70 | 71 | midimon.h 72 | file 73 | 74 | 75 | 76 | add 77 | 78 | mios32_config.h 79 | file 80 | 81 | 82 | 83 | add 84 | 85 | -------------------------------------------------------------------------------- /MIOS32_FBV/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 762 5 | svn://svnmios.midibox.org/mios32/trunk/modules 6 | svn://svnmios.midibox.org/mios32 7 | 8 | 9 | 10 | 2009-10-25T22:10:11.420612Z 11 | 759 12 | tk 13 | 14 | 15 | svn:special svn:externals svn:needs-lock 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 64d6c282-3004-4abb-abc2-16bea14f3ebd 28 | 29 | aout 30 | dir 31 | 32 | app_lcd 33 | dir 34 | 35 | blm 36 | dir 37 | 38 | blm_x 39 | dir 40 | 41 | dmx 42 | dir 43 | 44 | dosfs 45 | dir 46 | 47 | eeprom 48 | dir 49 | 50 | fram 51 | dir 52 | 53 | freertos_utils 54 | dir 55 | 56 | glcd_font 57 | dir 58 | 59 | mbnet 60 | dir 61 | 62 | midifile 63 | dir 64 | 65 | minfs 66 | dir 67 | 68 | msd 69 | dir 70 | 71 | notestack 72 | dir 73 | 74 | random 75 | dir 76 | 77 | sequencer 78 | dir 79 | 80 | sid 81 | dir 82 | 83 | template 84 | dir 85 | 86 | uip 87 | dir 88 | 89 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/midimon.h: -------------------------------------------------------------------------------- 1 | // $Id: midimon.h 662 2009-07-25 22:40:36Z tk $ 2 | /* 3 | * Header file for MIDI monitor module 4 | * 5 | * ========================================================================== 6 | * 7 | * Copyright (C) 2009 Thorsten Klose (tk@midibox.org) 8 | * Licensed for personal non-commercial use only. 9 | * All other rights reserved. 10 | * 11 | * ========================================================================== 12 | */ 13 | 14 | #ifndef _MIDIMON_H 15 | #define _MIDIMON_H 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // Global definitions 20 | ///////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // Global Types 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | 28 | ///////////////////////////////////////////////////////////////////////////// 29 | // Prototypes 30 | ///////////////////////////////////////////////////////////////////////////// 31 | 32 | extern s32 MIDIMON_Init(u32 mode); 33 | extern s32 MIDIMON_Receive(mios32_midi_port_t port, mios32_midi_package_t package, u32 timestamp, u8 filter_sysex_message); 34 | 35 | 36 | ///////////////////////////////////////////////////////////////////////////// 37 | // Export global variables 38 | ///////////////////////////////////////////////////////////////////////////// 39 | 40 | 41 | #endif /* _MIDIMON_H */ 42 | -------------------------------------------------------------------------------- /documents/pinout FBV.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww20800\viewh16580\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 6 | 7 | \f0\fs24 \cf0 pin color signal\ 8 | 1 OrW GND\ 9 | 2 Or +VDD (+7.5V open)\ 10 | 3 GrW Rx-\ 11 | 4 Bl GND\ 12 | 5 BlW +VDD (+7.5V open)\ 13 | 6 Gr Rx+\ 14 | 7 BrW Tx-\ 15 | 8 Br Tx+\ 16 | \ 17 | Br => BrW = 33kOhm in FBV\ 18 | Br / BrW => OrW = 16.8 kOhm in FBV\ 19 | Gr / GrW => OrW = 16.8 kOhm in AMP\ 20 | \ 21 | OrW => Bl = 0 Ohm\ 22 | Or => BlW = 0 Ohm\ 23 | \ 24 | BrW - Br = ca. 5V in AMP\ 25 | \ 26 | \ 27 | Tx = From Amp to FBV\ 28 | Rx = To Amp From FBV\ 29 | \ 30 | Constant Tx word\ 31 | Length = 1.550 [ms] = approx 48 bits => 50 ? = 5 bytes incl start/stop\ 32 | \ 33 | 2nd word\ 34 | offset = 29.6 [ms]\ 35 | \ 36 | Pattern repeating on 350 [ms] ==> TAP TEMPO !!!\ 37 | 0xE2\ 38 | \ 39 | \ 40 | Smallest "bit" size = 32 [us] => 31.25 Kbit/s ?\ 41 | \ 42 | \ 43 | \ 44 | tap led AAN 0x90 0xF7 0x3D 0xFD 0x00\ 45 | tab led UIT 0x90 0xF7 0x3D 0xFF 0x00\ 46 | delay led AAN 0x90 0xF7 0x5D 0xFD 0x00\ 47 | delay led UIT 0x90 0xF7 0x5D 0xFF 0x00\ 48 | pitch led AAN 0x90 0xF7 0x9D 0xFD 0x00\ 49 | pitch led UIT 0x90 0xF7 0x9D 0xFF 0x00\ 50 | rev led AAN 0x90 0xF7 0xBD 0xFD 0x00 \ 51 | rev led UIT 0x90 0xF7 0xBD 0xFF 0x00\ 52 | amp2 led AAN 0x90 0xF7 0xDD 0xFD 0x00\ 53 | amp2 led UIT 0x90 0xF7 0xDD 0xFF 0x00\ 54 | amp1 led AAN 0x90 0xF7 0xFD 0xFD 0x00\ 55 | amp1 led UIT 0x90 0xF7 0xFD 0xFF 0x00\ 56 | \ 57 | \ 58 | \ 59 | \ 60 | tab button IN \ 61 | tab button UIT } -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/app.h: -------------------------------------------------------------------------------- 1 | // $Id: app.h 674 2009-07-29 19:54:48Z tk $ 2 | /* 3 | * Header file of application 4 | * 5 | * ========================================================================== 6 | * 7 | * Copyright (C) () 8 | * Licensed for personal non-commercial use only. 9 | * All other rights reserved. 10 | * 11 | * ========================================================================== 12 | */ 13 | 14 | #ifndef _APP_H 15 | #define _APP_H 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // Global definitions 20 | ///////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // Global Types 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | 28 | ///////////////////////////////////////////////////////////////////////////// 29 | // Prototypes 30 | ///////////////////////////////////////////////////////////////////////////// 31 | 32 | extern void APP_Init(void); 33 | extern void APP_Background(void); 34 | extern void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package); 35 | extern void APP_SRIO_ServicePrepare(void); 36 | extern void APP_SRIO_ServiceFinish(void); 37 | extern void APP_DIN_NotifyToggle(u32 pin, u32 pin_value); 38 | extern void APP_ENC_NotifyChange(u32 encoder, s32 incrementer); 39 | extern void APP_AIN_NotifyChange(u32 pin, u32 pin_value); 40 | 41 | 42 | ///////////////////////////////////////////////////////////////////////////// 43 | // Export global variables 44 | ///////////////////////////////////////////////////////////////////////////// 45 | 46 | 47 | #endif /* _APP_H */ 48 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/mios32_config.h: -------------------------------------------------------------------------------- 1 | // $Id: mios32_config.h 662 2009-07-25 22:40:36Z tk $ 2 | /* 3 | * Local MIOS32 configuration file 4 | * 5 | * this file allows to disable (or re-configure) default functions of MIOS32 6 | * available switches are listed in $MIOS32_PATH/modules/mios32/MIOS32_CONFIG.txt 7 | * 8 | */ 9 | 10 | #ifndef _MIOS32_CONFIG_H 11 | #define _MIOS32_CONFIG_H 12 | 13 | #define MIOS32_DONT_USE_SPI 14 | #define MIOS32_DONT_USE_SPI0 15 | #define MIOS32_DONT_USE_SPI1 16 | #define MIOS32_DONT_USE_SPI2 17 | #define MIOS32_DONT_USE_SRIO 18 | #define MIOS32_DONT_USE_DIN 19 | #define MIOS32_DONT_USE_DOUT 20 | #define MIOS32_DONT_USE_ENC 21 | #define MIOS32_DONT_USE_AIN 22 | #define MIOS32_DONT_USE_MF 23 | #define MIOS32_DONT_USE_LCD 24 | #define MIOS32_DONT_USE_OSC 25 | #define MIOS32_DONT_USE_IIC 26 | #define MIOS32_DONT_USE_IIC_MIDI 27 | #define MIOS32_DONT_USE_SDCARD 28 | #define MIOS32_DONT_USE_ENC28J60 29 | 30 | // Using the first 2 uarts based on the MIOS32 code the 3rd will be based on FBV code 31 | #define MIOS32_UART_NUM 2 32 | 33 | 34 | // The boot message which is print during startup and returned on a SysEx query 35 | #define MIOS32_LCD_BOOT_MSG_LINE1 "USB MIDI 2x2 + FBV" 36 | #define MIOS32_LCD_BOOT_MSG_LINE2 "(C) 2009 VLoTech" 37 | 38 | // define a unique VID/PID for this application 39 | #define MIOS32_USB_VENDOR_ID 0x16c0 // sponsored by voti.nl! see http://www.voti.nl/pids 40 | #define MIOS32_USB_VENDOR_STR "VLoTech.nl" // you will see this in the USB device description 41 | #define MIOS32_USB_PRODUCT_STR "USB MIDI 2x2 + FBV" // you will see this in the MIDI device list 42 | #define MIOS32_USB_PRODUCT_ID 1005 // 1000..1009 are free for lab use 43 | 44 | #define MIOS32_USB_MIDI_NUM_PORTS 2 // we provide 2 USB ports 45 | 46 | 47 | #endif /* _MIOS32_CONFIG_H */ 48 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/axefx_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * axefx_info.h 3 | * 4 | * Created on: 20-mrt-2010 5 | * Author: vincent 6 | */ 7 | 8 | #ifndef _AXEFX_INFO_H_ 9 | #define _AXEFX_INFO_H_ 10 | 11 | enum 12 | { 13 | ID_COMP1 = 100, 14 | ID_COMP2, 15 | ID_GRAPHEQ1, 16 | ID_GRAPHEQ2, 17 | ID_PARAEQ1, 18 | ID_PARAEQ2, 19 | ID_AMP1, 20 | ID_AMP2, 21 | ID_CAB1, 22 | ID_CAB2, 23 | ID_REVERB1, 24 | ID_REVERB2, 25 | ID_DELAY1, 26 | ID_DELAY2, 27 | ID_MULTITAP1, 28 | ID_MULTITAP2, 29 | ID_CHORUS1, 30 | ID_CHORUS2, 31 | ID_FLANGER1, 32 | ID_FLANGER2, 33 | ID_ROTARY1, 34 | ID_ROTARY2, 35 | ID_PHASER1, 36 | ID_PHASER2, 37 | ID_WAH1, 38 | ID_WAH2, 39 | ID_FORMANT1, 40 | ID_VOLUME1, 41 | ID_TREMOLO1, 42 | ID_TREMOLO2, 43 | ID_PITCH1, 44 | ID_FILTER1, 45 | ID_FILTER2, 46 | ID_DRIVE1, 47 | ID_DRIVE2, 48 | ID_ENHANCER1, 49 | ID_LOOP1, 50 | ID_MIXER1, 51 | ID_MIXER2, 52 | ID_NOISEGATE1, 53 | ID_OUT1, 54 | ID_CONTROL, 55 | ID_FBSEND, 56 | ID_FBRETURN, 57 | ID_SYNTH1, 58 | ID_SYNTH2, 59 | ID_VOCODER1, 60 | ID_MEGATAP1, 61 | ID_CROSSOVER1, 62 | ID_CROSSOVER2, 63 | ID_GATE1, 64 | ID_GATE2, 65 | ID_RINGMOD1, 66 | ID_PITCH2, 67 | ID_MULTICOMP1, 68 | ID_MULTICOMP2, 69 | ID_QUADCHORUS1, 70 | ID_QUADCHORUS2, 71 | ID_RESONATOR1, 72 | ID_RESONATOR2, 73 | ID_GRAPHEQ3, 74 | ID_GRAPHEQ4, 75 | ID_PARAEQ3, 76 | ID_PARAEQ4, 77 | ID_FILTER3, 78 | ID_FILTER4, 79 | ID_VOLUME2, 80 | ID_VOLUME3, 81 | ID_VOLUME4, 82 | }; 83 | 84 | extern const u8 axefx_request_blocks_sysex[]; 85 | extern const u32 axefx_request_blocks_length; 86 | 87 | extern const u8 axefx_request_version_sysex[]; 88 | extern const u32 axefx_request_version_length; 89 | 90 | extern const u8 axefx_request_patch_name_sysex[]; 91 | extern const u32 axefx_request_patch_name_length; 92 | 93 | typedef struct { 94 | u16 id; 95 | u16 cc; 96 | u8 status; 97 | } axefx_block_status_struct; 98 | 99 | 100 | #endif /* _AXEFX_INFO_H_ */ 101 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/Makefile: -------------------------------------------------------------------------------- 1 | # $Id: Makefile 662 2009-07-25 22:40:36Z tk $ 2 | 3 | ################################################################################ 4 | # following setup taken from environment variables 5 | ################################################################################ 6 | 7 | 8 | MIOS32_PATH=~/Workspace/MIOS32_base 9 | MIOS32_BIN_PATH=$MIOS32_PATH/bin 10 | 11 | MIOS32_FBV_PATH=~/Workspace/MIOS32_FBV 12 | 13 | 14 | MIOS32_GCC_PREFIX=arm-none-eabi 15 | MIOS32_FAMILY=STM32F10x 16 | MIOS32_PROCESSOR=STM32F103RE 17 | MIOS32_BOARD=MBHP_CORE_STM32 18 | MIOS32_LCD=clcd 19 | 20 | PROCESSOR = $(MIOS32_PROCESSOR) 21 | FAMILY = $(MIOS32_FAMILY) 22 | BOARD = $(MIOS32_BOARD) 23 | LCD = $(MIOS32_LCD) 24 | 25 | 26 | ################################################################################ 27 | # Source Files, include paths and libraries 28 | ################################################################################ 29 | 30 | THUMB_SOURCE = app.c \ 31 | midimon.c \ 32 | axefx_info.c 33 | 34 | # (following source stubs not relevant for Cortex M3 derivatives) 35 | THUMB_AS_SOURCE = 36 | ARM_SOURCE = 37 | ARM_AS_SOURCE = 38 | 39 | C_INCLUDE = -I . 40 | A_INCLUDE = -I . 41 | 42 | LIBS = 43 | 44 | 45 | ################################################################################ 46 | # Remaining variables 47 | ################################################################################ 48 | 49 | LD_FILE = $(MIOS32_PATH)/etc/ld/$(FAMILY)/$(PROCESSOR).ld 50 | PROJECT = project 51 | 52 | DEBUG = -g 53 | OPTIMIZE = -Os 54 | 55 | CFLAGS = $(DEBUG) $(OPTIMIZE) 56 | 57 | 58 | ################################################################################ 59 | # Include source modules via additional makefiles 60 | ################################################################################ 61 | 62 | # sources of programming model 63 | include $(MIOS32_PATH)/programming_models/traditional/programming_model.mk 64 | 65 | # FBX 66 | include $(MIOS32_FBV_PATH)/modules/fbv/fbv.mk 67 | 68 | # common make rules 69 | include $(MIOS32_PATH)/include/makefile/common.mk 70 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/README.txt: -------------------------------------------------------------------------------- 1 | $Id: README.txt 720 2009-09-13 11:22:27Z tk $ 2 | 3 | MIDI USB 2x2 Interface Driver 4 | =============================================================================== 5 | Copyright (C) 2009 Thorsten Klose (tk@midibox.org) 6 | Licensed for personal non-commercial use only. 7 | All other rights reserved. 8 | =============================================================================== 9 | 10 | Required tools: 11 | -> http://www.ucapps.de/mio32_c.html 12 | 13 | =============================================================================== 14 | 15 | Required hardware: 16 | o MBHP_CORE_STM32 17 | 18 | Optional hardware: 19 | o four LEDs connected to J5A.A0..A3 to display Tx/Rx status 20 | o four jumpers to select diagnosis options 21 | 22 | Note that LCD output for the MIDI monitor function is not supported! 23 | 24 | =============================================================================== 25 | 26 | This application acts as a simple 2x2 USB MIDI interface. 27 | 28 | Beside of the common usecase (communication with MIDI devices), it is intended 29 | as a test application for the two MIDI IN and OUT ports of the MBHP_CORE_STM32 30 | module. 31 | 32 | An integrated MIDI monitor is provided which sends incoming MIDI events to 33 | a MIOS terminal (part of MIOS Studio) in plain text format via the first 34 | USB port for diagnosis. 35 | 36 | This function can be activated by jumpering J5B.A4 to ground. 37 | 38 | By jumpering J5B.A5 to ground, Active Sense, MIDI Clock and MTC messages 39 | are filtered. 40 | 41 | By jumpering J5B.A6 to ground, the beat number and tempo (BPM) is displayed 42 | on each beat when a MIDI clock is received. 43 | 44 | By jumpering J5B.A7 to ground, the MIDI time code (MTC) is displayed 45 | in plain text format whenever all 8 MTC messages have been received. 46 | (NOT IMPLEMENTED YET) 47 | 48 | 49 | 4 LEDs can be connected to J5A.A0..A3 to display the receive/transmit 50 | status. The cathodes (short legs) have to be connected to Ground (J5A.Vs), 51 | and the anodes (long legs) via serial resistors (220 Ohm) to following 52 | J5A.Ax pins: 53 | 54 | J5A.A0: OUT1 Tx 55 | J5A.A1: OUT2 Tx 56 | J5A.A2: IN1 Rx 57 | J5A.A3: IN2 Rx 58 | 59 | The Status LED of the MBHP_CORE_STM32 module flickers on *each* 60 | incoming/outgoing MIDI event. 61 | 62 | =============================================================================== 63 | 64 | IMPORTANT: 65 | 66 | This application has it's own USB product ID (e.g. to give it an own name), 67 | so that the device has to be enumerated again after the code has been uploaded. 68 | 69 | Just reconnect the USB cable after code upload, so that your operating system 70 | searches for the new device. 71 | 72 | Thereafter (depending on the OS you are using) it could be required to 73 | re-start MIOS Studio, and to configure the MIDI I/O ports again before 74 | you are able display MIDI Monitor output on the MIOS Terminal. 75 | 76 | =============================================================================== 77 | 78 | SysEx messages received on MIDI IN1 or transmitted to MIDI OUT1 via USB 79 | are not displayed by the MIDI monitor to avoid data corruption (the SysEx 80 | stream would interfere with monitor messages) 81 | 82 | =============================================================================== 83 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ine6 FBV interface unit 2 | The line6 FBV is a very versatile floorboard to control an amplifier (rack) for guitarists. 3 | 4 | The downside of the FBV is only that it normally only works for Line6 Products. The FBV uses an own protocol and therefore cannot communicate direct with other equipment. 5 | 6 | The FBV interface unit translates the FBV own protocol to MIDI. Also with additional configuration it is also possible to use the LEDs and display for feedback to the guitarist. (showing which units are on, what channel is selected, tuner output). 7 | 8 | The devices it can communicate with are: 9 | 10 | Any MIDI based amplifier for channel select. (other amps can also be used, but modifications are needed). 11 | Any MIDI based effect unit 12 | TC Electronics G-force (bidirectional) 13 | Fractal Audio Axe-FX (Ultra) (bidirectional) which is the main focus for this unit. 14 | 15 | 16 | 17 | 18 | A demo video is made: YouTube 19 | 20 | All additional information can also be found on github.com/vlotech/FBV-tools.git 21 | 22 | The feature supported at this moment: 23 | 24 | 5 preset buttons + bank up + bank down 25 | 10 CC buttons 26 | 2 Foot controllers with button and led 27 | For the 10 CC buttons the state of specific blocks within the AxeFX is read out. 28 | led off = block not loaded 29 | led on = block loaded and active 30 | led blinking = block loaded but inactive 31 | (Semi-) hardcoded CC values + block to button mapping 32 | USB 2x2 MIDI interface (can be used for programming the AxeFX) 33 | Additional MIDI connection to USB 34 | Tuner info in display 35 | Tap tempo control 36 | - Tap tempo button doubles with (long hold) tuner control 37 | Preset name in display 38 | 39 | 40 | 41 | 42 | TODO: 43 | 44 | configurable via sysex (is already prepared in the software structure) 45 | configuration software to be made 46 | additional MIDI forwarding between MIDI connections (preferable under configuration) 47 | 48 | 49 | 50 | 51 | Optional functions: 52 | 53 | larger (extra) display + additional buttons can be added to the CPU board 54 | specific filtering of MIDI 55 | additional devices to control with specific commands 56 | extra analog inputs or outputs for control purposes 57 | extra relais contact for controlling external amps or FX loops 58 | patch panels, cabling, specific housing, etc. etc. 59 | you name it, I'll make it..... 60 | 61 | 62 | FAQ: 63 | 64 | Can it be used with FBV longboard, FVB short, FBV short MK2, etc. etc. ? 65 | - My own board is the FBV longboard used with a Vetta amp. The FBV short Mk2 will be tested soon. Any board usable on a Vetta will be supported. 66 | What kind of casing will be available? / How will it be delivered? 67 | - option 1) As small as possible. probably plastic black. 68 | - option 2) 19" housing (1 HE) with the option to solve other cabling / patching 69 | - option 3) as a bare PCB where you can install it yourself. 70 | Can I also integrate it in a floorboard, adding additional buttons / relays / leds etc.? 71 | - the PCB had additional pins and digital busses available to add any kind of extra interfaces. It can even be used to create your own controller. (without any Line6 floorboard). Please contact me for the possibilities... 72 | How is it all powered? 73 | - The PCB will need a 9V DC (@ 1A) power supplY (e.g. wall outlet adapter). This will also be used to power the FBV. 74 | - The development board does not support phantom power over MIDI, but also doesn't support single MIDI cable connection. The final board will support this. (resulting in a single 7-pin MIDI cable from the AxeFX where the adapter is connected to the AxeFX for phantom power. 75 | 76 | 77 | 78 | 79 | For more info please contact VLoTech. 80 | -------------------------------------------------------------------------------- /MIOS32_FBV/fbv/fbv_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for FBV UART functions 3 | */ 4 | 5 | #ifndef _FBV_UART_H 6 | #define _FBV_UART_H 7 | 8 | ///////////////////////////////////////////////////////////////////////////// 9 | // Global definitions 10 | ///////////////////////////////////////////////////////////////////////////// 11 | 12 | #if defined(MIOS32_BOARD_MBHP_CORE_STM32) 13 | 14 | 15 | // Tx buffer size (1..256) 16 | #ifndef FBV_UART_TX_BUFFER_SIZE 17 | #define FBV_UART_TX_BUFFER_SIZE 256 18 | #endif 19 | 20 | // Rx buffer size (1..256) 21 | #ifndef FBV_UART_RX_BUFFER_SIZE 22 | #define FBV_UART_RX_BUFFER_SIZE 256 23 | #endif 24 | 25 | // Baudrate of UART first interface 26 | #ifndef FBV_UART_BAUDRATE 27 | #define FBV_UART_BAUDRATE 31250 28 | #endif 29 | 30 | // should UART0 Tx pin configured for open drain (default) or push-pull mode? 31 | #ifndef FBV_UART_TX_OD // was 1 32 | #define FBV_UART_TX_OD 0 33 | #endif 34 | 35 | // Interface assignment: 0 = disabled, 1 = FBV, 2 = COM 36 | #ifndef FBV_UART_ASSIGNMENT 37 | #define FBV_UART_ASSIGNMENT 1 38 | #endif 39 | 40 | 41 | #define FBV_BUTTON_RELEASED 0x00 42 | #define FBV_BUTTON_PRESSED 0x01 43 | #define FBV_LED_OFF 0x00 44 | #define FBV_LED_ON 0x01 45 | 46 | #define FBV_CHANNEL_USER 'U' 47 | #define FBV_CHANNEL_FACTORY 'F' 48 | 49 | 50 | #define FBV_ID_TAP 0x61 51 | #define FBV_ID_DELAY 0x51 52 | #define FBV_ID_MODULATION 0x41 53 | #define FBV_ID_PITCH 0x31 54 | #define FBV_ID_REVERB 0x21 55 | #define FBV_ID_AMP2 0x11 56 | #define FBV_ID_AMP1 0x01 57 | #define FBV_ID_CHAN_FAV 0x60 58 | #define FBV_ID_CHAN_D 0x50 59 | #define FBV_ID_CHAN_C 0x40 60 | #define FBV_ID_CHAN_B 0x30 61 | #define FBV_ID_CHAN_A 0x20 62 | #define FBV_ID_BANK_UP 0x10 63 | #define FBV_ID_BANK_DOWN 0x00 64 | #define FBV_ID_STOMP3 0x32 65 | #define FBV_ID_STOMP2 0x22 66 | #define FBV_ID_STOMP1 0x12 67 | #define FBV_ID_FX_LOOP 0x02 68 | #define FBV_ID_FOOT_CTRL_V_LED 0x23 69 | #define FBV_ID_FOOT_CTRL_P2_LED 0x33 70 | #define FBV_ID_FOOT_CTRL_W_LED 0x03 71 | #define FBV_ID_FOOT_CTRL_P1_LED 0x13 72 | #define FBV_ID_FOOT_CTRL_V_BTN 0x53 73 | #define FBV_ID_FOOT_CTRL_W_BTN 0x43 74 | #define FBV_ID_FOOT_CTRL_V_VAL 0x01 75 | #define FBV_ID_FOOT_CTRL_W_VAL 0x00 76 | 77 | #define FBV_ID_NONE 0xFF 78 | 79 | 80 | 81 | ///////////////////////////////////////////////////////////////////////////// 82 | // Global Types 83 | ///////////////////////////////////////////////////////////////////////////// 84 | typedef struct { 85 | u8 header; 86 | u8 size; 87 | u8 cmd; 88 | u8 data[64]; 89 | u8 pos; 90 | } mios32_fbv_message_t; 91 | 92 | 93 | ///////////////////////////////////////////////////////////////////////////// 94 | // Prototypes 95 | ///////////////////////////////////////////////////////////////////////////// 96 | 97 | extern s32 FBV_UART_Init(u32 mode); 98 | 99 | extern s32 FBV_UART_RxBufferFree(void); 100 | extern s32 FBV_UART_RxBufferUsed(void); 101 | extern s32 FBV_UART_RxBufferGet(void); 102 | extern s32 FBV_UART_RxBufferPeek(void); 103 | extern s32 FBV_UART_RxBufferPut(u8 b); 104 | extern s32 FBV_UART_TxBufferFree(void); 105 | extern s32 FBV_UART_TxBufferUsed(void); 106 | extern s32 FBV_UART_TxBufferGet(void); 107 | extern s32 FBV_UART_TxBufferPut_NonBlocking(u8 b); 108 | extern s32 FBV_UART_TxBufferPut(u8 b); 109 | extern s32 FBV_UART_TxBufferPutMore_NonBlocking(u8 *buffer, u16 len); 110 | extern s32 FBV_UART_TxBufferPutMore(u8 *buffer, u16 len); 111 | 112 | extern s32 FBV_UART_RxBufferReceiveMessage(mios32_fbv_message_t *msg); 113 | 114 | extern s32 FBV_UART_TxBufferSendInit(void); 115 | extern s32 FBV_UART_TxBufferSendLedCommand(u8 led, u8 status); 116 | extern s32 FBV_UART_TxBufferSendChannelCommand(u8 group, u8 nr, u8 ch); 117 | extern s32 FBV_UART_TxBufferSendDisplay(u8 *buf, u8 len); 118 | 119 | extern s32 FBV_UART_TxBufferSendTuner(u8 note, u8 flat); 120 | 121 | 122 | ///////////////////////////////////////////////////////////////////////////// 123 | // Export global variables 124 | ///////////////////////////////////////////////////////////////////////////// 125 | 126 | #endif /* MIOS32_BOARD_MBHP_CORE_STM32 */ 127 | 128 | #endif /* _FBV_UART_H */ 129 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/midimon.c: -------------------------------------------------------------------------------- 1 | // $Id: midimon.c 674 2009-07-29 19:54:48Z tk $ 2 | /* 3 | * MIDI Monitor functions 4 | * 5 | * ========================================================================== 6 | * 7 | * Copyright (C) 2009 Thorsten Klose (tk@midibox.org) 8 | * Licensed for personal non-commercial use only. 9 | * All other rights reserved. 10 | * 11 | * ========================================================================== 12 | */ 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | // Include files 16 | ///////////////////////////////////////////////////////////////////////////// 17 | #include 18 | #include 19 | 20 | #include "midimon.h" 21 | 22 | 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // Local defines 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | // shortcut for printing a message on MIOS Terminal 28 | // could also be replaced by "printf" if source code used in a different environment 29 | #define MSG MIOS32_MIDI_SendDebugMessage 30 | 31 | 32 | // jumper options (all pin states are low-active, and will be inverted here) 33 | #define JUMPER_MIDIMON_ACTIVE (MIOS32_BOARD_J5_PinGet(4) ? 0 : 1) 34 | #define JUMPER_FILTER_ACTIVE (MIOS32_BOARD_J5_PinGet(5) ? 0 : 1) 35 | #define JUMPER_TEMPO_ACTIVE (MIOS32_BOARD_J5_PinGet(6) ? 0 : 1) 36 | #define JUMPER_MTC_ACTIVE (MIOS32_BOARD_J5_PinGet(7) ? 0 : 1) 37 | 38 | // to determine BPM 39 | #define NUM_TEMPO_SAMPLES (6+1) // to display BPM correctly after one 16th step 40 | 41 | #define NUM_TEMPO_PORTS 4 // for USB0/1 and UART0/1 separately 42 | 43 | ///////////////////////////////////////////////////////////////////////////// 44 | // Local structures 45 | ///////////////////////////////////////////////////////////////////////////// 46 | 47 | typedef union { 48 | struct { 49 | unsigned long long ALL:64; 50 | }; 51 | 52 | struct { 53 | u32 measure; 54 | u8 beat; 55 | u8 step; 56 | s8 subtick; 57 | }; 58 | } midi_clk_pos_t; 59 | 60 | 61 | typedef union { 62 | struct { 63 | unsigned long long ALL:64; 64 | }; 65 | 66 | struct { 67 | u8 type; 68 | u8 hours; 69 | u8 minutes; 70 | u8 seconds; 71 | u8 frames; 72 | }; 73 | } mtc_pos_t; 74 | 75 | 76 | ///////////////////////////////////////////////////////////////////////////// 77 | // Local variables 78 | ///////////////////////////////////////////////////////////////////////////// 79 | 80 | static const char note_name[12][3] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }; 81 | 82 | static midi_clk_pos_t midi_clk_pos[NUM_TEMPO_PORTS]; 83 | static u32 tempo_samples[NUM_TEMPO_PORTS][NUM_TEMPO_SAMPLES]; 84 | static u8 tempo_sample_pos[NUM_TEMPO_PORTS]; 85 | 86 | static mtc_pos_t mtc_pos[NUM_TEMPO_PORTS]; 87 | 88 | 89 | ///////////////////////////////////////////////////////////////////////////// 90 | // Initialize the monitor 91 | ///////////////////////////////////////////////////////////////////////////// 92 | s32 MIDIMON_Init(u32 mode) 93 | { 94 | int tempo_port_ix; 95 | int i; 96 | 97 | if( mode > 0 ) 98 | return -1; // only mode 0 supported yet 99 | 100 | for(tempo_port_ix=0; tempo_port_ix>1) & 0x7); break; 162 | default: 163 | MSG("%s MTC Invalid: %02X %02X %02X\n", pre_str, package.evnt0, package.evnt1, package.evnt2); 164 | } 165 | } 166 | msg_sent = 1; 167 | } else if( package.evnt0 == 0xf3 ) { 168 | MSG("%s Song Number #%d\n", pre_str, package.evnt1); 169 | msg_sent = 1; 170 | } 171 | break; 172 | 173 | case 0x3: // Three-byte System Common messages like SPP, etc. 174 | if( package.evnt0 == 0xf2 ) { 175 | u16 song_pos = package.evnt1 | (package.evnt2 >> 7); 176 | u8 step = song_pos % 4; 177 | u8 beat = (song_pos / 4) % 4; 178 | u32 measure = song_pos / 16; 179 | 180 | MSG("%s Song Position %d.%d.%d\n", pre_str, measure+1, beat+1, step+1); 181 | msg_sent = 1; 182 | 183 | if( tempo_port_ix >= 0 ) { 184 | midi_clk_pos_t *mcp = (midi_clk_pos_t *)&midi_clk_pos[tempo_port_ix]; 185 | 186 | mcp->subtick = -1; // ensure that next clock starts with 0 187 | mcp->step = step; 188 | mcp->beat = beat; 189 | mcp->measure = measure; 190 | } 191 | } 192 | break; 193 | 194 | case 0x4: // SysEx starts or continues (3 bytes) 195 | case 0x7: // SysEx ends with following three bytes 196 | if( !filter_sysex_message ) 197 | MSG("%s SysEx: %02X %02X %02X\n", pre_str, package.evnt0, package.evnt1, package.evnt2); 198 | msg_sent = 1; 199 | break; 200 | 201 | case 0x5: // Single-byte System Common Message or SysEx ends with following single bytes 202 | case 0xf: // Single Byte 203 | switch( package.evnt0 ) { 204 | case 0xf6: MSG("%s Tune Request (F6)\n", pre_str); break; 205 | case 0xf7: if( !filter_sysex_message ) { MSG("%s SysEx End (F7)\n", pre_str); } break; 206 | case 0xf8: 207 | if( !JUMPER_FILTER_ACTIVE ) { 208 | MSG("%s MIDI Clock (F8)\n", pre_str); 209 | } 210 | 211 | if( tempo_port_ix >= 0 ) { 212 | midi_clk_pos_t *mcp = (midi_clk_pos_t *)&midi_clk_pos[tempo_port_ix]; 213 | if( ++mcp->subtick >= 6 ) { 214 | mcp->subtick = 0; 215 | if( ++mcp->step >= 4 ) { 216 | mcp->step = 0; 217 | if( ++mcp->beat >= 4 ) { 218 | mcp->beat = 0; 219 | ++mcp->measure; 220 | } 221 | } 222 | } 223 | 224 | // for tempo measurements 225 | tempo_samples[tempo_port_ix][tempo_sample_pos[tempo_port_ix]] = timestamp; 226 | if( ++tempo_sample_pos[tempo_port_ix] >= NUM_TEMPO_SAMPLES ) 227 | tempo_sample_pos[tempo_port_ix] = 0; 228 | 229 | // will happen on -1 -> 0 (after FA has been received) and after common overrun 230 | if( mcp->subtick == 0 ) 231 | display_midi_clk = 1; 232 | } 233 | 234 | break; 235 | 236 | case 0xf9: MSG("%s MIDI Tick (F9)\n", pre_str); break; 237 | case 0xfa: 238 | MSG("%s MIDI Clock Start (FA)\n", pre_str); 239 | if( tempo_port_ix >= 0 ) { 240 | midi_clk_pos_t *mcp = (midi_clk_pos_t *)&midi_clk_pos[tempo_port_ix]; 241 | mcp->ALL = 0; 242 | mcp->subtick = -1; // ensure that next clock starts with 0 243 | } 244 | break; 245 | case 0xfb: MSG("%s MIDI Clock Continue (FB)\n", pre_str); break; 246 | case 0xfc: MSG("%s MIDI Clock Stop (FC)\n", pre_str); break; 247 | case 0xfd: MSG("%s Inspecified Realtime Event (FD)\n", pre_str); break; 248 | case 0xfe: if( !JUMPER_FILTER_ACTIVE ) { MSG("%s Active Sense (FE)\n", pre_str); } break; 249 | case 0xff: MSG("%s Reset (FF)\n", pre_str); break; 250 | default: 251 | if( package.type == 0xf ) 252 | MSG("%s Single-Byte Package: %02X\n", pre_str, package.evnt0); 253 | else 254 | MSG("%s Invalid SysEx Single-Byte Event (%02X)\n", pre_str, package.evnt0); 255 | } 256 | msg_sent = 1; 257 | break; 258 | 259 | case 0x6: // SysEx ends with following two bytes 260 | if( !filter_sysex_message ) 261 | MSG("%s SysEx: %02X %02X\n", pre_str, package.evnt0, package.evnt1); 262 | msg_sent = 1; 263 | break; 264 | 265 | case 0x8: // Note Off 266 | MSG("%s Chn%2d Note Off %s%d V:%3d\n", 267 | pre_str, (package.evnt0 & 0xf)+1, note_name[package.evnt1%12], (int)(package.evnt1/12)-2, package.evnt2); 268 | msg_sent = 1; 269 | break; 270 | 271 | case 0x9: // Note On 272 | MSG("%s Chn%2d Note On %s%d V:%3d\n", 273 | pre_str, (package.evnt0 & 0xf)+1, note_name[package.evnt1%12], (int)(package.evnt1/12)-2, package.evnt2); 274 | msg_sent = 1; 275 | break; 276 | 277 | case 0xa: // Poly Aftertouch 278 | MSG("%s Chn%2d Poly Aftertouch %s%d V:%3d\n", 279 | pre_str, (package.evnt0 & 0xf)+1, note_name[package.evnt1%12], (int)(package.evnt1/12)-2, package.evnt2); 280 | msg_sent = 1; 281 | break; 282 | 283 | case 0xb: // CC 284 | MSG("%s Chn%2d CC#%3d V:%3d\n", 285 | pre_str, (package.evnt0 & 0xf)+1, package.evnt1, package.evnt2); 286 | msg_sent = 1; 287 | break; 288 | 289 | case 0xc: // Program Change 290 | MSG("%s Chn%2d Program Change #%3d\n", 291 | pre_str, (package.evnt0 & 0xf)+1, package.evnt1); 292 | msg_sent = 1; 293 | break; 294 | 295 | case 0xd: // Channel Aftertouch 296 | MSG("%s Chn%2d Channel Aftertouch %s%d\n", 297 | pre_str, (package.evnt0 & 0xf)+1, note_name[package.evnt1%12], (int)(package.evnt1/12)-2); 298 | msg_sent = 1; 299 | break; 300 | } 301 | 302 | // unspecified or invalid packages 303 | if( !msg_sent ) { 304 | MSG("%s Invalid Package (Type %d: %02X %02X %02X)\n", 305 | pre_str, package.type, package.evnt0, package.evnt1, package.evnt2); 306 | } 307 | 308 | if( display_midi_clk && JUMPER_TEMPO_ACTIVE && tempo_port_ix >= 0 ) { 309 | midi_clk_pos_t *mcp = (midi_clk_pos_t *)&midi_clk_pos[tempo_port_ix]; 310 | 311 | // calculate tempo based on last samples 312 | // last samples have higher weight (FIT algorithm) 313 | int i; 314 | int valid = 1; 315 | 316 | int pos = tempo_sample_pos[tempo_port_ix]; 317 | u32 sample_timestamp = tempo_samples[tempo_port_ix][pos]; 318 | 319 | u32 filter_value = 0; 320 | int weight = 100; 321 | int divisor = 0; 322 | for(i=0; i<(NUM_TEMPO_SAMPLES-1); ++i) { 323 | if( ++pos >= NUM_TEMPO_SAMPLES ) 324 | pos = 0; 325 | 326 | u32 delta = tempo_samples[tempo_port_ix][pos] - sample_timestamp; 327 | #if 0 328 | MSG(">>>Delta %d: %u\n", i, delta); 329 | #endif 330 | 331 | // more than 1000 mS between two ticks would result into 2.5 BPM 332 | // we assume that measuring results are invalid! 333 | if( delta >= 1000 ) 334 | valid = 0; 335 | 336 | filter_value += weight * delta; 337 | divisor += weight; 338 | weight = (weight*100) / 110; // if divided by 100, we will get an unweighted mean value 339 | sample_timestamp = tempo_samples[tempo_port_ix][pos]; 340 | } 341 | 342 | if( !valid ) { 343 | MSG("%s MIDI Clock: %3d.%d.%d (???.? BPM)\n", 344 | pre_str, 345 | mcp->measure+1, mcp->beat+1, mcp->step+1); 346 | } else { 347 | float mean_value = (float)filter_value / (float)divisor; 348 | float bpm = 60.0 / ((mean_value/1000.0) * 24.0); 349 | 350 | // print MIDI Clock position and tempo 351 | MSG("%s MIDI Clock: %3d.%d.%d (%3d.%d BPM)\n", 352 | pre_str, 353 | mcp->measure+1, mcp->beat+1, mcp->step+1, 354 | (int)bpm, (int)(10.0*bpm) % 10); 355 | } 356 | } 357 | 358 | return 0; // no error 359 | } 360 | -------------------------------------------------------------------------------- /MIOS32_FBV/fbv/fbv_uart.c: -------------------------------------------------------------------------------- 1 | //! \defgroup FBV_UART 2 | //! 3 | //! FBV USART functions for MIOS32 4 | //! 5 | //! Applications shouldn't call these functions directly, instead please use \ref FBV layer functions 6 | //! 7 | //! \{ 8 | 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // Include files 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include 14 | 15 | #include "fbv_uart.h" 16 | 17 | #define DEBUG_VERBOSE_LEVEL 1 18 | #define DEBUG_MSG MIOS32_MIDI_SendDebugMessage 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | // Pin definitions and USART mappings 22 | ///////////////////////////////////////////////////////////////////////////// 23 | 24 | #define FBV_UART_TX_PORT GPIOA 25 | #define FBV_UART_TX_PIN GPIO_Pin_2 26 | #define FBV_UART_RX_PORT GPIOA 27 | #define FBV_UART_RX_PIN GPIO_Pin_3 28 | #define FBV_UART USART2 29 | #define FBV_UART_IRQ_CHANNEL USART2_IRQn 30 | #define FBV_UART_IRQHANDLER_FUNC void USART2_IRQHandler(void) 31 | #define FBV_UART_REMAP_FUNC {} 32 | 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | // Local variables 36 | ///////////////////////////////////////////////////////////////////////////// 37 | 38 | static u8 rx_buffer[FBV_UART_RX_BUFFER_SIZE]; 39 | static volatile u8 rx_buffer_tail; 40 | static volatile u8 rx_buffer_head; 41 | static volatile u8 rx_buffer_size; 42 | 43 | static u8 tx_buffer[FBV_UART_TX_BUFFER_SIZE]; 44 | static volatile u8 tx_buffer_tail; 45 | static volatile u8 tx_buffer_head; 46 | static volatile u8 tx_buffer_size; 47 | 48 | 49 | ///////////////////////////////////////////////////////////////////////////// 50 | //! Initializes UART interfaces 51 | //! \param[in] mode currently only mode 0 supported 52 | //! \return < 0 if initialisation failed 53 | //! \note Applications shouldn't call this function directly, instead please use \ref FBV 54 | ///////////////////////////////////////////////////////////////////////////// 55 | s32 FBV_UART_Init(u32 mode) 56 | { 57 | 58 | USART_DeInit(FBV_UART); 59 | 60 | GPIO_InitTypeDef GPIO_InitStructure; 61 | 62 | // currently only mode 0 supported 63 | if( mode != 0 ) 64 | return -1; // unsupported mode 65 | 66 | // map UART pins 67 | FBV_UART_REMAP_FUNC; 68 | 69 | // configure UART pins 70 | GPIO_StructInit(&GPIO_InitStructure); 71 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 72 | 73 | // outputs as open-drain 74 | GPIO_InitStructure.GPIO_Pin = FBV_UART_TX_PIN; 75 | #if FBV_UART_TX_OD 76 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 77 | #else 78 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 79 | #endif 80 | GPIO_Init(FBV_UART_TX_PORT, &GPIO_InitStructure); 81 | 82 | // inputs with internal pull-up 83 | //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 84 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 85 | GPIO_InitStructure.GPIO_Pin = FBV_UART_RX_PIN; 86 | GPIO_Init(FBV_UART_RX_PORT, &GPIO_InitStructure); 87 | 88 | // enable all USART clocks 89 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 90 | 91 | // USART configuration 92 | USART_InitTypeDef USART_InitStructure; 93 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 94 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 95 | USART_InitStructure.USART_Parity = USART_Parity_No; 96 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 97 | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 98 | 99 | USART_InitStructure.USART_BaudRate = FBV_UART_BAUDRATE; 100 | USART_Init(FBV_UART, &USART_InitStructure); 101 | 102 | // configure and enable UART interrupts 103 | NVIC_InitTypeDef NVIC_InitStructure; 104 | 105 | NVIC_InitStructure.NVIC_IRQChannel = FBV_UART_IRQ_CHANNEL; 106 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = MIOS32_IRQ_UART_PRIORITY; // defined in mios32_irq.h 107 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 108 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 109 | NVIC_Init(&NVIC_InitStructure); 110 | USART_ITConfig(FBV_UART, USART_IT_RXNE, ENABLE); 111 | //USART_ITConfig(FBV_UART, USART_IT_TXE, ENABLE); 112 | 113 | // clear buffer counters 114 | rx_buffer_tail = rx_buffer_head = rx_buffer_size = 0; 115 | tx_buffer_tail = tx_buffer_head = tx_buffer_size = 0; 116 | 117 | // enable UARTs 118 | USART_Cmd(FBV_UART, ENABLE); 119 | 120 | return 0; // no error 121 | } 122 | 123 | 124 | ///////////////////////////////////////////////////////////////////////////// 125 | //! returns number of free bytes in receive buffer 126 | //! \param[in] uart UART number (0..1) 127 | //! \return uart number of free bytes 128 | //! \return 1: uart available 129 | //! \return 0: uart not available 130 | ///////////////////////////////////////////////////////////////////////////// 131 | s32 FBV_UART_RxBufferFree(void) 132 | { 133 | return FBV_UART_RX_BUFFER_SIZE - rx_buffer_size; 134 | } 135 | 136 | 137 | ///////////////////////////////////////////////////////////////////////////// 138 | //! returns number of used bytes in receive buffer 139 | //! \param[in] uart UART number (0..1) 140 | //! \return > 0: number of used bytes 141 | //! \return 0 if uart not available 142 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 143 | ///////////////////////////////////////////////////////////////////////////// 144 | s32 FBV_UART_RxBufferUsed(void) 145 | { 146 | return rx_buffer_size; 147 | } 148 | 149 | 150 | ///////////////////////////////////////////////////////////////////////////// 151 | //! gets a byte from the receive buffer 152 | //! \return -1 if no new byte available 153 | //! \return >= 0: number of received bytes 154 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 155 | ///////////////////////////////////////////////////////////////////////////// 156 | s32 FBV_UART_RxBufferGet(void) 157 | { 158 | if( !rx_buffer_size ) 159 | return -1; // nothing new in buffer 160 | 161 | // get byte - this operation should be atomic! 162 | MIOS32_IRQ_Disable(); 163 | u8 b = rx_buffer[rx_buffer_tail]; 164 | if( ++rx_buffer_tail >= FBV_UART_RX_BUFFER_SIZE ) 165 | rx_buffer_tail = 0; 166 | --rx_buffer_size; 167 | MIOS32_IRQ_Enable(); 168 | 169 | return b; // return received byte 170 | } 171 | 172 | 173 | ///////////////////////////////////////////////////////////////////////////// 174 | //! returns the next byte of the receive buffer without taking it 175 | //! \return -1 if no new byte available 176 | //! \return >= 0: number of received bytes 177 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 178 | ///////////////////////////////////////////////////////////////////////////// 179 | s32 FBV_UART_RxBufferPeek(void) 180 | { 181 | if( !rx_buffer_size ) 182 | return -1; // nothing new in buffer 183 | 184 | // get byte - this operation should be atomic! 185 | MIOS32_IRQ_Disable(); 186 | u8 b = rx_buffer[rx_buffer_tail]; 187 | MIOS32_IRQ_Enable(); 188 | 189 | return b; // return received byte 190 | } 191 | 192 | 193 | ///////////////////////////////////////////////////////////////////////////// 194 | //! puts a byte onto the receive buffer 195 | //! \param[in] b byte which should be put into Rx buffer 196 | //! \return 0 if no error 197 | //! \return -1 if buffer full (retry) 198 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 199 | ///////////////////////////////////////////////////////////////////////////// 200 | s32 FBV_UART_RxBufferPut( u8 b) 201 | { 202 | 203 | if( rx_buffer_size >= FBV_UART_RX_BUFFER_SIZE ) 204 | return -1; // buffer full (retry) 205 | 206 | // copy received byte into receive buffer 207 | // this operation should be atomic! 208 | MIOS32_IRQ_Disable(); 209 | rx_buffer[rx_buffer_head] = b; 210 | if( ++rx_buffer_head >= FBV_UART_RX_BUFFER_SIZE ) 211 | rx_buffer_head = 0; 212 | ++rx_buffer_size; 213 | MIOS32_IRQ_Enable(); 214 | 215 | return 0; // no error 216 | } 217 | 218 | 219 | ///////////////////////////////////////////////////////////////////////////// 220 | //! returns number of free bytes in transmit buffer 221 | //! \return number of free bytes 222 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 223 | ///////////////////////////////////////////////////////////////////////////// 224 | s32 FBV_UART_TxBufferFree(void) 225 | { 226 | return FBV_UART_TX_BUFFER_SIZE - tx_buffer_size; 227 | } 228 | 229 | 230 | ///////////////////////////////////////////////////////////////////////////// 231 | //! returns number of used bytes in transmit buffer 232 | //! \return number of used bytes 233 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 234 | ///////////////////////////////////////////////////////////////////////////// 235 | s32 FBV_UART_TxBufferUsed(void) 236 | { 237 | return tx_buffer_size; 238 | } 239 | 240 | 241 | ///////////////////////////////////////////////////////////////////////////// 242 | //! gets a byte from the transmit buffer 243 | //! \return -1 if no new byte available 244 | //! \return >= 0: transmitted byte 245 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 246 | ///////////////////////////////////////////////////////////////////////////// 247 | s32 FBV_UART_TxBufferGet(void) 248 | { 249 | 250 | if( !tx_buffer_size ) 251 | return -1; // nothing new in buffer 252 | 253 | // get byte - this operation should be atomic! 254 | MIOS32_IRQ_Disable(); 255 | u8 b = tx_buffer[tx_buffer_tail]; 256 | if( ++tx_buffer_tail >= FBV_UART_TX_BUFFER_SIZE ) 257 | tx_buffer_tail = 0; 258 | --tx_buffer_size; 259 | MIOS32_IRQ_Enable(); 260 | 261 | return b; // return transmitted byte 262 | } 263 | 264 | 265 | ///////////////////////////////////////////////////////////////////////////// 266 | //! puts more than one byte onto the transmit buffer (used for atomic sends) 267 | //! \param[in] *buffer pointer to buffer to be sent 268 | //! \param[in] len number of bytes to be sent 269 | //! \return 0 if no error 270 | //! \return -1 if buffer full or cannot get all requested bytes (retry) 271 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 272 | ///////////////////////////////////////////////////////////////////////////// 273 | s32 FBV_UART_TxBufferPutMore_NonBlocking( u8 *buffer, u16 len) 274 | { 275 | 276 | if( (tx_buffer_size+len) >= FBV_UART_TX_BUFFER_SIZE ) 277 | return -1; // buffer full or cannot get all requested bytes (retry) 278 | 279 | // copy bytes to be transmitted into transmit buffer 280 | // this operation should be atomic! 281 | MIOS32_IRQ_Disable(); 282 | 283 | u16 i; 284 | for(i=0; i= FBV_UART_TX_BUFFER_SIZE ) 288 | tx_buffer_head = 0; 289 | 290 | // enable Tx interrupt if buffer was empty 291 | if( ++tx_buffer_size == 1 ) { 292 | FBV_UART->CR1 |= (1 << 7); // enable TXE interrupt (TXEIE=1) 293 | } 294 | } 295 | 296 | MIOS32_IRQ_Enable(); 297 | 298 | return 0; // no error 299 | } 300 | 301 | ///////////////////////////////////////////////////////////////////////////// 302 | //! puts more than one byte onto the transmit buffer (used for atomic sends)
303 | //! (blocking function) 304 | //! \param[in] *buffer pointer to buffer to be sent 305 | //! \param[in] len number of bytes to be sent 306 | //! \return 0 if no error 307 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 308 | ///////////////////////////////////////////////////////////////////////////// 309 | s32 FBV_UART_TxBufferPutMore(u8 *buffer, u16 len) 310 | { 311 | s32 error; 312 | 313 | while( (error=FBV_UART_TxBufferPutMore_NonBlocking(buffer, len)) == -1 ); 314 | 315 | return error; 316 | } 317 | 318 | 319 | ///////////////////////////////////////////////////////////////////////////// 320 | //! puts a byte onto the transmit buffer 321 | //! \param[in] b byte which should be put into Tx buffer 322 | //! \return 0 if no error 323 | //! \return -1 if buffer full (retry) 324 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 325 | ///////////////////////////////////////////////////////////////////////////// 326 | s32 FBV_UART_TxBufferPut_NonBlocking(u8 b) 327 | { 328 | // for more comfortable usage... 329 | // -> just forward to FBV_UART_TxBufferPutMore 330 | return FBV_UART_TxBufferPutMore_NonBlocking(&b, 1); 331 | } 332 | 333 | 334 | ///////////////////////////////////////////////////////////////////////////// 335 | //! puts a byte onto the transmit buffer
336 | //! (blocking function) 337 | //! \param[in] b byte which should be put into Tx buffer 338 | //! \return 0 if no error 339 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 340 | ///////////////////////////////////////////////////////////////////////////// 341 | s32 FBV_UART_TxBufferPut(u8 b) 342 | { 343 | s32 error; 344 | 345 | while( (error=FBV_UART_TxBufferPutMore(&b, 1)) == -1 ); 346 | 347 | return error; 348 | } 349 | 350 | 351 | ///////////////////////////////////////////////////////////////////////////// 352 | //! returns the size of the next message in the receive buffer without taking it 353 | //! \return -1 if no new byte available 354 | //! \return 0 if no new message available 355 | //! \return > 0: size of received message 356 | //! \note Applications shouldn't call these functions directly, instead please use \ref FBV 357 | ///////////////////////////////////////////////////////////////////////////// 358 | s32 FBV_UART_RxBufferReceiveMessage(mios32_fbv_message_t *target) 359 | { 360 | if( !rx_buffer_size ) 361 | return -1; // nothing new in buffer 362 | 363 | static mios32_fbv_message_t msg = {0}; 364 | 365 | s32 status = 0; 366 | s32 retval = -1; 367 | u8 b = 0x00; 368 | 369 | if((status = FBV_UART_RxBufferGet()) >= 0) { 370 | b = (u8)status; 371 | 372 | //DEBUG_MSG("input: %02X\n", (u8)b); 373 | 374 | 375 | if(b == 0xF0) { 376 | bzero(&msg,sizeof(mios32_fbv_message_t)); 377 | } 378 | 379 | if( msg.header != 0xF0) { 380 | if( b == 0xF0) { 381 | msg.header = b; 382 | } 383 | } else if (msg.size == 0) { 384 | msg.size = b; 385 | if(msg.size == (msg.pos + 0)) 386 | retval = 0; 387 | } else if (msg.cmd == 0) { 388 | msg.cmd = b; 389 | if(msg.size == (msg.pos + 1)) 390 | retval = 0; 391 | } else { 392 | msg.data[msg.pos++] = (u8)status; 393 | if(msg.size == (msg.pos + 1)) 394 | retval = 0; 395 | } 396 | 397 | } 398 | 399 | if(retval == 0) { 400 | memcpy(target,&msg,sizeof(mios32_fbv_message_t)); 401 | // bzero(&msg,sizeof(mios32_fbv_message_t)) 402 | DEBUG_MSG("\n\nFBV Message DONE\n\n"); 403 | } 404 | return retval; // return received byte 405 | } 406 | 407 | s32 FBV_UART_TxBufferSendInit(void) 408 | { 409 | FBV_UART_TxBufferPut(0xF0); //header 410 | FBV_UART_TxBufferPut(0x02); //size 411 | FBV_UART_TxBufferPut(0x01); // version cmd?!? 412 | FBV_UART_TxBufferPut(0x00); // version 0?!? 413 | 414 | return 0; 415 | } 416 | 417 | 418 | s32 FBV_UART_TxBufferSendLedCommand(u8 led, u8 status) 419 | { 420 | u8 led_inner = led; 421 | if( led == FBV_ID_FOOT_CTRL_W_BTN) led_inner = FBV_ID_FOOT_CTRL_P1_LED; 422 | if( led == FBV_ID_FOOT_CTRL_V_BTN) led_inner = FBV_ID_FOOT_CTRL_V_LED; 423 | 424 | FBV_UART_TxBufferPut(0xF0); //header 425 | FBV_UART_TxBufferPut(0x03); //size 426 | FBV_UART_TxBufferPut(0x04); // Led command 427 | FBV_UART_TxBufferPut(led_inner); // led ID 428 | FBV_UART_TxBufferPut(status); // led state 429 | 430 | return 0; 431 | } 432 | 433 | s32 FBV_UART_TxBufferSendChannelCommand(u8 group, u8 nr, u8 ch) 434 | { 435 | FBV_UART_TxBufferPut(0xF0); //header 436 | FBV_UART_TxBufferPut(0x05); //size 437 | FBV_UART_TxBufferPut(0x08); // Channel command 438 | FBV_UART_TxBufferPut(group); // group (F/U) 439 | FBV_UART_TxBufferPut(0x20); // 'space' 440 | FBV_UART_TxBufferPut(nr); // Channel number 441 | FBV_UART_TxBufferPut(ch); // Channel char 442 | FBV_UART_TxBufferPut(0xF0); //header 443 | FBV_UART_TxBufferPut(0x02); //size 444 | FBV_UART_TxBufferPut(0x20); // Channel command 445 | FBV_UART_TxBufferPut(0x00); // 0 = off, 1 = on 446 | 447 | return 0; 448 | } 449 | 450 | s32 FBV_UART_TxBufferSendDisplay(u8 *buf, u8 len) 451 | { 452 | FBV_UART_TxBufferPut(0xF0); //header 453 | FBV_UART_TxBufferPut(0x13); //size 454 | FBV_UART_TxBufferPut(0x10); // Channel command 455 | FBV_UART_TxBufferPut(0x00); // ??? 456 | FBV_UART_TxBufferPut(0x10); // ??? 457 | int i; 458 | for(i=0; i < len && i < 16; i++) 459 | FBV_UART_TxBufferPut(buf[i]); // chars 460 | for(i=0; i < 16; i++) 461 | FBV_UART_TxBufferPut(0x20); // 'space' 462 | return 0; 463 | } 464 | 465 | s32 FBV_UART_TxBufferSendTuner(u8 note, u8 flat) 466 | { 467 | FBV_UART_TxBufferPut(0xF0); //header 468 | FBV_UART_TxBufferPut(0x05); //size 469 | FBV_UART_TxBufferPut(0x08); // Channel command 470 | FBV_UART_TxBufferPut(0x20); // group (F/U) 471 | FBV_UART_TxBufferPut(0x20); // 'space' 472 | FBV_UART_TxBufferPut(0x20); // Channel number 473 | FBV_UART_TxBufferPut(0x20); // Channel char 474 | FBV_UART_TxBufferPut(0xF0); //header 475 | FBV_UART_TxBufferPut(0x02); //size 476 | FBV_UART_TxBufferPut(0x0C); // note 477 | FBV_UART_TxBufferPut(note); // ASCII 478 | FBV_UART_TxBufferPut(0xF0); //header 479 | FBV_UART_TxBufferPut(0x02); //size 480 | FBV_UART_TxBufferPut(0x20); // Channel command 481 | FBV_UART_TxBufferPut(flat); // 0 = off, 1 = on 482 | return 0; 483 | } 484 | 485 | ///////////////////////////////////////////////////////////////////////////// 486 | // Interrupt handler for fbv UART 487 | ///////////////////////////////////////////////////////////////////////////// 488 | FBV_UART_IRQHANDLER_FUNC 489 | { 490 | if( FBV_UART->SR & (1 << 5) ) { // check if RXNE flag is set 491 | u8 b = FBV_UART->DR; 492 | 493 | //s32 status = MIOS32_MIDI_SendByteToRxCallback(UART0, b); 494 | 495 | //if( status == 0 && FBV_UART_RxBufferPut(0, b) < 0 ) { 496 | if( FBV_UART_RxBufferPut( b) < 0 ) { 497 | 498 | // here we could add some error handling 499 | //DEBUG_MSG("errin:\n"); 500 | } else { 501 | //DEBUG_MSG("input: %02X\n", (u8)b); 502 | } 503 | 504 | } 505 | 506 | if( FBV_UART->SR & (1 << 7) ) { // check if TXE flag is set 507 | if( FBV_UART_TxBufferUsed() > 0 ) { 508 | s32 b = FBV_UART_TxBufferGet(); 509 | 510 | if( b < 0 ) { 511 | // here we could add some error handling 512 | FBV_UART->DR = 0xff; 513 | //DEBUG_MSG("errout: %02X\n", (u8)b); 514 | } else { 515 | FBV_UART->DR = (u8)b; 516 | //DEBUG_MSG("output: %02X\n", (u8)b); 517 | } 518 | } else { 519 | FBV_UART->CR1 &= ~(1 << 7); // disable TXE interrupt (TXEIE=0) 520 | } 521 | } 522 | } 523 | 524 | 525 | -------------------------------------------------------------------------------- /MIOS32_FBV/usb_midi_2x2_FBV/app.c: -------------------------------------------------------------------------------- 1 | // $Id: app.c 722 2009-09-13 11:25:43Z tk $ 2 | /* 3 | * MIDI USB 2x2 Interface Driver 4 | * 5 | * ========================================================================== 6 | * 7 | * Copyright (C) 2009 Thorsten Klose (tk@midibox.org) 8 | * Licensed for personal non-commercial use only. 9 | * All other rights reserved. 10 | * 11 | * ========================================================================== 12 | */ 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | // Include files 16 | ///////////////////////////////////////////////////////////////////////////// 17 | 18 | #include 19 | 20 | #include "app.h" 21 | #include "axefx_info.h" 22 | 23 | #include "fbv_uart.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | // for optional debugging messages via MIDI 32 | // should be enabled for this application! 33 | ///////////////////////////////////////////////////////////////////////////// 34 | #define DEBUG_VERBOSE_LEVEL 1 35 | #define DEBUG_MSG MIOS32_MIDI_SendDebugMessage 36 | 37 | #define RACK_MIDI_CHN Chn1 38 | 39 | #define AXEFX_PORT UART1 40 | 41 | ///////////////////////////////////////////////////////////////////////////// 42 | // Local defines 43 | ///////////////////////////////////////////////////////////////////////////// 44 | #define PRIORITY_TASK_FBV_CHECK ( tskIDLE_PRIORITY + 2 ) 45 | 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | // AxeFX SysEx stuff 49 | ///////////////////////////////////////////////////////////////////////////// 50 | #define SYSEX_HEADER 0 51 | #define SYSEX_CMD_STATE_BEGIN 1 52 | #define SYSEX_CMD_STATE_CONT 2 53 | #define SYSEX_CMD_STATE_END 3 54 | #define SYSEX_MAX_LEN 256 55 | 56 | static u8 sysex_state = SYSEX_HEADER; 57 | static u8 sysex_count = 0; 58 | static u8 sysex_axefx_type = 0; 59 | static u8 sysex_cmd; 60 | 61 | 62 | const u8 sysex_header[5] = { 0xf0, 0x00, 0x00, 0x7d, 0x01 }; 63 | u8 sysex_buffer[SYSEX_MAX_LEN]; 64 | 65 | 66 | ///////////////////////////////////////////////////////////////////////////// 67 | // Local variables 68 | ///////////////////////////////////////////////////////////////////////////// 69 | 70 | static u32 ms_counter; 71 | 72 | static u8 midi_channel = 0x01; 73 | static u8 midi_bank_size = 0x04; 74 | static u8 midi_bank = 0x00; 75 | static const u8 bank_ids[10] = {FBV_ID_CHAN_A, FBV_ID_CHAN_B, FBV_ID_CHAN_C, FBV_ID_CHAN_D, FBV_ID_CHAN_FAV, 76 | FBV_ID_REVERB, FBV_ID_PITCH, FBV_ID_MODULATION, FBV_ID_DELAY, FBV_ID_TAP}; 77 | enum { 78 | FBV_ID_TYPE_BTN_LED, 79 | FBV_ID_TYPE_BTN_ONLY, 80 | FBV_ID_TYPE_LED_ONLY, 81 | FBV_ID_TYPE_FOOT_CTRL, 82 | FBV_ID_TYPE_TEMPO, 83 | FBV_ID_TYPE_BANK, // cc = direction 0 = down, 1 = up 84 | FBV_ID_TYPE_PRESET, // cc = offset on preset 85 | FBV_ID_TYPE_TEMPO_TUNER, 86 | FBV_ID_TYPE_NONE 87 | }; 88 | 89 | enum { 90 | FBV_ID_TAP_i, 91 | FBV_ID_DELAY_i, 92 | FBV_ID_MODULATION_i, 93 | FBV_ID_PITCH_i, 94 | FBV_ID_REVERB_i, 95 | FBV_ID_AMP2_i, 96 | FBV_ID_AMP1_i, 97 | FBV_ID_CHAN_FAV_i, 98 | FBV_ID_CHAN_D_i, 99 | FBV_ID_CHAN_C_i, 100 | FBV_ID_CHAN_B_i, 101 | FBV_ID_CHAN_A_i, 102 | FBV_ID_BANK_UP_i, 103 | FBV_ID_BANK_DOWN_i, 104 | FBV_ID_STOMP3_i, 105 | FBV_ID_STOMP2_i, 106 | FBV_ID_STOMP1_i, 107 | FBV_ID_FX_LOOP_i, 108 | // FBV_ID_FOOT_CTRL_V_LED_i, //in lower layers the led is translated to the button 109 | // FBV_ID_FOOT_CTRL_P2_LED_i, // not in use!! 110 | // FBV_ID_FOOT_CTRL_W_LED_i, //in lower layers the led is translated to the button 111 | // FBV_ID_FOOT_CTRL_P1_LED_i, // not in use!! 112 | FBV_ID_FOOT_CTRL_V_BTN_i, 113 | FBV_ID_FOOT_CTRL_W_BTN_i, 114 | FBV_ID_MAX_INDEX 115 | }; 116 | 117 | enum { 118 | FBV_ID_FOOT_CTRL_V_VAL_i, 119 | FBV_ID_FOOT_CTRL_W_VAL_i 120 | }; 121 | 122 | enum { 123 | FBV_ID_OFF, 124 | FBV_ID_ON, 125 | }; 126 | 127 | #define FBV_ID_MAX_BLOCKS 8 128 | 129 | typedef struct { 130 | u8 fbv_id; 131 | u8 type; 132 | u8 cc; 133 | u8 status; 134 | u8 len; 135 | axefx_block_status_struct blocks[FBV_ID_MAX_BLOCKS]; 136 | } fbv_ctrl_t; 137 | 138 | typedef struct { 139 | u8 fbv_id_foot; 140 | u8 fbv_id_btn; 141 | u8 fbv_id_led1; 142 | u8 fbv_id_led2; 143 | u8 cc; 144 | u8 cc_value1; 145 | u8 cc_value2; 146 | u8 status; 147 | u8 len; 148 | axefx_block_status_struct blocks[FBV_ID_MAX_BLOCKS]; 149 | } fbv_footctrl_t; 150 | 151 | #define FBV_ID_MAX_FOOT_INDEX 2 152 | 153 | fbv_ctrl_t FBV_ctrls[FBV_ID_MAX_INDEX] = {}; 154 | fbv_footctrl_t FBV_ctrls_cont[FBV_ID_MAX_FOOT_INDEX] = {}; 155 | 156 | 157 | 158 | 159 | static const u8 block_to_id[] = { 160 | FBV_ID_FX_LOOP_i,// ID_COMP1 = 100, 161 | FBV_ID_NONE,// ID_COMP2, 162 | FBV_ID_NONE,// ID_GRAPHEQ1, 163 | FBV_ID_NONE,// ID_GRAPHEQ2, 164 | FBV_ID_NONE,// ID_PARAEQ1, 165 | FBV_ID_NONE,// ID_PARAEQ2, 166 | FBV_ID_NONE,// ID_AMP1, 167 | FBV_ID_NONE,// ID_AMP2, 168 | FBV_ID_NONE,// ID_CAB1, 169 | FBV_ID_NONE,// ID_CAB2, 170 | FBV_ID_REVERB_i,// ID_REVERB1, 171 | FBV_ID_NONE,// ID_REVERB2, 172 | FBV_ID_DELAY_i, // ID_DELAY1, 173 | FBV_ID_NONE, // ID_DELAY2, 174 | FBV_ID_NONE, // ID_MULTITAP1, 175 | FBV_ID_NONE, // ID_MULTITAP2, 176 | FBV_ID_STOMP2_i,// ID_CHORUS1, 177 | FBV_ID_NONE,// ID_CHORUS2, 178 | FBV_ID_STOMP1_i,// ID_FLANGER1, 179 | FBV_ID_NONE,// ID_FLANGER2, 180 | FBV_ID_MODULATION_i,// ID_ROTARY1, 181 | FBV_ID_NONE,// ID_ROTARY2, 182 | FBV_ID_AMP1_i,// ID_PHASER1, 183 | FBV_ID_NONE,// ID_PHASER2, 184 | FBV_ID_FOOT_CTRL_W_BTN_i,// ID_WAH1, 185 | FBV_ID_NONE,// ID_WAH2, 186 | FBV_ID_NONE,// ID_FORMANT1, 187 | FBV_ID_FOOT_CTRL_V_BTN_i,// ID_VOLUME1, 188 | FBV_ID_PITCH_i,// ID_TREMOLO1, 189 | FBV_ID_NONE,// ID_TREMOLO2, 190 | FBV_ID_AMP2_i,// ID_PITCH1, 191 | FBV_ID_CHAN_FAV_i,// ID_FILTER1, 192 | FBV_ID_NONE,// ID_FILTER2, 193 | FBV_ID_STOMP3_i,// ID_DRIVE1, 194 | FBV_ID_NONE,// ID_DRIVE2, 195 | FBV_ID_NONE,// ID_ENHANCER1, 196 | FBV_ID_NONE,// ID_LOOP1, 197 | FBV_ID_NONE,// ID_MIXER1, 198 | FBV_ID_NONE,// ID_MIXER2, 199 | FBV_ID_NONE,// ID_NOISEGATE1, 200 | FBV_ID_NONE,// ID_OUT1, 201 | FBV_ID_NONE,// ID_CONTROL, 202 | FBV_ID_NONE,// ID_FBSEND, 203 | FBV_ID_NONE,// ID_FBRETURN, 204 | FBV_ID_NONE,// ID_SYNTH1, 205 | FBV_ID_NONE,// ID_SYNTH2, 206 | FBV_ID_NONE,// ID_VOCODER1, 207 | FBV_ID_NONE, // ID_MEGATAP1, 208 | FBV_ID_NONE,// ID_CROSSOVER1, 209 | FBV_ID_NONE,// ID_CROSSOVER2, 210 | FBV_ID_NONE,// ID_GATE1, 211 | FBV_ID_NONE,// ID_GATE2, 212 | FBV_ID_NONE,// ID_RINGMOD1, 213 | FBV_ID_NONE,// ID_PITCH2, 214 | FBV_ID_NONE,// ID_MULTICOMP1, 215 | FBV_ID_NONE,// ID_MULTICOMP2, 216 | FBV_ID_NONE,// ID_QUADCHORUS1, 217 | FBV_ID_NONE,// ID_QUADCHORUS2, 218 | FBV_ID_NONE,// ID_RESONATOR1, 219 | FBV_ID_NONE,// ID_RESONATOR2, 220 | FBV_ID_NONE,// ID_GRAPHEQ3, 221 | FBV_ID_NONE,// ID_GRAPHEQ4, 222 | FBV_ID_NONE,// ID_PARAEQ3, 223 | FBV_ID_NONE,// ID_PARAEQ4, 224 | FBV_ID_NONE,// ID_FILTER3, 225 | FBV_ID_NONE,// ID_FILTER4, 226 | FBV_ID_NONE,// ID_VOLUME2, 227 | FBV_ID_NONE,// ID_VOLUME3, 228 | FBV_ID_NONE,// ID_VOLUME4, 229 | }; 230 | 231 | void do_init_info(void) { 232 | 233 | FBV_ctrls[FBV_ID_TAP_i].fbv_id = FBV_ID_TAP; 234 | //FBV_ctrls[FBV_ID_TAP_i].type = FBV_ID_TYPE_TEMPO; 235 | FBV_ctrls[FBV_ID_TAP_i].type = FBV_ID_TYPE_TEMPO_TUNER; 236 | //FBV_ctrls[FBV_ID_TAP_i].type = FBV_ID_TYPE_BTN_LED; 237 | FBV_ctrls[FBV_ID_TAP_i].cc = 14; 238 | FBV_ctrls[FBV_ID_TAP_i].status = 107; 239 | 240 | 241 | FBV_ctrls[FBV_ID_DELAY_i].fbv_id = FBV_ID_DELAY; 242 | FBV_ctrls[FBV_ID_DELAY_i].type = FBV_ID_TYPE_BTN_LED; 243 | FBV_ctrls[FBV_ID_DELAY_i].cc = 28; 244 | 245 | FBV_ctrls[FBV_ID_MODULATION_i].fbv_id = FBV_ID_MODULATION; 246 | FBV_ctrls[FBV_ID_MODULATION_i].type = FBV_ID_TYPE_BTN_LED; 247 | FBV_ctrls[FBV_ID_MODULATION_i].cc = 50; 248 | 249 | FBV_ctrls[FBV_ID_PITCH_i].fbv_id = FBV_ID_PITCH; 250 | FBV_ctrls[FBV_ID_PITCH_i].type = FBV_ID_TYPE_BTN_LED; 251 | FBV_ctrls[FBV_ID_PITCH_i].cc = 113; 252 | 253 | FBV_ctrls[FBV_ID_REVERB_i].fbv_id = FBV_ID_REVERB; 254 | FBV_ctrls[FBV_ID_REVERB_i].type = FBV_ID_TYPE_BTN_LED; 255 | FBV_ctrls[FBV_ID_REVERB_i].cc = 36; 256 | 257 | FBV_ctrls[FBV_ID_AMP2_i].fbv_id = FBV_ID_AMP2; 258 | FBV_ctrls[FBV_ID_AMP2_i].type = FBV_ID_TYPE_BTN_LED; 259 | FBV_ctrls[FBV_ID_AMP2_i].cc = 112; 260 | 261 | FBV_ctrls[FBV_ID_AMP1_i].fbv_id = FBV_ID_AMP1; 262 | FBV_ctrls[FBV_ID_AMP1_i].type = FBV_ID_TYPE_BTN_LED; 263 | FBV_ctrls[FBV_ID_AMP1_i].cc = 111; 264 | 265 | FBV_ctrls[FBV_ID_CHAN_FAV_i].fbv_id = FBV_ID_CHAN_FAV; 266 | FBV_ctrls[FBV_ID_CHAN_FAV_i].type = FBV_ID_TYPE_BTN_LED; 267 | FBV_ctrls[FBV_ID_CHAN_FAV_i].cc = 52; 268 | 269 | FBV_ctrls[FBV_ID_CHAN_D_i].fbv_id = FBV_ID_CHAN_D; 270 | FBV_ctrls[FBV_ID_CHAN_D_i].type = FBV_ID_TYPE_PRESET; 271 | FBV_ctrls[FBV_ID_CHAN_D_i].cc = 3; 272 | 273 | FBV_ctrls[FBV_ID_CHAN_C_i].fbv_id = FBV_ID_CHAN_C; 274 | FBV_ctrls[FBV_ID_CHAN_C_i].type = FBV_ID_TYPE_PRESET; 275 | FBV_ctrls[FBV_ID_CHAN_C_i].cc = 2; 276 | 277 | FBV_ctrls[FBV_ID_CHAN_B_i].fbv_id = FBV_ID_CHAN_B; 278 | FBV_ctrls[FBV_ID_CHAN_B_i].type = FBV_ID_TYPE_PRESET; 279 | FBV_ctrls[FBV_ID_CHAN_B_i].cc = 1; 280 | 281 | FBV_ctrls[FBV_ID_CHAN_A_i].fbv_id = FBV_ID_CHAN_A; 282 | FBV_ctrls[FBV_ID_CHAN_A_i].type = FBV_ID_TYPE_PRESET; 283 | FBV_ctrls[FBV_ID_CHAN_A_i].cc = 0; 284 | 285 | FBV_ctrls[FBV_ID_BANK_UP_i].fbv_id = FBV_ID_BANK_UP; 286 | FBV_ctrls[FBV_ID_BANK_UP_i].type = FBV_ID_TYPE_BANK; 287 | FBV_ctrls[FBV_ID_BANK_UP_i].cc = 1; 288 | 289 | FBV_ctrls[FBV_ID_BANK_DOWN_i].fbv_id = FBV_ID_BANK_DOWN; 290 | FBV_ctrls[FBV_ID_BANK_DOWN_i].type = FBV_ID_TYPE_BANK; 291 | FBV_ctrls[FBV_ID_BANK_DOWN_i].cc = 0; 292 | 293 | FBV_ctrls[FBV_ID_STOMP3_i].fbv_id = FBV_ID_STOMP3; 294 | FBV_ctrls[FBV_ID_STOMP3_i].type = FBV_ID_TYPE_BTN_LED; 295 | FBV_ctrls[FBV_ID_STOMP3_i].cc = 110; 296 | 297 | FBV_ctrls[FBV_ID_STOMP2_i].fbv_id = FBV_ID_STOMP2; 298 | FBV_ctrls[FBV_ID_STOMP2_i].type = FBV_ID_TYPE_BTN_LED; 299 | FBV_ctrls[FBV_ID_STOMP2_i].cc = 109; 300 | 301 | FBV_ctrls[FBV_ID_STOMP1_i].fbv_id = FBV_ID_STOMP1; 302 | FBV_ctrls[FBV_ID_STOMP1_i].type = FBV_ID_TYPE_BTN_LED; 303 | FBV_ctrls[FBV_ID_STOMP1_i].cc = 25; 304 | 305 | FBV_ctrls[FBV_ID_FX_LOOP_i].fbv_id = FBV_ID_FX_LOOP; 306 | FBV_ctrls[FBV_ID_FX_LOOP_i].type = FBV_ID_TYPE_BTN_LED; 307 | FBV_ctrls[FBV_ID_FX_LOOP_i].cc = 107; 308 | 309 | FBV_ctrls[FBV_ID_FOOT_CTRL_V_BTN_i].fbv_id = FBV_ID_FOOT_CTRL_V_BTN; 310 | FBV_ctrls[FBV_ID_FOOT_CTRL_V_BTN_i].type = FBV_ID_TYPE_FOOT_CTRL; 311 | FBV_ctrls[FBV_ID_FOOT_CTRL_V_BTN_i].cc = FBV_ID_FOOT_CTRL_V_VAL_i; 312 | 313 | FBV_ctrls[FBV_ID_FOOT_CTRL_W_BTN_i].fbv_id = FBV_ID_FOOT_CTRL_W_BTN; 314 | FBV_ctrls[FBV_ID_FOOT_CTRL_W_BTN_i].type = FBV_ID_TYPE_FOOT_CTRL; 315 | FBV_ctrls[FBV_ID_FOOT_CTRL_W_BTN_i].cc = FBV_ID_FOOT_CTRL_W_VAL_i; 316 | 317 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].fbv_id_foot = FBV_ID_FOOT_CTRL_V_VAL; 318 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].fbv_id_btn= FBV_ID_FOOT_CTRL_V_BTN; 319 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].fbv_id_led1 = FBV_ID_FOOT_CTRL_P2_LED; 320 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].fbv_id_led2 = FBV_ID_FOOT_CTRL_V_LED; 321 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].cc = 105; 322 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].cc_value1 = 125; 323 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].cc_value2 = 7; 324 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].status = FBV_ID_OFF; 325 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_V_VAL_i].len = 0; 326 | 327 | 328 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_foot = FBV_ID_FOOT_CTRL_W_VAL; 329 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_btn= FBV_ID_FOOT_CTRL_W_BTN; 330 | 331 | //FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_led1 = FBV_ID_FOOT_CTRL_P1_LED; 332 | //FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_led2 = FBV_ID_FOOT_CTRL_W_LED; 333 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_led1 = FBV_ID_FOOT_CTRL_W_LED; 334 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].fbv_id_led2 = FBV_ID_FOOT_CTRL_P1_LED; 335 | 336 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].cc = 43; 337 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].cc_value1 = 126; 338 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].cc_value2 = 2; 339 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].status = FBV_ID_OFF; 340 | FBV_ctrls_cont[FBV_ID_FOOT_CTRL_W_VAL_i].len = 0; 341 | 342 | } 343 | 344 | 345 | typedef struct { 346 | u8 status; 347 | u8 led_count; 348 | u16 btn_count; 349 | } FBV_tempo_tuner_info_struct; 350 | 351 | FBV_tempo_tuner_info_struct FBV_tempo_tuner_info = {0}; 352 | 353 | ///////////////////////////////////////////////////////////////////////////// 354 | // Local prototypes 355 | ///////////////////////////////////////////////////////////////////////////// 356 | static void APP_Periodic_100uS(void); 357 | static void TASK_FBV_Check(void *pvParameters); 358 | static s32 AxeFX_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in); 359 | static void AxeFX_SYSEX_Handle_Package(void); 360 | 361 | ///////////////////////////////////////////////////////////////////////////// 362 | // This hook is called after startup to initialize the application 363 | ///////////////////////////////////////////////////////////////////////////// 364 | void APP_Init(void) 365 | { 366 | 367 | #if DEBUG_VERBOSE_LEVEL >= 1 368 | // print welcome message on MIOS terminal 369 | DEBUG_MSG("\n"); 370 | DEBUG_MSG("====================\n"); 371 | DEBUG_MSG("%s\n", MIOS32_LCD_BOOT_MSG_LINE1); 372 | DEBUG_MSG("====================\n"); 373 | DEBUG_MSG("\n"); 374 | #endif 375 | 376 | // clear mS counter 377 | ms_counter = 0; 378 | 379 | // init MIDImon 380 | //MIDIMON_Init(0); 381 | 382 | // initialize status LED 383 | MIOS32_BOARD_LED_Init(0x1); 384 | MIOS32_BOARD_LED_Set(1, 0); 385 | 386 | FBV_UART_Init(0); 387 | 388 | do_init_info(); 389 | 390 | midi_channel = 0; 391 | midi_bank_size = 4; 392 | midi_bank = 0; 393 | 394 | FBV_UART_TxBufferSendChannelCommand(FBV_CHANNEL_USER,'0' + (midi_bank/10),'0' + (midi_bank%10)); //ascii code for numbers 395 | FBV_UART_TxBufferSendLedCommand(FBV_ID_CHAN_A, FBV_LED_ON); 396 | 397 | FBV_UART_TxBufferSendDisplay("VLoTech FBV ctrl",16); 398 | 399 | MIOS32_MIDI_SendProgramChange(USB1, RACK_MIDI_CHN, midi_channel); 400 | MIOS32_MIDI_SendProgramChange(UART1, RACK_MIDI_CHN, midi_channel); 401 | 402 | MIOS32_MIDI_SysExCallback_Init(AxeFX_SYSEX_Parser); 403 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_version_sysex,axefx_request_version_length); 404 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_blocks_sysex,axefx_request_blocks_length); 405 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_patch_name_sysex,axefx_request_patch_name_length); 406 | 407 | // install timer function which is called each 100 uS 408 | MIOS32_TIMER_Init(0, 100, APP_Periodic_100uS, MIOS32_IRQ_PRIO_MID); 409 | 410 | // start BLM check task 411 | xTaskCreate(TASK_FBV_Check, (signed portCHAR *)"FBV_Check", MIOS32_MINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_FBV_CHECK, NULL); 412 | 413 | } 414 | 415 | ///////////////////////////////////////////////////////////////////////////// 416 | // This task is running endless in background 417 | ///////////////////////////////////////////////////////////////////////////// 418 | void APP_Background(void) 419 | { 420 | // // init LCD 421 | // MIOS32_LCD_Clear(); 422 | // MIOS32_LCD_CursorSet(0, 0); 423 | // MIOS32_LCD_PrintString("see README.txt "); 424 | // MIOS32_LCD_CursorSet(0, 1); 425 | // MIOS32_LCD_PrintString("for details "); 426 | 427 | // endless loop 428 | while( 1 ) { 429 | // do nothing 430 | } 431 | } 432 | 433 | 434 | ///////////////////////////////////////////////////////////////////////////// 435 | // This hook is called when a MIDI package has been received 436 | ///////////////////////////////////////////////////////////////////////////// 437 | void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) 438 | { 439 | // forward packages USBx->UARTx and UARTx->USBx 440 | switch( port ) { 441 | case USB0: 442 | MIOS32_MIDI_SendPackage(UART0, midi_package); 443 | break; 444 | 445 | case USB1: 446 | MIOS32_MIDI_SendPackage(UART1, midi_package); 447 | break; 448 | 449 | case UART0: 450 | MIOS32_MIDI_SendPackage(USB0, midi_package); 451 | break; 452 | 453 | case UART1: 454 | MIOS32_MIDI_SendPackage(USB1, midi_package); 455 | break; 456 | } 457 | // forward to MIDI Monitor 458 | // SysEx messages have to be filtered for USB0 and UART0 to avoid data corruption 459 | // (the SysEx stream would interfere with monitor messages) 460 | // u8 filter_sysex_message = (port == USB0) || (port == UART0); 461 | // MIDIMON_Receive(port, midi_package, ms_counter, filter_sysex_message); 462 | } 463 | 464 | 465 | void APP_SRIO_ServicePrepare(void) { } 466 | void APP_SRIO_ServiceFinish(void) { } 467 | void APP_DIN_NotifyToggle(u32 pin, u32 pin_value) { } 468 | void APP_ENC_NotifyChange(u32 encoder, s32 incrementer) { } 469 | void APP_AIN_NotifyChange(u32 pin, u32 pin_value) { } 470 | 471 | ///////////////////////////////////////////////////////////////////////////// 472 | // This function parses an incoming sysex stream for SysEx messages 473 | ///////////////////////////////////////////////////////////////////////////// 474 | s32 AxeFX_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in) 475 | { 476 | if( port != AXEFX_PORT ) 477 | return 0; // forward package to APP_MIDI_NotifyPackage() 478 | 479 | // branch depending on state 480 | if( sysex_state == SYSEX_HEADER ) { 481 | if( midi_in != sysex_header[sysex_count]) { 482 | // incoming byte doesn't match 483 | sysex_count = 0; 484 | sysex_cmd = 0; 485 | DEBUG_MSG("AxeFX other byte found than header\n"); 486 | } else { 487 | sysex_buffer[sysex_count++] = midi_in; 488 | if( sysex_count == sizeof(sysex_header) ) { 489 | // complete header received, waiting for data 490 | sysex_state = SYSEX_CMD_STATE_BEGIN; 491 | sysex_count = 0; 492 | sysex_axefx_type = sysex_buffer[4]; 493 | 494 | DEBUG_MSG("AxeFX %s header found\n", sysex_axefx_type==0?"Standard":"Ultra"); 495 | } 496 | } 497 | } else { 498 | // check for end of SysEx message or invalid status byte 499 | if( midi_in >= 0x80 ) { 500 | if( midi_in == 0xf7 && sysex_state == SYSEX_CMD_STATE_CONT ) { 501 | sysex_state = SYSEX_CMD_STATE_END; 502 | DEBUG_MSG("AxeFX data done\n"); 503 | } else { 504 | sysex_state = SYSEX_HEADER; 505 | sysex_count = 0; 506 | sysex_cmd = 0; 507 | DEBUG_MSG("AxeFX data broken\n"); 508 | } 509 | } else { 510 | // check if command byte has been received 511 | if (sysex_state == SYSEX_CMD_STATE_BEGIN) { 512 | sysex_cmd = midi_in; 513 | sysex_state = SYSEX_CMD_STATE_CONT; 514 | sysex_count = 0; 515 | DEBUG_MSG("AxeFX CMD received %02X\n", sysex_cmd); 516 | } else { 517 | if(sysex_count=0x10 || sysex_buffer[2] <0x70) { 553 | 554 | switch(sysex_buffer[0]) { 555 | case 0:FBV_UART_TxBufferSendTuner('A',0);break; 556 | case 1:FBV_UART_TxBufferSendTuner('B',1);break; 557 | case 2:FBV_UART_TxBufferSendTuner('B',0);break; 558 | case 3:FBV_UART_TxBufferSendTuner('C',0);break; 559 | case 4:FBV_UART_TxBufferSendTuner('D',1);break; 560 | case 5:FBV_UART_TxBufferSendTuner('D',0);break; 561 | case 6:FBV_UART_TxBufferSendTuner('E',1);break; 562 | case 7:FBV_UART_TxBufferSendTuner('E',0);break; 563 | case 8:FBV_UART_TxBufferSendTuner('F',0);break; 564 | case 9:FBV_UART_TxBufferSendTuner('G',1);break; 565 | case 10:FBV_UART_TxBufferSendTuner('G',0);break; 566 | case 11:FBV_UART_TxBufferSendTuner('A',1);break; 567 | default:FBV_UART_TxBufferSendTuner(' ',0);break; 568 | } 569 | 570 | // sysex_buffer[2] == pos from 0x10 to 0x6F 571 | if(sysex_buffer[2] < 0x1A) { 572 | needle[0] = ')'; 573 | } 574 | if(sysex_buffer[2] < 0x20) { 575 | needle[1] = ')'; 576 | } 577 | if(sysex_buffer[2] < 0x26) { 578 | needle[2] = ')'; 579 | } 580 | if(sysex_buffer[2] < 0x2C) { 581 | needle[3] = ')'; 582 | } 583 | if(sysex_buffer[2] < 0x32) { 584 | needle[4] = ')'; 585 | } 586 | if(sysex_buffer[2] < 0x38) { 587 | needle[5] = ')'; 588 | } 589 | if(sysex_buffer[2] < 0x3E) { 590 | needle[6] = ')'; 591 | } 592 | if(sysex_buffer[2] < 0x42) { 593 | needle[7] = ')'; 594 | } 595 | if(sysex_buffer[2] > 0x3E) { 596 | needle[8] = '('; 597 | } 598 | if(sysex_buffer[2] > 0x41) { 599 | needle[9] = '('; 600 | } 601 | if(sysex_buffer[2] > 0x47) { 602 | needle[10] = '('; 603 | } 604 | if(sysex_buffer[2] > 0x4D) { 605 | needle[11] = '('; 606 | } 607 | if(sysex_buffer[2] > 0x53) { 608 | needle[12] = '('; 609 | } 610 | if(sysex_buffer[2] > 0x59) { 611 | needle[13] = '('; 612 | } 613 | if(sysex_buffer[2] > 0x5F) { 614 | needle[14] = '('; 615 | } 616 | if(sysex_buffer[2] > 0x65) { 617 | needle[15] = '('; 618 | } 619 | if(sysex_buffer[2] > 0x3E && sysex_buffer[2] < 0x42) { 620 | needle[6] = '-'; 621 | needle[7] = '*'; 622 | needle[8] = '*'; 623 | needle[9] = '-'; 624 | } 625 | 626 | 627 | FBV_UART_TxBufferSendDisplay(needle,16); 628 | 629 | } else { 630 | FBV_UART_TxBufferSendTuner(' ',0); 631 | FBV_UART_TxBufferSendDisplay(" ",16); 632 | } 633 | 634 | } 635 | break; 636 | 637 | case 0x0e: 638 | // block status result 639 | DEBUG_MSG("AxeFX block status result\n"); 640 | for(i = 0; itype == FBV_ID_TYPE_BTN_LED) { 654 | ctrl->blocks[ctrl->len].cc = fx_cc; 655 | ctrl->blocks[ctrl->len].id = fx_id; 656 | ctrl->blocks[ctrl->len].status = status; 657 | 658 | if(ctrl->len == 0) 659 | ctrl->status = status; 660 | 661 | FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, status); 662 | 663 | ctrl->len++; 664 | } else if(ctrl->type == FBV_ID_TYPE_FOOT_CTRL) { 665 | fbv_footctrl_t *foot = &(FBV_ctrls_cont[ctrl->cc]); 666 | 667 | foot->blocks[foot->len].cc = fx_cc; 668 | foot->blocks[foot->len].id = fx_id; 669 | foot->blocks[foot->len].status = status; 670 | 671 | if(foot->len == 0) { 672 | foot->status = status; 673 | if(status== FBV_ID_OFF) { 674 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led1, FBV_ID_ON); 675 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led2, FBV_ID_OFF); 676 | } else { 677 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led1, FBV_ID_OFF); 678 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led2, FBV_ID_ON); 679 | } 680 | } 681 | 682 | 683 | foot->len++; 684 | } 685 | DEBUG_MSG("------ for FBV: %02X\n", ctrl->fbv_id); 686 | } else { 687 | DEBUG_MSG("------ NOT USED !!\n"); 688 | } 689 | DEBUG_MSG("AxeFX fx-ID: %02X\n", fx_id); 690 | DEBUG_MSG("AxeFX fx-CC: %02X\n", fx_cc); 691 | DEBUG_MSG("AxeFX fx-status: %02X\n", status); 692 | } 693 | break; 694 | case 0x0f: 695 | // patch name result 696 | DEBUG_MSG("AxeFX patch name status result\n"); 697 | DEBUG_MSG(sysex_buffer); 698 | FBV_UART_TxBufferSendDisplay(sysex_buffer,16); 699 | break; 700 | case 0x08: 701 | // version status result 702 | DEBUG_MSG("AxeFX version status result\n"); 703 | u8 axefx_major = sysex_buffer[i]; 704 | u8 axefx_minor = sysex_buffer[i+1]; 705 | DEBUG_MSG("AxeFX major: %02i\n", axefx_major); 706 | DEBUG_MSG("AxeFX minor: %02i\n", axefx_minor); 707 | 708 | if(sysex_axefx_type==0x0) { 709 | u8 buf[17] = "Axe-FX Std v0.00"; 710 | if(axefx_major>9) 711 | buf[11] = '0'+ axefx_major/10; 712 | buf[12] = '0'+ axefx_major%10; 713 | buf[14] = '0'+ axefx_minor/10; 714 | buf[15] = '0'+ axefx_minor%10; 715 | //FBV_UART_TxBufferSendDisplay(buf,16); 716 | } else if(sysex_axefx_type==0x1) { 717 | u8 buf[17] = "Axe-FX Ult v0.00"; 718 | if(axefx_major>9) 719 | buf[11] = '0'+ axefx_major/10; 720 | buf[12] = '0'+ axefx_major%10; 721 | buf[14] = '0'+ axefx_minor/10; 722 | buf[15] = '0'+ axefx_minor%10; 723 | //FBV_UART_TxBufferSendDisplay(buf,16); 724 | } 725 | 726 | break; 727 | case 0x10: 728 | // tempo tap info 729 | FBV_tempo_tuner_info.led_count = 0x01; 730 | for(i = 0; i 0 ) { 758 | for(j=0; j< FBV_ctrls[i].len; j++ ) { 759 | if(FBV_ctrls[i].blocks[j].status == 0) { 760 | FBV_UART_TxBufferSendLedCommand(FBV_ctrls[i].fbv_id, FBV_LED_ON); 761 | break; 762 | } 763 | } 764 | 765 | } 766 | } 767 | 768 | if((midi_channel)/midi_bank_size != midi_bank ) { 769 | for(i = 0;i 0 ) { 779 | for(j=0; j< FBV_ctrls[i].len; j++ ) { 780 | if(FBV_ctrls[i].blocks[j].status == 0) { 781 | FBV_UART_TxBufferSendLedCommand(FBV_ctrls[i].fbv_id, FBV_LED_OFF); 782 | break; 783 | } 784 | } 785 | 786 | } 787 | } 788 | 789 | 790 | } else if((flash_cnt) == 0x1000) { 791 | if((midi_channel)/midi_bank_size != midi_bank ) { 792 | for(i = 0;i= 1875) {// 3 sec. 800 | for(i = 0; i=0x2000) 833 | flash_cnt = 0; 834 | 835 | } 836 | 837 | 838 | static void TASK_FBV_Check(void *pvParameters) 839 | { 840 | portTickType xLastExecutionTime; 841 | 842 | // Initialise the xLastExecutionTime variable on task entry 843 | xLastExecutionTime = xTaskGetTickCount(); 844 | 845 | while( 1 ) { 846 | vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS); 847 | 848 | mios32_fbv_message_t msg = {0}; 849 | 850 | while(FBV_UART_RxBufferReceiveMessage(&msg) == 0) { 851 | // DEBUG_MSG("FBV Message:\n"); 852 | // DEBUG_MSG("header: %08X\n", msg.header); 853 | // DEBUG_MSG("size: %08X\n", msg.size); 854 | // DEBUG_MSG("cmd: %08X\n", msg.cmd); 855 | // if(msg.pos == 1) 856 | // DEBUG_MSG("data: %08X\n", msg.data[0]); 857 | // else if(msg.pos > 1) { 858 | // DEBUG_MSG("data:\n"); 859 | // MIOS32_MIDI_SendDebugHexDump(msg.data,msg.pos); 860 | // } 861 | // DEBUG_MSG("------------\n"); 862 | 863 | if(msg.cmd == 0x90) { //INIT ?!? 864 | 865 | int i; 866 | 867 | FBV_UART_TxBufferSendInit(); 868 | 869 | FBV_UART_TxBufferSendChannelCommand(FBV_CHANNEL_USER,'0' + (midi_bank/10),'0' + (midi_bank%10)); //ascii code for numbers 870 | FBV_UART_TxBufferSendLedCommand(FBV_ID_CHAN_A, FBV_LED_ON); 871 | 872 | for(i = 0; i < midi_bank_size; i++) 873 | FBV_UART_TxBufferSendLedCommand(bank_ids[i], FBV_LED_OFF); 874 | FBV_UART_TxBufferSendLedCommand(bank_ids[(midi_channel%midi_bank_size)], FBV_LED_ON); 875 | 876 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_version_sysex,axefx_request_version_length); 877 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_blocks_sysex,axefx_request_blocks_length); 878 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_patch_name_sysex,axefx_request_patch_name_length); 879 | 880 | } 881 | 882 | else if(msg.cmd == 0x81 && msg.data[1] == FBV_BUTTON_PRESSED ) { //BUTTON -> PRESSED 883 | int i,j,k; 884 | u8 handled = 0; 885 | //FBV_UART_TxBufferSendLedCommand(msg.data[0], msg.data[1]); 886 | 887 | DEBUG_MSG("FBV button pressed:\n"); 888 | DEBUG_MSG("FBV button %08X\n",msg.data[0]); 889 | for(i = 0; ifbv_id); 895 | DEBUG_MSG("type is %08X\n",ctrl->type); 896 | 897 | 898 | if(ctrl->type == FBV_ID_TYPE_BTN_LED) { 899 | //if(ctrl->len == 0) { 900 | if(ctrl->status == FBV_ID_OFF) { 901 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, ctrl->cc, 127); 902 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, ctrl->cc, 127); 903 | FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_ON); 904 | ctrl->status = FBV_ID_ON; 905 | DEBUG_MSG("to ON %i\n",ctrl->cc); 906 | } else { 907 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, ctrl->cc, 0); 908 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, ctrl->cc, 0); 909 | FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_OFF); 910 | ctrl->status = FBV_ID_OFF; 911 | DEBUG_MSG("to OFF %i\n",ctrl->cc); 912 | } 913 | //} else { 914 | for(j=0; j< ctrl->len; j++ ) { 915 | if(ctrl->blocks[j].status == FBV_ID_OFF) { 916 | if(ctrl->blocks[j].cc != 128) { 917 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, ctrl->blocks[j].cc, 127); 918 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, ctrl->blocks[j].cc, 127); 919 | } else { 920 | // TODO: Add SysEx control 921 | } 922 | //FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_ON); 923 | ctrl->blocks[j].status = FBV_ID_ON; 924 | //ctrl->status = FBV_ID_ON; 925 | DEBUG_MSG("to AxeFX block ON %i\n",ctrl->cc); 926 | } else { 927 | if(ctrl->blocks[j].cc != 128) { 928 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, ctrl->blocks[j].cc, 0); 929 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, ctrl->blocks[j].cc, 0); 930 | } else { 931 | // TODO: Add SysEx control 932 | } 933 | //FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_OFF); 934 | DEBUG_MSG("to AxeFX block OFF %i\n",ctrl->cc); 935 | ctrl->blocks[j].status = FBV_ID_OFF; 936 | //ctrl->status = FBV_ID_OFF; 937 | } 938 | } 939 | //} 940 | } else if(ctrl->type == FBV_ID_TYPE_BANK) { // TODO: handle banks above preset 128 941 | if(ctrl->cc == 0) { 942 | //down 943 | if(midi_bank==0) midi_bank = 20; else midi_bank -= 1; 944 | } else { 945 | if(midi_bank==20) midi_bank = 0; else midi_bank += 1; 946 | } 947 | FBV_UART_TxBufferSendChannelCommand(FBV_CHANNEL_USER,'0' + (midi_bank/10),'0' + (midi_bank%10)); 948 | } else if(ctrl->type == FBV_ID_TYPE_PRESET) { // TODO: handle banks above preset 128 949 | midi_channel = midi_bank*midi_bank_size + ctrl->cc; 950 | for(k = 0; k < midi_bank_size; k++) 951 | FBV_UART_TxBufferSendLedCommand(bank_ids[k], FBV_LED_OFF); 952 | FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_ON); 953 | for(k = 0; k < FBV_ID_MAX_INDEX; k++) { 954 | if(FBV_ctrls[k].type == FBV_ID_TYPE_BTN_LED) { 955 | FBV_UART_TxBufferSendLedCommand(FBV_ctrls[k].fbv_id, FBV_LED_OFF); 956 | FBV_ctrls[k].status = FBV_ID_OFF; 957 | } 958 | } 959 | MIOS32_MIDI_SendProgramChange(USB1, RACK_MIDI_CHN, midi_channel); 960 | MIOS32_MIDI_SendProgramChange(UART1, RACK_MIDI_CHN, midi_channel); 961 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_blocks_sysex,axefx_request_blocks_length); 962 | MIOS32_MIDI_SendSysEx(AXEFX_PORT,axefx_request_patch_name_sysex,axefx_request_patch_name_length); 963 | } else if (ctrl->type == FBV_ID_TYPE_TEMPO || ctrl->type == FBV_ID_TYPE_TEMPO_TUNER ) { 964 | // send tap tempo CC 965 | FBV_tempo_tuner_info.status = FBV_BUTTON_PRESSED; 966 | FBV_tempo_tuner_info.btn_count = 0; 967 | 968 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, ctrl->cc, 127); 969 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, ctrl->cc, 127); 970 | } else if(ctrl->type == FBV_ID_TYPE_FOOT_CTRL) { 971 | fbv_footctrl_t *foot = &FBV_ctrls_cont[ctrl->cc]; 972 | //if(ctrl->len == 0) { 973 | if(foot->status == FBV_ID_OFF) { 974 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->cc, 127); 975 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->cc, 127); 976 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led1, FBV_LED_OFF); 977 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led2, FBV_LED_ON); 978 | foot->status = FBV_ID_ON; 979 | DEBUG_MSG("to ON %i\n",foot->cc); 980 | } else { 981 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->cc, 0); 982 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->cc, 0); 983 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led1, FBV_LED_ON); 984 | FBV_UART_TxBufferSendLedCommand(foot->fbv_id_led2, FBV_LED_OFF); 985 | foot->status = FBV_ID_OFF; 986 | DEBUG_MSG("to OFF %i\n",ctrl->cc); 987 | } 988 | //} else { 989 | for(j=0; j< foot->len; j++ ) { 990 | if(foot->blocks[j].status == FBV_ID_OFF) { 991 | if(foot->blocks[j].cc != 128) { 992 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->blocks[j].cc, 127); 993 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->blocks[j].cc, 127); 994 | } else { 995 | // TODO: Add SysEx control 996 | } 997 | //FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_ON); 998 | foot->blocks[j].status = FBV_ID_ON; 999 | //ctrl->status = FBV_ID_ON; 1000 | DEBUG_MSG("to AxeFX block ON %i\n",foot->cc); 1001 | } else { 1002 | if(foot->blocks[j].cc != 128) { 1003 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->blocks[j].cc, 0); 1004 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->blocks[j].cc, 0); 1005 | } else { 1006 | // TODO: Add SysEx control 1007 | } 1008 | //FBV_UART_TxBufferSendLedCommand(ctrl->fbv_id, FBV_LED_OFF); 1009 | DEBUG_MSG("to AxeFX block OFF %i\n",foot->cc); 1010 | foot->blocks[j].status = FBV_ID_OFF; 1011 | //ctrl->status = FBV_ID_OFF; 1012 | } 1013 | } 1014 | //} 1015 | } 1016 | break; 1017 | } 1018 | } 1019 | } 1020 | 1021 | else if(msg.cmd == 0x81 && msg.data[1] == FBV_BUTTON_RELEASED ) { //BUTTON -> RELEASED 1022 | int i; 1023 | //FBV_UART_TxBufferSendLedCommand(msg.data[0], msg.data[1]); 1024 | 1025 | DEBUG_MSG("FBV button released:\n"); 1026 | DEBUG_MSG("FBV button %08X\n",msg.data[0]); 1027 | for(i = 0; istatus == FBV_ID_OFF ) { 1062 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->cc_value1, msg.data[1]); 1063 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->cc_value1, msg.data[1]); 1064 | } else { 1065 | MIOS32_MIDI_SendCC(USB1, RACK_MIDI_CHN, foot->cc_value2, msg.data[1]); 1066 | MIOS32_MIDI_SendCC(UART1, RACK_MIDI_CHN, foot->cc_value2, msg.data[1]); 1067 | } 1068 | 1069 | } 1070 | 1071 | } 1072 | 1073 | } 1074 | 1075 | } 1076 | } 1077 | --------------------------------------------------------------------------------