├── debug-utils └── MIDI LE for OSX │ ├── MIDI LE for OSX.app │ └── Contents │ │ ├── PkgInfo │ │ ├── MacOS │ │ └── MIDI LE for OSX │ │ ├── Resources │ │ └── Base.lproj │ │ │ └── MainMenu.nib │ │ ├── Info.plist │ │ └── _CodeSignature │ │ └── CodeResources │ ├── MIDI LE for OSX Binary.zip │ ├── MIDI LE for OSX │ ├── PGMidi │ │ ├── worra.mp3 │ │ ├── PGMidiAllSources.h │ │ ├── PGMidiFind.h │ │ ├── PGArc.h │ │ ├── PGMidiAllSources.mm │ │ ├── iOSVersionDetection.h │ │ ├── PGMidiFind.mm │ │ └── PGMidi.h │ ├── main.m │ ├── NSData+hexConv.h │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── NSData+hexConv.m │ └── AppDelegate.h │ ├── MIDI LE for OSX.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sierenmusic.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sierenmusic.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ └── MIDI LE for OSX.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ ├── README.md │ └── MIDI LE for OSXTests │ ├── Info.plist │ └── MIDI_LE_for_OSXTests.m ├── run_unit_tests.sh ├── .gitmodules ├── .travis.yml ├── LICENSE ├── Legacy Projects └── nRF8001-BLE-Proto │ ├── RBL_nRF8001 │ ├── examples │ │ ├── BLE_RGB │ │ │ ├── BLE_RGB.ino │ │ │ └── Adafruit_NeoPixel.h │ │ ├── SimpleChat │ │ │ └── SimpleChat.ino │ │ ├── HelloWorld │ │ │ └── HelloWorld.ino │ │ ├── SimpleControls │ │ │ └── SimpleControls.ino │ │ ├── BLEFirmataSketch │ │ │ ├── BLEFirmata.h │ │ │ ├── BLEFirmata.cpp │ │ │ └── Boards.h │ │ └── BLEControllerSketch │ │ │ ├── BLEControllerSketch.ino │ │ │ └── Boards.h │ ├── RBL_nRF8001.h │ ├── RBL_services_OLD.h │ └── RBL_services.h │ ├── README.md │ ├── RBL_services.h │ └── nRF8001-BLE-Proto.ino ├── nRF51822-BLEMIDI ├── README.md ├── projectconfig.h ├── nRF51822-BLEMIDI.ino └── BLEParser.h ├── CMakeLists.txt ├── README.md └── unit_tests └── tst_BLEParser.cpp /debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /run_unit_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir build 4 | cd build 5 | cmake ./../ 6 | make 7 | ./bletest 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "nRF51822-BLEMIDI/googletest"] 2 | path = nRF51822-BLEMIDI/googletest 3 | url = https://github.com/google/googletest.git 4 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX Binary.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sieren/blidino/HEAD/debug-utils/MIDI LE for OSX/MIDI LE for OSX Binary.zip -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | os: 3 | - osx 4 | env: 5 | - CONFIG=Release 6 | - CONFIG=Debug 7 | install: 8 | script: 9 | ./run_unit_tests.sh 10 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/worra.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sieren/blidino/HEAD/debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/worra.mp3 -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/MacOS/MIDI LE for OSX: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sieren/blidino/HEAD/debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/MacOS/MIDI LE for OSX -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/Resources/Base.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sieren/blidino/HEAD/debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/Resources/Base.lproj/MainMenu.nib -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/project.xcworkspace/xcuserdata/sierenmusic.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sieren/blidino/HEAD/debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/project.xcworkspace/xcuserdata/sierenmusic.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MIDI LE for OSX 4 | // 5 | // Created by Matthias Frick on 08.10.2014. 6 | // Copyright (c) 2014 Matthias Frick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/NSData+hexConv.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+hexConv.h 3 | // MIDI LE for OSX 4 | // 5 | // Created by Matthias Frick on 08.10.2014. 6 | // Copyright (c) 2014 Matthias Frick. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSData (hexConv) 12 | -(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces; 13 | @end 14 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/README.md: -------------------------------------------------------------------------------- 1 | MIDI LE FOR OSX 2 | ======= 3 | 4 | Based on Apple's Sample Code fora Bluetooth LE Heart Rate Monitor this utility connects to devices offering the MIDI-BLE UDID/Characeteristic introduced in OSX/iOS and prints out the received "MIDI"-Packets in HEX. I am using this tool to monitor and debug incoming raw packets. It's just a quick hack at this point and at some point might be extended to route incoming MIDI Data to the IAC Bus for backwards compatibility to OSX 10.7+. 5 | 6 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/PGMidiAllSources.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGMidiAllSources.h 3 | // PGMidi 4 | // 5 | 6 | #import 7 | 8 | @class PGMidi; 9 | @protocol PGMidiSourceDelegate; 10 | 11 | @interface PGMidiAllSources : NSObject 12 | { 13 | PGMidi *midi; 14 | id delegate; 15 | } 16 | 17 | #if ! __has_feature(objc_arc) 18 | 19 | @property (nonatomic,assign) PGMidi *midi; 20 | @property (nonatomic,assign) id delegate; 21 | 22 | #else 23 | 24 | @property (nonatomic,strong) PGMidi *midi; 25 | @property (nonatomic,strong) id delegate; 26 | 27 | #endif 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/PGMidiFind.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGMidiFind.h 3 | // PGMidi 4 | // 5 | 6 | #import "PGMidi.h" 7 | 8 | @interface PGMidi (FindingConnections) 9 | 10 | - (PGMidiSource*) findSourceCalled:(NSString*)name; 11 | 12 | - (PGMidiDestination*) findDestinationCalled:(NSString*)name; 13 | 14 | - (void) findMatchingSource:(PGMidiSource**)source 15 | andDestination:(PGMidiDestination**)destination; 16 | 17 | - (void) findMatchingSource:(PGMidiSource**)source 18 | andDestination:(PGMidiDestination**)destination 19 | avoidNames:(NSArray*)namesToAvoid; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/xcuserdata/sierenmusic.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MIDI LE for OSX.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 693626B519E5AF620071E21C 16 | 17 | primary 18 | 19 | 20 | 693626C819E5AF620071E21C 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSXTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.matt.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSXTests/MIDI_LE_for_OSXTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDI_LE_for_OSXTests.m 3 | // MIDI LE for OSXTests 4 | // 5 | // Created by Matthias Frick on 08.10.2014. 6 | // Copyright (c) 2014 Matthias Frick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface MIDI_LE_for_OSXTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation MIDI_LE_for_OSXTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Matt Sieren 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.matt.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2014 Matthias Frick. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLE_RGB/BLE_RGB.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_NeoPixel.h" 2 | #include 3 | #include 4 | #include 5 | 6 | // Parameter 1 = number of pixels in strip 7 | // Parameter 2 = pin number (most are valid) 8 | // Parameter 3 = pixel type flags, add together as needed: 9 | // NEO_RGB Pixels are wired for RGB bitstream 10 | // NEO_GRB Pixels are wired for GRB bitstream 11 | // NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels) 12 | // NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip) 13 | Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, 7, NEO_GRB + NEO_KHZ800); 14 | 15 | int R = 0; 16 | int G = 0; 17 | int B = 0; 18 | 19 | void setup() 20 | { 21 | strip.begin(); 22 | strip.show(); // Initialize all pixels to 'off' 23 | ble_begin(); 24 | } 25 | 26 | void loop() 27 | { 28 | if(3 == ble_available()) 29 | { 30 | R = ble_read(); 31 | G = ble_read(); 32 | B = ble_read(); 33 | colorWipe( strip.Color(R, G, B) ); 34 | } 35 | ble_do_events(); 36 | } 37 | 38 | // Fill the dots one after the other with a color 39 | void colorWipe(uint32_t c) 40 | { 41 | for(uint16_t i=0; i= 3 20 | #define PGMIDI_ARC 1 21 | #else 22 | #define PGMIDI_ARC 0 23 | #endif 24 | 25 | //============================================================================== 26 | // arc_cast 27 | 28 | #ifdef __cplusplus 29 | 30 | #if PGMIDI_ARC 31 | 32 | template 33 | inline 34 | OBJC_TYPE *arc_cast(SOURCE_TYPE *source) 35 | { 36 | return (__bridge OBJC_TYPE*)source; 37 | } 38 | 39 | #define PG_RELEASE(a) a = nil; 40 | 41 | #else 42 | 43 | template 44 | inline 45 | OBJC_TYPE *arc_cast(SOURCE_TYPE *source) 46 | { 47 | return (OBJC_TYPE*)source; 48 | } 49 | 50 | #define PG_RELEASE(a) [a release]; a = nil; 51 | 52 | #endif 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/PGMidiAllSources.mm: -------------------------------------------------------------------------------- 1 | // 2 | // PGMidiAllSources.mm 3 | // PGMidi 4 | // 5 | 6 | #import "PGMidiAllSources.h" 7 | 8 | #import "PGMidi.h" 9 | #import "PGArc.h" 10 | 11 | @interface PGMidiAllSources () 12 | @end 13 | 14 | @implementation PGMidiAllSources 15 | 16 | - (void) dealloc 17 | { 18 | self.midi = nil; 19 | #if ! PGMIDI_ARC 20 | [super dealloc]; 21 | #endif 22 | } 23 | 24 | @synthesize midi, delegate; 25 | 26 | - (void) setMidi:(PGMidi *)newMidi 27 | { 28 | midi.delegate = nil; 29 | for (PGMidiSource *source in midi.sources) [source removeDelegate:self]; 30 | 31 | midi = newMidi; 32 | 33 | midi.delegate = self; 34 | for (PGMidiSource *source in midi.sources) [source addDelegate:self]; 35 | } 36 | 37 | #pragma mark PGMidiDelegate 38 | 39 | - (void) midi:(PGMidi*)midi sourceAdded:(PGMidiSource *)source 40 | { 41 | [source addDelegate:self]; 42 | } 43 | 44 | - (void) midi:(PGMidi*)midi sourceRemoved:(PGMidiSource *)source {} 45 | - (void) midi:(PGMidi*)midi destinationAdded:(PGMidiDestination *)destination {} 46 | - (void) midi:(PGMidi*)midi destinationRemoved:(PGMidiDestination *)destination {} 47 | 48 | #pragma mark PGMidiSourceDelegate 49 | 50 | - (void) midiSource:(PGMidiSource*)input midiReceived:(const MIDIPacketList *)packetList 51 | { 52 | [delegate midiSource:input midiReceived:packetList]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/iOSVersionDetection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * iOSVersionDetection.h 3 | * PGMidi 4 | * 5 | */ 6 | 7 | // Adapted from http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html 8 | 9 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0 10 | #define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32 11 | #endif 12 | 13 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_1 14 | #define kCFCoreFoundationVersionNumber_iPhoneOS_4_1 550.38 15 | #endif 16 | 17 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_2 18 | // NOTE: THIS IS NOT THE FINAL NUMBER 19 | // 4.2 is not out of beta yet, so took the beta 1 build number 20 | #define kCFCoreFoundationVersionNumber_iPhoneOS_4_2 550.47 21 | #endif 22 | 23 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 24 | #define IF_IOS4_OR_GREATER(...) \ 25 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \ 26 | { \ 27 | __VA_ARGS__ \ 28 | } 29 | #else 30 | #define IF_IOS4_OR_GREATER(...) \ 31 | if (false) \ 32 | { \ 33 | } 34 | #endif 35 | 36 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40200 37 | #define IF_IOS4_2_OR_GREATER(...) \ 38 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_2) \ 39 | { \ 40 | __VA_ARGS__ \ 41 | } 42 | #else 43 | #define IF_IOS4_2_OR_GREATER(...) \ 44 | if (false) \ 45 | { \ 46 | } 47 | #endif 48 | 49 | #define IF_IOS_HAS_COREMIDI(...) IF_IOS4_2_OR_GREATER(__VA_ARGS__) 50 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/NSData+hexConv.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+hexConv.m 3 | // MIDI LE for OSX 4 | // 5 | // Created by Matthias Frick on 08.10.2014. 6 | // Copyright (c) 2014 Matthias Frick. All rights reserved. 7 | // 8 | 9 | #import "NSData+hexConv.h" 10 | 11 | @implementation NSData (hexConv) 12 | 13 | -(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces 14 | { 15 | const unsigned char* bytes = (const unsigned char*)[self bytes]; 16 | NSUInteger nbBytes = [self length]; 17 | //If spaces is true, insert a space every this many input bytes (twice this many output characters). 18 | static const NSUInteger spaceEveryThisManyBytes = 4UL; 19 | //If spaces is true, insert a line-break instead of a space every this many spaces. 20 | static const NSUInteger lineBreakEveryThisManySpaces = 4UL; 21 | const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces; 22 | NSUInteger strLen = 2*nbBytes + (spaces ? nbBytes/spaceEveryThisManyBytes : 0); 23 | 24 | NSMutableString* hex = [[NSMutableString alloc] initWithCapacity:strLen]; 25 | for(NSUInteger i=0; i Show Package Contents and then navigate to Resources/Java). 20 | 3. Download and import the [USB Host Shield 2.0 Library](https://github.com/felis/USB_Host_Shield_2.0) and the [USBH_MIDI Library](https://github.com/YuuichiAkagawa/USBH_MIDI) into Arduino. 21 | 4. Compile and upload the sketch. 22 | 23 | Known Issues 24 | ============ 25 | 26 | Please check the [README within the root directory](https://github.com/sieren/blidino) for known issues. 27 | 28 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14A386a 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | MIDI LE for OSX 11 | CFBundleIdentifier 12 | com.matt.MIDI-LE-for-OSX 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | MIDI LE for OSX 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 6A317 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 13F26 33 | DTSDKName 34 | macosx10.9 35 | DTXcode 36 | 0600 37 | DTXcodeBuild 38 | 6A317 39 | LSMinimumSystemVersion 40 | 10.10 41 | NSHumanReadableCopyright 42 | Copyright © 2014 Matthias Frick. All rights reserved. 43 | NSMainNibFile 44 | MainMenu 45 | NSPrincipalClass 46 | NSApplication 47 | 48 | 49 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/README.md: -------------------------------------------------------------------------------- 1 | blidino (nRF51288) 2 | ================== 3 | 4 | This project was the first prototype in reverse-engineering MIDI over BLE. 5 | Unfortunately the nRF8001 is too slow for extensive tasks like turning knobs (capped at 0.6-0.9kb/s) 6 | but it will work fine for playing keys. 7 | 8 | Hardware 9 | ======== 10 | 1. [USB Host Shield by Sparkfun](https://www.sparkfun.com/products/9947) 11 | 12 | 2. [RedBearLab Blend Micro](http://redbearlab.com/blendmicro/) 13 | 14 | 15 | Installation 16 | ============ 17 | 1. Set up the board as instructed on the [RedBearLab Blend Micro](http://redbearlab.com/blendmicro/) page. 18 | 2. Replace the ***RBL_services.h, RBL_nRF8001.cpp and RBL_nRF8001.h*** in the */libraries/RBL_nRF8001* subfolder of your Arduino workspace. 19 | 3. Download and import the [USB Host Shield 2.0 Library](https://github.com/felis/USB_Host_Shield_2.0) and the [USBH_MIDI Library](https://github.com/YuuichiAkagawa/USBH_MIDI) into Arduino. You might need to check the pin assignments for SS,INT,MISO,MOSI and CLK within *USBCore.h* and *usbhost.h in the USB Host Shield Library. 20 | 4. Compile and upload the sketch to the device. 21 | 22 | Known Issues 23 | ============ 24 | 25 | • Slow MIDI Output 26 | 27 | The nRF8001 chip is designed for low-performance bluetooth applications, rendering it suitable for low 28 | performance MIDI applications only. Exceeding the bandwidth will result in dropped packets or stuck notes. 29 | 30 | 31 | 32 | The [Wiki](https://github.com/sieren/blidino/wiki) will be updated frequently with information about the ongoing development and discoveries about the BLE-MIDI Specificiation. 33 | 34 | Click the link to see a demo. 35 | 36 | Video -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MIDI LE for OSX 4 | // 5 | // Created by Matthias Frick on 08.10.2014. 6 | // Copyright (c) 2014 Matthias Frick. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "PGMidi.h" 12 | #import "NSData+hexConv.h" 13 | 14 | @interface AppDelegate : NSObject 15 | { 16 | 17 | 18 | NSTimer *pulseTimer; 19 | // NSArrayController *arrayController; 20 | 21 | CBCentralManager *manager; 22 | CBPeripheral *peripheral; 23 | 24 | 25 | 26 | NSString *manufacturer; 27 | 28 | uint16_t heartRate; 29 | 30 | IBOutlet NSButton* connectButton; 31 | BOOL autoConnect; 32 | 33 | // Progress Indicator 34 | IBOutlet NSButton * indicatorButton; 35 | IBOutlet NSProgressIndicator *progressIndicator; 36 | } 37 | 38 | 39 | @property (assign) IBOutlet NSWindow *window; 40 | @property (assign) IBOutlet NSWindow *scanSheet; 41 | @property (assign) IBOutlet NSView *bleView; 42 | @property (assign) IBOutlet NSArrayController *arrayController; 43 | @property (nonatomic, strong) IBOutlet NSTextView *debugView; 44 | @property (assign) uint16_t heartRate; 45 | @property (retain) NSTimer *pulseTimer; 46 | @property (nonatomic, strong) IBOutlet NSMutableArray *heartRateMonitors; 47 | @property (copy) NSString *manufacturer; 48 | @property (copy) NSString *connected; 49 | 50 | - (IBAction) openScanSheet:(id) sender; 51 | - (IBAction) closeScanSheet:(id)sender; 52 | - (IBAction) cancelScanSheet:(id)sender; 53 | - (IBAction) connectButtonPressed:(id)sender; 54 | 55 | - (void) startScan; 56 | - (void) stopScan; 57 | - (BOOL) isLECapableHardware; 58 | 59 | // - (void) pulse; 60 | - (void) updateWithHRMData:(NSData *)data; 61 | 62 | 63 | 64 | 65 | 66 | @end 67 | 68 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | include(CheckCXXCompilerFlag) 4 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 5 | 6 | # Enable ExternalProject CMake module 7 | include(ExternalProject) 8 | 9 | # Download and install GoogleTest 10 | ExternalProject_Add( 11 | gtest 12 | GIT_REPOSITORY https://github.com/google/googletest.git 13 | PREFIX ${CMAKE_CURRENT_BINARY_DIR}/googletest 14 | # Disable install step 15 | INSTALL_COMMAND "" 16 | ) 17 | 18 | # Create a libgtest target to be used as a dependency by test programs 19 | add_library(libgtest IMPORTED STATIC GLOBAL) 20 | add_dependencies(libgtest gtest) 21 | 22 | # Set gtest properties 23 | ExternalProject_Get_Property(gtest source_dir binary_dir) 24 | set_target_properties(libgtest PROPERTIES 25 | "IMPORTED_LOCATION" "${binary_dir}/libgtest.a" 26 | "IMPORTED_LINK_INTERFACE_LIBRARIES" "${CMAKE_THREAD_LIBS_INIT}" 27 | # "INTERFACE_INCLUDE_DIRECTORIES" "${source_dir}/include" 28 | ) 29 | # I couldn't make it work with INTERFACE_INCLUDE_DIRECTORIES 30 | #include_directories("${source_dir}/include") 31 | include_directories(SYSTEM 32 | ${CMAKE_CURRENT_BINARY_DIR}/googletest/src/gtest/googletest/include) 33 | include_directories(SYSTEM 34 | ${CMAKE_CURRENT_BINARY_DIR}/googletest/src/gtest/googlemock/include) 35 | # Set gmock properties 36 | # I couldn't make it work with INTERFACE_INCLUDE_DIRECTORIES 37 | include_directories("${source_dir}/include") 38 | add_library(libgmock IMPORTED STATIC GLOBAL) 39 | 40 | file(GLOB SRCS *.cpp *.h) 41 | add_executable(bletest ${SRCS} unit_tests/tst_BLEParser.cpp) 42 | set_property(TARGET bletest PROPERTY CXX_STANDARD 11) 43 | 44 | set_target_properties(libgmock PROPERTIES IMPORTED_LOCATION 45 | ${CMAKE_CURRENT_BINARY_DIR}/googletest/src/gtest-build/googlemock/libgmock.a) 46 | set_target_properties(libgtest PROPERTIES IMPORTED_LOCATION 47 | ${CMAKE_CURRENT_BINARY_DIR}/googletest/src/gtest-build/googlemock/gtest/libgtest.a) 48 | 49 | target_link_libraries(bletest 50 | libgtest 51 | libgmock 52 | ) 53 | IF(CMAKE_SYSTEM_NAME STREQUAL Linux) 54 | set_target_properties(bletest PROPERTIES COMPILE_FLAGS -pthread LINK_FLAGS -pthread) 55 | ENDIF(CMAKE_SYSTEM_NAME STREQUAL Linux) 56 | install(TARGETS bletest DESTINATION bin) 57 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/RBL_nRF8001.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, 2013 RedBearLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | */ 12 | 13 | #ifndef _RBL_NRF8001_H 14 | #define _RBL_NRF8001_H 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | /* Put the nRF8001 setup in the RAM of the nRF8001.*/ 25 | #include "RBL_services.h" 26 | /* Include the services_lock.h to put the setup in the OTP memory of the nRF8001. 27 | This would mean that the setup cannot be changed once put in. 28 | However this removes the need to do the setup of the nRF8001 on every reset.*/ 29 | 30 | #if defined(BLEND_MICRO) 31 | #define DEFAULT_REQN 6 32 | #define DEFAULT_RDYN 7 33 | #else 34 | #define DEFAULT_REQN 9 35 | #define DEFAULT_RDYN 8 36 | #endif 37 | 38 | void ble_begin(); 39 | void ble_set_name(char *name); 40 | void ble_write(unsigned char data); 41 | void ble_write_bytes(unsigned char *data, unsigned char len); 42 | void ble_do_events(); 43 | int ble_buff_len(); // Added, we need buffer length in sketch 44 | int ble_read(); 45 | unsigned char ble_available(); 46 | unsigned char ble_connected(void); 47 | void ble_set_pins(uint8_t reqn, uint8_t rdyn); 48 | unsigned char ble_busy(); 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/SimpleChat/SimpleChat.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012-2014 RedBearLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | */ 12 | 13 | /* 14 | * Chat 15 | * 16 | * Simple chat sketch, work with the Chat iOS/Android App. 17 | * Type something from the Arduino serial monitor to send 18 | * to the Chat App or vice verse. 19 | * 20 | */ 21 | 22 | //"services.h/spi.h/boards.h" is needed in every new project 23 | #include 24 | #include 25 | #include 26 | 27 | void setup() 28 | { 29 | // Default pins set to 9 and 8 for REQN and RDYN 30 | // Set your REQN and RDYN here before ble_begin() if you need 31 | //ble_set_pins(3, 2); 32 | 33 | // Set your BLE Shield name here, max. length 10 34 | //ble_set_name("My Name"); 35 | 36 | // Init. and start BLE library. 37 | ble_begin(); 38 | 39 | // Enable serial debug 40 | Serial.begin(57600); 41 | } 42 | 43 | unsigned char buf[16] = {0}; 44 | unsigned char len = 0; 45 | 46 | void loop() 47 | { 48 | if ( ble_available() ) 49 | { 50 | while ( ble_available() ) 51 | Serial.write(ble_read()); 52 | 53 | Serial.println(); 54 | } 55 | 56 | if ( Serial.available() ) 57 | { 58 | delay(5); 59 | 60 | while ( Serial.available() ) 61 | ble_write( Serial.read() ); 62 | } 63 | 64 | ble_do_events(); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLE_RGB/Adafruit_NeoPixel.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | This file is part of the Adafruit NeoPixel library. 3 | 4 | NeoPixel is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU Lesser General Public License as 6 | published by the Free Software Foundation, either version 3 of 7 | the License, or (at your option) any later version. 8 | 9 | NeoPixel is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with NeoPixel. If not, see 16 | . 17 | --------------------------------------------------------------------*/ 18 | 19 | #if (ARDUINO >= 100) 20 | #include 21 | #else 22 | #include 23 | #include 24 | #endif 25 | 26 | // 'type' flags for LED pixels (third parameter to constructor): 27 | #define NEO_RGB 0x00 // Wired for RGB data order 28 | #define NEO_GRB 0x01 // Wired for GRB data order 29 | #define NEO_COLMASK 0x01 30 | #define NEO_KHZ400 0x00 // 400 KHz datastream 31 | #define NEO_KHZ800 0x02 // 800 KHz datastream 32 | #define NEO_SPDMASK 0x02 33 | 34 | class Adafruit_NeoPixel { 35 | 36 | public: 37 | 38 | // Constructor: number of LEDs, pin number, LED type 39 | Adafruit_NeoPixel(uint16_t n, uint8_t p=6, uint8_t t=NEO_GRB + NEO_KHZ800); 40 | 41 | void 42 | begin(void), 43 | show(void), 44 | setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), 45 | setPixelColor(uint16_t n, uint32_t c); 46 | uint16_t 47 | numPixels(void); 48 | uint32_t 49 | Color(uint8_t r, uint8_t g, uint8_t b), 50 | getPixelColor(uint16_t n); 51 | 52 | private: 53 | 54 | uint16_t 55 | numLEDs, // Number of RGB LEDs in strip 56 | numBytes; // Size of 'pixels' buffer below 57 | uint8_t 58 | *pixels, // Holds LED color values (3 bytes each) 59 | pin, // Output pin number 60 | pinMask, // Output PORT bitmask 61 | type; // Pixel flags (400 vs 800 KHz, RGB vs GRB color) 62 | volatile uint8_t 63 | *port; // Output PORT register 64 | uint32_t 65 | endTime; // Latch timing reference 66 | 67 | }; 68 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/xcuserdata/sierenmusic.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/HelloWorld/HelloWorld.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012-2014 RedBearLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | */ 12 | 13 | /* 14 | * HelloWorld 15 | * 16 | * HelloWorld sketch, work with the Chat iOS/Android App. 17 | * It will send "Hello World" string to the App every 1 sec. 18 | * 19 | */ 20 | 21 | //"services.h/spi.h/boards.h" is needed in every new project 22 | #include 23 | #include 24 | #include 25 | 26 | void setup() 27 | { 28 | // 29 | // For BLE Shield and Blend: 30 | // Default pins set to 9 and 8 for REQN and RDYN 31 | // Set your REQN and RDYN here before ble_begin() if you need 32 | // 33 | // For Blend Micro: 34 | // Default pins set to 6 and 7 for REQN and RDYN 35 | // So, no need to set for Blend Micro. 36 | // 37 | //ble_set_pins(3, 2); 38 | 39 | // Set your BLE advertising name here, max. length 10 40 | //ble_set_name("My BLE"); 41 | 42 | // Init. and start BLE library. 43 | ble_begin(); 44 | 45 | // Enable serial debug 46 | Serial.begin(57600); 47 | } 48 | 49 | unsigned char buf[16] = {0}; 50 | unsigned char len = 0; 51 | 52 | void loop() 53 | { 54 | if ( ble_connected() ) 55 | { 56 | ble_write('H'); 57 | ble_write('e'); 58 | ble_write('l'); 59 | ble_write('l'); 60 | ble_write('o'); 61 | ble_write(' '); 62 | ble_write('W'); 63 | ble_write('o'); 64 | ble_write('r'); 65 | ble_write('l'); 66 | ble_write('d'); 67 | ble_write('!'); 68 | } 69 | 70 | ble_do_events(); 71 | 72 | if ( ble_available() ) 73 | { 74 | while ( ble_available() ) 75 | { 76 | Serial.write(ble_read()); 77 | } 78 | 79 | Serial.println(); 80 | } 81 | 82 | delay(1000); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.app/Contents/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Base.lproj/MainMenu.nib 8 | 9 | hash 10 | 11 | 66Vr7R2OyX8v5mwLrRCVrbJP3vE= 12 | 13 | optional 14 | 15 | 16 | 17 | files2 18 | 19 | Resources/Base.lproj/MainMenu.nib 20 | 21 | hash 22 | 23 | 66Vr7R2OyX8v5mwLrRCVrbJP3vE= 24 | 25 | optional 26 | 27 | 28 | 29 | rules 30 | 31 | ^Resources/ 32 | 33 | ^Resources/.*\.lproj/ 34 | 35 | optional 36 | 37 | weight 38 | 1000 39 | 40 | ^Resources/.*\.lproj/locversion.plist$ 41 | 42 | omit 43 | 44 | weight 45 | 1100 46 | 47 | ^version.plist$ 48 | 49 | 50 | rules2 51 | 52 | .*\.dSYM($|/) 53 | 54 | weight 55 | 11 56 | 57 | ^(.*/)?\.DS_Store$ 58 | 59 | omit 60 | 61 | weight 62 | 2000 63 | 64 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 65 | 66 | nested 67 | 68 | weight 69 | 10 70 | 71 | ^.* 72 | 73 | ^Info\.plist$ 74 | 75 | omit 76 | 77 | weight 78 | 20 79 | 80 | ^PkgInfo$ 81 | 82 | omit 83 | 84 | weight 85 | 20 86 | 87 | ^Resources/ 88 | 89 | weight 90 | 20 91 | 92 | ^Resources/.*\.lproj/ 93 | 94 | optional 95 | 96 | weight 97 | 1000 98 | 99 | ^Resources/.*\.lproj/locversion.plist$ 100 | 101 | omit 102 | 103 | weight 104 | 1100 105 | 106 | ^[^/]+$ 107 | 108 | nested 109 | 110 | weight 111 | 10 112 | 113 | ^embedded\.provisionprofile$ 114 | 115 | weight 116 | 20 117 | 118 | ^version\.plist$ 119 | 120 | weight 121 | 20 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build 2 | Status](https://travis-ci.org/sieren/blidino.svg?branch=master)](https://travis-ci.org/sieren/blidino) 3 | 4 | blidino 5 | ======= 6 | 7 | Arduino USB-MIDI to MIDI over Bluetooth Project. 8 | This repo hosts sketches and instructions to wirelessly connect USB Class compliant MIDI Devices to iOS / OSX Devices based on the recently released MIDI over Bluetooth protocol by Apple. 9 | 10 | The [BLEParser.h](https://github.com/auxren/blidino/blob/master/nRF51822-BLEMIDI/BLEParser.h) is fully templatized and can be injected with any class that supports the modelled functions (it is based around USBH_MIDI). 11 | 12 | GoogleMock based Unit-Tests ensure its basic feature-functionality (Single MIDI Notes, Running MIDI Status, SysEx). 13 | 14 | Simply execute `./run_unit_tests.sh` and the corresponding CMAKE file should take care of the rest (including fetching GoogleMock and GoogleTest). 15 | 16 | 17 | Projects 18 | ======== 19 | 20 | 21 | [nRF52188](https://github.com/sieren/blidino/tree/master/nRF51822-BLEMIDI) 22 | 23 | This project holds code specifically aimed at the *nRF51288* by RedBearLab. It is designed to work out of the box with the [Circuits@Home USB Host Shield 2.0](http://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-2-0-for-arduino). You can get both boards for a total of around 50$. 24 | 25 | 26 | Requirements 27 | ==================== 28 | 29 | As of 02.2016 this sketch requires the recent RBL SDK (based on S130). To make sure you are using the right firmware, 30 | drop the [bootloader.hex](https://github.com/RedBearLab/nRF51822-Arduino/blob/S130/bootloader/bootloader.hex) to the mBED drive. 31 | Older RBL Boards sold in 2014/2015 may still be using S110, thus updating is recommended if not done already. 32 | 33 | FAQ 34 | ==================== 35 | 36 | • Do I have to use the USB Shield to make this work? 37 | 38 | Certainly not, removing all the USB Routines from the Code and replacing them with other functions is quite easy. 39 | The BLEParser takes in a Receiver Type which can be anything. To see an example of a fake-receiver, see the unit-test code. 40 | 41 | 42 | • Does this work with other Bluetooth boards? 43 | 44 | I suppose, but not out of the box. You'd have to re-implement the nRF SDK specific bluetooth functions for your board. 45 | The only supported boards right now are the ones based on the nRF51288 (and marketed through RBL). 46 | Rewriting this code natively for the nRF SDK is quite easy though and proved an ideal reference in the past. 47 | 48 | 49 | Known Issues 50 | ==================== 51 | 52 | 53 | • USB to BLE Parsing 54 | 55 | MIDI to BLE-MIDI Parsing needs to be rewritten and made testable. This will be added shortly. 56 | 57 | Specifications 58 | ============== 59 | [Apple MIDI over Bluetooth 60 | PDF](https://developer.apple.com/bluetooth/Apple-Bluetooth-Low-Energy-MIDI-Specification.pdf) 61 | 62 | 63 | 64 | Videos 65 | ======= 66 | 67 | Video 70 | 71 | 72 | Video 75 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/SimpleControls/SimpleControls.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, 2013 RedBearLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | */ 12 | 13 | //"services.h/spi.h/boards.h" is needed in every new project 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define DIGITAL_OUT_PIN 2 20 | #define DIGITAL_IN_PIN A4 21 | #define PWM_PIN 3 22 | #define SERVO_PIN 5 23 | #define ANALOG_IN_PIN A5 24 | 25 | Servo myservo; 26 | 27 | void setup() 28 | { 29 | // Default pins set to 9 and 8 for REQN and RDYN 30 | // Set your REQN and RDYN here before ble_begin() if you need 31 | //ble_set_pins(3, 2); 32 | 33 | // Set your BLE Shield name here, max. length 10 34 | //ble_set_name("My Name"); 35 | 36 | // Init. and start BLE library. 37 | ble_begin(); 38 | 39 | // Enable serial debug 40 | Serial.begin(57600); 41 | 42 | pinMode(DIGITAL_OUT_PIN, OUTPUT); 43 | pinMode(DIGITAL_IN_PIN, INPUT); 44 | 45 | // Default to internally pull high, change it if you need 46 | digitalWrite(DIGITAL_IN_PIN, HIGH); 47 | //digitalWrite(DIGITAL_IN_PIN, LOW); 48 | 49 | myservo.attach(SERVO_PIN); 50 | } 51 | 52 | void loop() 53 | { 54 | static boolean analog_enabled = false; 55 | static byte old_state = LOW; 56 | 57 | // If data is ready 58 | while(ble_available()) 59 | { 60 | // read out command and data 61 | byte data0 = ble_read(); 62 | byte data1 = ble_read(); 63 | byte data2 = ble_read(); 64 | 65 | if (data0 == 0x01) // Command is to control digital out pin 66 | { 67 | if (data1 == 0x01) 68 | digitalWrite(DIGITAL_OUT_PIN, HIGH); 69 | else 70 | digitalWrite(DIGITAL_OUT_PIN, LOW); 71 | } 72 | else if (data0 == 0xA0) // Command is to enable analog in reading 73 | { 74 | if (data1 == 0x01) 75 | analog_enabled = true; 76 | else 77 | analog_enabled = false; 78 | } 79 | else if (data0 == 0x02) // Command is to control PWM pin 80 | { 81 | analogWrite(PWM_PIN, data1); 82 | } 83 | else if (data0 == 0x03) // Command is to control Servo pin 84 | { 85 | myservo.write(data1); 86 | } 87 | else if (data0 == 0x04) 88 | { 89 | analog_enabled = false; 90 | myservo.write(0); 91 | analogWrite(PWM_PIN, 0); 92 | digitalWrite(DIGITAL_OUT_PIN, LOW); 93 | } 94 | } 95 | 96 | if (analog_enabled) // if analog reading enabled 97 | { 98 | // Read and send out 99 | uint16_t value = analogRead(ANALOG_IN_PIN); 100 | ble_write(0x0B); 101 | ble_write(value >> 8); 102 | ble_write(value); 103 | } 104 | 105 | // If digital in changes, report the state 106 | if (digitalRead(DIGITAL_IN_PIN) != old_state) 107 | { 108 | old_state = digitalRead(DIGITAL_IN_PIN); 109 | 110 | if (digitalRead(DIGITAL_IN_PIN) == HIGH) 111 | { 112 | ble_write(0x0A); 113 | ble_write(0x01); 114 | ble_write(0x00); 115 | } 116 | else 117 | { 118 | ble_write(0x0A); 119 | ble_write(0x00); 120 | ble_write(0x00); 121 | } 122 | } 123 | 124 | if (!ble_connected()) 125 | { 126 | analog_enabled = false; 127 | digitalWrite(DIGITAL_OUT_PIN, LOW); 128 | } 129 | 130 | // Allow BLE Shield to send/receive data 131 | ble_do_events(); 132 | } 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /unit_tests/tst_BLEParser.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "gtest/gtest.h" 4 | #include "gmock/gmock.h" 5 | #include "../nRF51822-BLEMIDI/BLEParser.h" 6 | #include 7 | #include 8 | 9 | typedef uint8_t byte; 10 | 11 | int main(int argc, char **argv) 12 | { 13 | ::testing::InitGoogleTest(&argc, argv); 14 | int ret = RUN_ALL_TESTS(); 15 | return ret; 16 | } 17 | 18 | // Mocking used USBMidi_H Functions 19 | class USBMidiMock 20 | { 21 | public: 22 | USBMidiMock() = default; 23 | // Ommiting byte nCable=0 overload 24 | MOCK_METHOD3(SendSysEx, void( 25 | uint8_t *dataptr, 26 | unsigned int datasize, 27 | byte nCable)); 28 | 29 | // everything GEQ 3 is ignored by USBH_MIDI 30 | MOCK_METHOD2(SendData, void( 31 | (const uint8_t (&dataptr)[3], byte nCable))); 32 | }; 33 | 34 | struct Fixture 35 | { 36 | Fixture() 37 | { 38 | mParser.setUSBMidiHandle(&mUSBMock); 39 | } 40 | 41 | void parseDataArray(uint8_t *data, uint8_t length) 42 | { 43 | for (int i = 1; i < length; i++) 44 | { 45 | mParser.parseMidiEvent(data[0], data[i]); 46 | } 47 | } 48 | 49 | void parseMidiEvent(uint8_t header, uint8_t event) 50 | { 51 | mParser.parseMidiEvent(header, event); 52 | } 53 | 54 | USBMidiMock& getMock() 55 | { 56 | return mUSBMock; 57 | } 58 | 59 | mfk::midi::BLEMIDIParser<256, USBMidiMock> mParser; 60 | ::testing::NiceMock mUSBMock; 61 | }; 62 | 63 | 64 | TEST(BLEReturnMIDIData, SingleNote) 65 | { 66 | using testing::ElementsAreArray; 67 | using testing::_; 68 | Fixture f; 69 | static uint8_t testdata[5] = 70 | { 0x80, 0x80, 0x90, 0x80, 0x45 }; 71 | static uint8_t midiResult[3] = 72 | { 0x90, 0x80, 0x45 }; 73 | 74 | EXPECT_CALL(f.getMock(), SendData(ElementsAreArray(midiResult),0)); 75 | f.parseDataArray(testdata, 5); 76 | } 77 | 78 | 79 | TEST(BLEReturnRunningMIDIData, TwoNotes) 80 | { 81 | using testing::ElementsAreArray; 82 | using testing::_; 83 | Fixture f; 84 | static uint8_t testdata[8] = 85 | { 0x80, 0x80, 0x90, 0x45, 0x45, 0x80, 0x22, 0x45 }; 86 | static uint8_t midiResult1[3] = 87 | { 0x90, 0x45, 0x45 }; 88 | static uint8_t midiResult2[3] = 89 | { 0x90, 0x22, 0x45 }; 90 | 91 | 92 | 93 | EXPECT_CALL(f.getMock(), SendData(ElementsAreArray(midiResult1),0)); 94 | EXPECT_CALL(f.getMock(), SendData(ElementsAreArray(midiResult2),0)); 95 | f.parseDataArray(testdata, 8); 96 | } 97 | 98 | 99 | TEST(BLEReturnSysExData, SingleData) 100 | { 101 | using testing::ElementsAreArray; 102 | using testing::_; 103 | using testing::Args; 104 | Fixture f; 105 | static uint8_t testdata[8] = 106 | { 0x80, 0x80, 0xf0, 0x90, 0x80, 0x45, 0x88, 0xf7}; 107 | static uint8_t sysExResult[5] = 108 | { 0xf0, 0x90, 0x80, 0x45, 0xf7 }; 109 | 110 | EXPECT_CALL(f.getMock(), SendSysEx(_,_,0)).With(Args<0,1>(ElementsAreArray(sysExResult))); 111 | f.parseDataArray(testdata, 8); 112 | } 113 | 114 | 115 | TEST(BLEReturnLongSysExData, MultipleData) 116 | { 117 | using testing::ElementsAreArray; 118 | using testing::_; 119 | using testing::Args; 120 | Fixture f; 121 | static uint8_t longSysEx1[9] = 122 | { 123 | 0x80, 0x80, 0xf0, 0x47, 0x7f, 0x15, 0x5c, 0x00, 0x01 124 | }; 125 | static uint8_t longSysEx2[9] = 126 | { 127 | 0x80, 0x21, 0x46, 0x47, 0x7f, 0x15, 0x5c, 0x80, 0xf7 128 | }; 129 | 130 | static uint8_t sysExResult[14] = 131 | { 0xf0, 0x47, 0x7f, 0x15, 0x5c, 0x00, 0x01, 0x21, 0x46, 132 | 0x47, 0x7f, 0x15, 0x5c, 0xf7 133 | }; 134 | 135 | EXPECT_CALL(f.getMock(), SendSysEx(_,_,0)).With(Args<0,1>(ElementsAreArray(sysExResult))); 136 | f.parseDataArray(longSysEx1, 9); 137 | f.parseDataArray(longSysEx2, 9); 138 | } 139 | 140 | TEST(BLEReturnSysExRecoveryBuffer, ReturnTwice) 141 | { 142 | using testing::ElementsAreArray; 143 | using testing::_; 144 | using testing::Args; 145 | Fixture f; 146 | static uint8_t longSysEx1[9] = 147 | { 148 | 0x80, 0x80, 0xf0, 0x47, 0x7f, 0x15, 0x5c, 0x00, 0x01 149 | }; 150 | static uint8_t longSysEx2[9] = 151 | { 152 | 0x80, 0x21, 0x46, 0x47, 0x7f, 0x15, 0x5c, 0xf7, 0xf7 153 | }; 154 | 155 | static uint8_t sysExFalseResult[13] = 156 | { 0xf0, 0x47, 0x7f, 0x15, 0x5c, 0x00, 0x01, 0x21, 0x46, 157 | 0x47, 0x7f, 0x15, 0xf7 158 | }; 159 | 160 | static uint8_t sysExRecoveryResult[14] = 161 | { 0xf0, 0x47, 0x7f, 0x15, 0x5c, 0x00, 0x01, 0x21, 0x46, 162 | 0x47, 0x7f, 0x15, 0x5c, 0xf7 163 | }; 164 | 165 | EXPECT_CALL(f.getMock(), SendSysEx(_,_,0)).With(Args<0,1>( 166 | ElementsAreArray(sysExFalseResult))).Times(1); 167 | EXPECT_CALL(f.getMock(), SendSysEx(_,_,0)).With(Args<0,1>( 168 | ElementsAreArray(sysExRecoveryResult))).Times(1); 169 | 170 | f.parseDataArray(longSysEx1, 9); 171 | f.parseDataArray(longSysEx2, 9); 172 | } 173 | 174 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX.xcodeproj/xcuserdata/sierenmusic.xcuserdatad/xcschemes/MIDI LE for OSX.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /debug-utils/MIDI LE for OSX/MIDI LE for OSX/PGMidi/PGMidi.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGMidi.h 3 | // PGMidi 4 | // 5 | 6 | 7 | #import 8 | #import 9 | #import "PGArc.h" 10 | 11 | @class PGMidi; 12 | @class PGMidiSource; 13 | 14 | extern NSString * const PGMidiSourceAddedNotification; 15 | extern NSString * const PGMidiSourceRemovedNotification; 16 | extern NSString * const PGMidiDestinationAddedNotification; 17 | extern NSString * const PGMidiDestinationRemovedNotification; 18 | 19 | extern NSString * const PGMidiConnectionKey; 20 | 21 | 22 | /// Represents a source/destination for MIDI data 23 | /// 24 | /// @see PGMidiSource 25 | /// @see PGMidiDestination 26 | @interface PGMidiConnection : NSObject 27 | { 28 | PGMidi *midi; 29 | MIDIEndpointRef endpoint; 30 | NSString *name; 31 | BOOL isNetworkSession; 32 | } 33 | @property (nonatomic,readonly) PGMidi *midi; 34 | @property (nonatomic,readonly) MIDIEndpointRef endpoint; 35 | @property (nonatomic,readonly) NSString *name; 36 | @property (nonatomic,readonly) BOOL isNetworkSession; 37 | @end 38 | 39 | 40 | /// Delegate protocol for PGMidiSource class. 41 | /// Adopt this protocol in your object to receive MIDI events 42 | /// 43 | /// IMPORTANT NOTE: 44 | /// MIDI input is received from a high priority background thread 45 | /// 46 | /// @see PGMidiSource 47 | @protocol PGMidiSourceDelegate 48 | 49 | // Raised on main run loop 50 | /// NOTE: Raised on high-priority background thread. 51 | /// 52 | /// To do anything UI-ish, you must forward the event to the main runloop 53 | /// (e.g. use performSelectorOnMainThread:withObject:waitUntilDone:) 54 | /// 55 | /// Be careful about autoreleasing objects here - there is no NSAutoReleasePool. 56 | /// 57 | /// Handle the data like this: 58 | /// 59 | /// // for some function HandlePacketData(Byte *data, UInt16 length) 60 | /// const MIDIPacket *packet = &packetList->packet[0]; 61 | /// for (int i = 0; i < packetList->numPackets; ++i) 62 | /// { 63 | /// HandlePacketData(packet->data, packet->length); 64 | /// packet = MIDIPacketNext(packet); 65 | /// } 66 | - (void) midiSource:(PGMidiSource*)input midiReceived:(const MIDIPacketList *)packetList; 67 | 68 | @end 69 | 70 | /// Represents a source of MIDI data identified by CoreMIDI 71 | /// 72 | /// @see PGMidiSourceDelegate 73 | @interface PGMidiSource : PGMidiConnection 74 | - (void)addDelegate:(id)delegate; 75 | - (void)removeDelegate:(id)delegate; 76 | 77 | @property (strong, nonatomic, readonly) NSArray *delegates; 78 | @end 79 | 80 | //============================================================================== 81 | 82 | /// Represents a destination for MIDI data identified by CoreMIDI 83 | @interface PGMidiDestination : PGMidiConnection 84 | { 85 | } 86 | - (void) flushOutput; 87 | - (void) sendBytes:(const UInt8*)bytes size:(UInt32)size; 88 | - (void) sendPacketList:(MIDIPacketList *)packetList; 89 | @end 90 | 91 | //============================================================================== 92 | 93 | /// Delegate protocol for PGMidi class. 94 | /// 95 | /// @see PGMidi 96 | @protocol PGMidiDelegate 97 | - (void) midi:(PGMidi*)midi sourceAdded:(PGMidiSource *)source; 98 | - (void) midi:(PGMidi*)midi sourceRemoved:(PGMidiSource *)source; 99 | - (void) midi:(PGMidi*)midi destinationAdded:(PGMidiDestination *)destination; 100 | - (void) midi:(PGMidi*)midi destinationRemoved:(PGMidiDestination *)destination; 101 | @end 102 | 103 | /// Class for receiving MIDI input from any MIDI device. 104 | /// 105 | /// If you intend your app to support iOS 3.x which does not have CoreMIDI 106 | /// support, weak link to the CoreMIDI framework, and only create a 107 | /// PGMidi object if you are running the right version of iOS. 108 | /// 109 | /// @see PGMidiDelegate 110 | @interface PGMidi : NSObject 111 | { 112 | MIDIClientRef client; 113 | MIDIPortRef outputPort; 114 | MIDIPortRef inputPort; 115 | NSString *virtualEndpointName; 116 | MIDIEndpointRef virtualSourceEndpoint; 117 | MIDIEndpointRef virtualDestinationEndpoint; 118 | PGMidiSource *virtualDestinationSource; 119 | PGMidiDestination *virtualSourceDestination; 120 | NSMutableArray *sources, *destinations; 121 | } 122 | 123 | + (BOOL)midiAvailable; 124 | 125 | @property (nonatomic,assign) id delegate; 126 | @property (nonatomic,readonly) NSUInteger numberOfConnections; 127 | @property (nonatomic,readonly) NSMutableArray *sources; 128 | @property (nonatomic,readonly) NSMutableArray *destinations; 129 | @property (nonatomic,readonly) PGMidiSource *virtualDestinationSource; 130 | @property (nonatomic,readonly) PGMidiDestination *virtualSourceDestination; 131 | @property (nonatomic,retain) NSString *virtualEndpointName; 132 | @property (nonatomic,assign) BOOL networkEnabled; 133 | @property (nonatomic,assign) BOOL virtualSourceEnabled; 134 | @property (nonatomic,assign) BOOL virtualDestinationEnabled; 135 | 136 | /// Send a MIDI byte stream to every connected MIDI port 137 | - (void) sendBytes:(const UInt8*)bytes size:(UInt32)size; 138 | - (void) sendPacketList:(const MIDIPacketList *)packetList; 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/RBL_services_OLD.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. 2 | * 3 | * The information contained herein is property of Nordic Semiconductor ASA. 4 | * Terms and conditions of usage are described in detail in NORDIC 5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 6 | * 7 | * Licensees are granted free, non-transferable use of the information. NO 8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 9 | * the file. 10 | */ 11 | 12 | /** 13 | * This file is autogenerated by nRFgo Studio 1.14.1.2369 14 | */ 15 | 16 | #ifndef SETUP_MESSAGES_H__ 17 | #define SETUP_MESSAGES_H__ 18 | 19 | #include "hal_platform.h" 20 | #include "aci.h" 21 | #define PIPE_GAP_DEVICE_NAME_SET 1 22 | #define PIPE_UART_OVER_BTLE_UART_RX_RX 2 23 | #define PIPE_UART_OVER_BTLE_UART_TX_TX 3 24 | #define PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET 4 25 | 26 | #define NUMBER_OF_PIPES 4 27 | 28 | #define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ 29 | {ACI_STORE_LOCAL, ACI_SET}, \ 30 | {ACI_STORE_LOCAL, ACI_RX}, \ 31 | {ACI_STORE_LOCAL, ACI_TX}, \ 32 | {ACI_STORE_LOCAL, ACI_SET}, \ 33 | } 34 | 35 | #define GAP_PPCP_MAX_CONN_INT 0x12 /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ 36 | #define GAP_PPCP_MIN_CONN_INT 0x6 /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific maximum*/ 37 | #define GAP_PPCP_SLAVE_LATENCY 0 38 | #define GAP_PPCP_CONN_TIMEOUT 0xa /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ 39 | 40 | #define NB_SETUP_MESSAGES 21 41 | #define SETUP_MESSAGES_CONTENT {\ 42 | {0x00,\ 43 | {\ 44 | 0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xd7,\ 45 | },\ 46 | },\ 47 | {0x00,\ 48 | {\ 49 | 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x01,0x01,0x00,0x00,0x06,0x00,0x00,\ 50 | 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 51 | },\ 52 | },\ 53 | {0x00,\ 54 | {\ 55 | 0x1f,0x06,0x10,0x1c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 56 | 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x03,0x90,0x01,0xff,\ 57 | },\ 58 | },\ 59 | {0x00,\ 60 | {\ 61 | 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,\ 62 | 0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,\ 63 | },\ 64 | },\ 65 | {0x00,\ 66 | {\ 67 | 0x05,0x06,0x10,0x54,0x00,0x00,\ 68 | },\ 69 | },\ 70 | {0x00,\ 71 | {\ 72 | 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ 73 | 0x02,0x28,0x03,0x01,0x0e,0x03,0x00,0x00,0x2a,0x04,0x14,0x0a,\ 74 | },\ 75 | },\ 76 | {0x00,\ 77 | {\ 78 | 0x1f,0x06,0x20,0x1c,0x0a,0x00,0x03,0x2a,0x00,0x01,0x42,0x4c,0x45,0x20,0x53,0x68,0x69,0x65,0x6c,0x64,\ 79 | 0x04,0x04,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,\ 80 | },\ 81 | },\ 82 | {0x00,\ 83 | {\ 84 | 0x1f,0x06,0x20,0x38,0x01,0x2a,0x06,0x04,0x03,0x02,0x00,0x05,0x2a,0x01,0x01,0x00,0x00,0x04,0x04,0x05,\ 85 | 0x05,0x00,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,\ 86 | },\ 87 | },\ 88 | {0x00,\ 89 | {\ 90 | 0x1f,0x06,0x20,0x54,0x04,0x09,0x08,0x00,0x07,0x2a,0x04,0x01,0x06,0x00,0x12,0x00,0x00,0x00,0x0a,0x00,\ 91 | 0x04,0x04,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,\ 92 | },\ 93 | },\ 94 | {0x00,\ 95 | {\ 96 | 0x1f,0x06,0x20,0x70,0x04,0x10,0x10,0x00,0x09,0x28,0x00,0x01,0x1e,0x94,0x8d,0xf1,0x48,0x31,0x94,0xba,\ 97 | 0x75,0x4c,0x3e,0x50,0x00,0x00,0x3d,0x71,0x04,0x04,0x13,0x13,\ 98 | },\ 99 | },\ 100 | {0x00,\ 101 | {\ 102 | 0x1f,0x06,0x20,0x8c,0x00,0x0a,0x28,0x03,0x01,0x04,0x0b,0x00,0x1e,0x94,0x8d,0xf1,0x48,0x31,0x94,0xba,\ 103 | 0x75,0x4c,0x3e,0x50,0x03,0x00,0x3d,0x71,0x44,0x10,0x14,0x00,\ 104 | },\ 105 | },\ 106 | {0x00,\ 107 | {\ 108 | 0x1f,0x06,0x20,0xa8,0x00,0x0b,0x00,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 109 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x13,\ 110 | },\ 111 | },\ 112 | {0x00,\ 113 | {\ 114 | 0x1f,0x06,0x20,0xc4,0x13,0x00,0x0c,0x28,0x03,0x01,0x10,0x0d,0x00,0x1e,0x94,0x8d,0xf1,0x48,0x31,0x94,\ 115 | 0xba,0x75,0x4c,0x3e,0x50,0x02,0x00,0x3d,0x71,0x14,0x00,0x14,\ 116 | },\ 117 | },\ 118 | {0x00,\ 119 | {\ 120 | 0x1f,0x06,0x20,0xe0,0x00,0x00,0x0d,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 121 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x14,\ 122 | },\ 123 | },\ 124 | {0x00,\ 125 | {\ 126 | 0x1f,0x06,0x20,0xfc,0x03,0x02,0x00,0x0e,0x29,0x02,0x01,0x00,0x00,0x04,0x04,0x02,0x02,0x00,0x0f,0x28,\ 127 | 0x00,0x01,0x0a,0x18,0x04,0x04,0x05,0x05,0x00,0x10,0x28,0x03,\ 128 | },\ 129 | },\ 130 | {0x00,\ 131 | {\ 132 | 0x1c,0x06,0x21,0x18,0x01,0x02,0x11,0x00,0x27,0x2a,0x04,0x04,0x09,0x01,0x00,0x11,0x2a,0x27,0x01,0x0a,\ 133 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 134 | },\ 135 | },\ 136 | {0x00,\ 137 | {\ 138 | 0x1f,0x06,0x40,0x00,0x2a,0x00,0x01,0x00,0x80,0x04,0x00,0x03,0x00,0x00,0x00,0x03,0x02,0x00,0x08,0x04,\ 139 | 0x00,0x0b,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x04,0x00,0x0d,\ 140 | },\ 141 | },\ 142 | {0x00,\ 143 | {\ 144 | 0x0f,0x06,0x40,0x1c,0x00,0x0e,0x2a,0x27,0x01,0x00,0x80,0x04,0x00,0x11,0x00,0x00,\ 145 | },\ 146 | },\ 147 | {0x00,\ 148 | {\ 149 | 0x13,0x06,0x50,0x00,0x1e,0x94,0x8d,0xf1,0x48,0x31,0x94,0xba,0x75,0x4c,0x3e,0x50,0x00,0x00,0x3d,0x71,\ 150 | },\ 151 | },\ 152 | {0x00,\ 153 | {\ 154 | 0x0f,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 155 | },\ 156 | },\ 157 | {0x00,\ 158 | {\ 159 | 0x06,0x06,0xf0,0x00,0x03,0x6a,0x44,\ 160 | },\ 161 | },\ 162 | } 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/RBL_services.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * - Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * - The name of Nordic Semiconductor ASA may not be used to endorse or promote 16 | * products derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /** 31 | * This file is autogenerated by nRFgo Studio 1.16.1.3119 32 | */ 33 | 34 | #ifndef SETUP_MESSAGES_H__ 35 | #define SETUP_MESSAGES_H__ 36 | 37 | #include 38 | #include 39 | #include 40 | #define PIPE_GAP_DEVICE_NAME_SET 3 41 | #define PIPE_UART_OVER_BTLE_UART_RX_RX 2 42 | #define PIPE_UART_OVER_BTLE_UART_TX_TX 1 43 | #define PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET 4 44 | 45 | 46 | 47 | #define SETUP_ID 0 48 | #define SETUP_FORMAT 3 /** nRF8001 D */ 49 | #define ACI_DYNAMIC_DATA_SIZE 135 50 | 51 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: TX */ 52 | #define PIPE_BLIDINO_MIDI_SERVICE_TX 1 53 | #define PIPE_BLIDINO_MIDI_SERVICE_TX_MAX_SIZE 20 54 | 55 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: RX */ 56 | #define PIPE_BLIDINO_MIDI_SERVICE_RX 2 57 | #define PIPE_BLIDINO_MIDI_SERVICE_RX_MAX_SIZE 20 58 | 59 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: SET */ 60 | #define PIPE_BLIDINO_MIDI_SERVICE_SET 3 61 | #define PIPE_BLIDINO_MIDI_SERVICE_SET_MAX_SIZE 20 62 | 63 | 64 | #define NUMBER_OF_PIPES 3 65 | 66 | #define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ 67 | {ACI_STORE_LOCAL, ACI_TX}, \ 68 | {ACI_STORE_LOCAL, ACI_RX}, \ 69 | {ACI_STORE_LOCAL, ACI_SET}, \ 70 | } 71 | 72 | #define GAP_PPCP_MAX_CONN_INT 0xc /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ 73 | #define GAP_PPCP_MIN_CONN_INT 0x6 /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ 74 | #define GAP_PPCP_SLAVE_LATENCY 0 75 | #define GAP_PPCP_CONN_TIMEOUT 0xffff /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ 76 | 77 | #define NB_SETUP_MESSAGES 18 78 | #define SETUP_MESSAGES_CONTENT {\ 79 | {0x00,\ 80 | {\ 81 | 0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xfe,\ 82 | },\ 83 | },\ 84 | {0x00,\ 85 | {\ 86 | 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x01,0x01,0x00,0x00,0x06,0x00,0x00,\ 87 | 0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,\ 88 | },\ 89 | },\ 90 | {0x00,\ 91 | {\ 92 | 0x1f,0x06,0x10,0x1c,0x5a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 93 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x03,0x90,0x02,0xff,\ 94 | },\ 95 | },\ 96 | {0x00,\ 97 | {\ 98 | 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,\ 99 | 0x00,0x14,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,\ 100 | },\ 101 | },\ 102 | {0x00,\ 103 | {\ 104 | 0x05,0x06,0x10,0x54,0x00,0x00,\ 105 | },\ 106 | },\ 107 | {0x00,\ 108 | {\ 109 | 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ 110 | 0x02,0x28,0x03,0x01,0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14,\ 111 | },\ 112 | },\ 113 | {0x00,\ 114 | {\ 115 | 0x1f,0x06,0x20,0x1c,0x07,0x00,0x03,0x2a,0x00,0x01,0x42,0x4c,0x49,0x44,0x49,0x6e,0x6f,0x65,0x6d,0x69,\ 116 | 0x2e,0x63,0x6f,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,\ 117 | },\ 118 | },\ 119 | {0x00,\ 120 | {\ 121 | 0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,\ 122 | 0x00,0x05,0x2a,0x01,0x01,0x00,0x00,0x04,0x04,0x05,0x05,0x00,\ 123 | },\ 124 | },\ 125 | {0x00,\ 126 | {\ 127 | 0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,\ 128 | 0x04,0x01,0x06,0x00,0x0c,0x00,0x00,0x00,0xff,0xff,0x04,0x04,\ 129 | },\ 130 | },\ 131 | {0x00,\ 132 | {\ 133 | 0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x10,0x10,0x00,0x09,0x28,\ 134 | 0x00,0x01,0x00,0xc7,0xc4,0x4e,0xe3,0x6c,0x51,0xa7,0x33,0x4b,\ 135 | },\ 136 | },\ 137 | {0x00,\ 138 | {\ 139 | 0x1f,0x06,0x20,0x8c,0xe8,0xed,0x5a,0x0e,0xb8,0x03,0x04,0x04,0x13,0x13,0x00,0x0a,0x28,0x03,0x01,0x16,\ 140 | 0x0b,0x00,0xf3,0x6b,0x10,0x9d,0x66,0xf2,0xa9,0xa1,0x12,0x41,\ 141 | },\ 142 | },\ 143 | {0x00,\ 144 | {\ 145 | 0x1f,0x06,0x20,0xa8,0x68,0x38,0xdb,0xe5,0x72,0x77,0x54,0x14,0x14,0x00,0x00,0x0b,0xe5,0xdb,0x03,0x00,\ 146 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 147 | },\ 148 | },\ 149 | {0x00,\ 150 | {\ 151 | 0x16,0x06,0x20,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x14,0x03,0x02,0x00,0x0c,0x29,0x02,0x01,\ 152 | 0x00,0x00,0x00,\ 153 | },\ 154 | },\ 155 | {0x00,\ 156 | {\ 157 | 0x0d,0x06,0x40,0x00,0xe5,0xdb,0x03,0x00,0x8a,0x04,0x00,0x0b,0x00,0x0c,\ 158 | },\ 159 | },\ 160 | {0x00,\ 161 | {\ 162 | 0x1f,0x06,0x50,0x00,0x00,0xc7,0xc4,0x4e,0xe3,0x6c,0x51,0xa7,0x33,0x4b,0xe8,0xed,0x00,0x00,0xb8,0x03,\ 163 | 0xf3,0x6b,0x10,0x9d,0x66,0xf2,0xa9,0xa1,0x12,0x41,0x68,0x38,\ 164 | },\ 165 | },\ 166 | {0x00,\ 167 | {\ 168 | 0x07,0x06,0x50,0x1c,0x00,0x00,0x72,0x77,\ 169 | },\ 170 | },\ 171 | {0x00,\ 172 | {\ 173 | 0x06,0x06,0x60,0x00,0x00,0x00,0x00,\ 174 | },\ 175 | },\ 176 | {0x00,\ 177 | {\ 178 | 0x06,0x06,0xf0,0x00,0x03,0x84,0xcb,\ 179 | },\ 180 | },\ 181 | } 182 | 183 | #endif -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_services.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * - Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * - The name of Nordic Semiconductor ASA may not be used to endorse or promote 16 | * products derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /** 31 | * This file is autogenerated by nRFgo Studio 1.16.1.3119 32 | */ 33 | 34 | #ifndef SETUP_MESSAGES_H__ 35 | #define SETUP_MESSAGES_H__ 36 | 37 | #include 38 | #include 39 | #include 40 | #define PIPE_GAP_DEVICE_NAME_SET 3 41 | #define PIPE_UART_OVER_BTLE_UART_RX_RX 2 42 | #define PIPE_UART_OVER_BTLE_UART_TX_TX 1 43 | #define PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET 4 44 | 45 | 46 | 47 | #define SETUP_ID 0 48 | #define SETUP_FORMAT 3 /** nRF8001 D */ 49 | #define ACI_DYNAMIC_DATA_SIZE 135 50 | 51 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: TX */ 52 | #define PIPE_BLIDINO_MIDI_SERVICE_TX 1 53 | #define PIPE_BLIDINO_MIDI_SERVICE_TX_MAX_SIZE 20 54 | 55 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: RX */ 56 | #define PIPE_BLIDINO_MIDI_SERVICE_RX 2 57 | #define PIPE_BLIDINO_MIDI_SERVICE_RX_MAX_SIZE 20 58 | 59 | /* Service: BLIDino - Characteristic: MIDI Service - Pipe: SET */ 60 | #define PIPE_BLIDINO_MIDI_SERVICE_SET 3 61 | #define PIPE_BLIDINO_MIDI_SERVICE_SET_MAX_SIZE 20 62 | 63 | 64 | #define NUMBER_OF_PIPES 3 65 | 66 | #define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ 67 | {ACI_STORE_LOCAL, ACI_TX}, \ 68 | {ACI_STORE_LOCAL, ACI_RX}, \ 69 | {ACI_STORE_LOCAL, ACI_SET}, \ 70 | } 71 | 72 | #define GAP_PPCP_MAX_CONN_INT 0xc /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ 73 | #define GAP_PPCP_MIN_CONN_INT 0x6 /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ 74 | #define GAP_PPCP_SLAVE_LATENCY 0 75 | #define GAP_PPCP_CONN_TIMEOUT 0xffff /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ 76 | 77 | #define NB_SETUP_MESSAGES 18 78 | #define SETUP_MESSAGES_CONTENT {\ 79 | {0x00,\ 80 | {\ 81 | 0x07,0x06,0x00,0x00,0x03,0x02,0x41,0xfe,\ 82 | },\ 83 | },\ 84 | {0x00,\ 85 | {\ 86 | 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x01,0x01,0x00,0x00,0x06,0x00,0x00,\ 87 | 0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,\ 88 | },\ 89 | },\ 90 | {0x00,\ 91 | {\ 92 | 0x1f,0x06,0x10,0x1c,0x5a,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 93 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x03,0x90,0x02,0xff,\ 94 | },\ 95 | },\ 96 | {0x00,\ 97 | {\ 98 | 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x00,\ 99 | 0x00,0x14,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,\ 100 | },\ 101 | },\ 102 | {0x00,\ 103 | {\ 104 | 0x05,0x06,0x10,0x54,0x00,0x00,\ 105 | },\ 106 | },\ 107 | {0x00,\ 108 | {\ 109 | 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ 110 | 0x02,0x28,0x03,0x01,0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14,\ 111 | },\ 112 | },\ 113 | {0x00,\ 114 | {\ 115 | 0x1f,0x06,0x20,0x1c,0x07,0x00,0x03,0x2a,0x00,0x01,0x42,0x4c,0x49,0x44,0x49,0x6e,0x6f,0x65,0x6d,0x69,\ 116 | 0x2e,0x63,0x6f,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,\ 117 | },\ 118 | },\ 119 | {0x00,\ 120 | {\ 121 | 0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,\ 122 | 0x00,0x05,0x2a,0x01,0x01,0x00,0x00,0x04,0x04,0x05,0x05,0x00,\ 123 | },\ 124 | },\ 125 | {0x00,\ 126 | {\ 127 | 0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,\ 128 | 0x04,0x01,0x06,0x00,0x0c,0x00,0x00,0x00,0xff,0xff,0x04,0x04,\ 129 | },\ 130 | },\ 131 | {0x00,\ 132 | {\ 133 | 0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x10,0x10,0x00,0x09,0x28,\ 134 | 0x00,0x01,0x00,0xc7,0xc4,0x4e,0xe3,0x6c,0x51,0xa7,0x33,0x4b,\ 135 | },\ 136 | },\ 137 | {0x00,\ 138 | {\ 139 | 0x1f,0x06,0x20,0x8c,0xe8,0xed,0x5a,0x0e,0xb8,0x03,0x04,0x04,0x13,0x13,0x00,0x0a,0x28,0x03,0x01,0x16,\ 140 | 0x0b,0x00,0xf3,0x6b,0x10,0x9d,0x66,0xf2,0xa9,0xa1,0x12,0x41,\ 141 | },\ 142 | },\ 143 | {0x00,\ 144 | {\ 145 | 0x1f,0x06,0x20,0xa8,0x68,0x38,0xdb,0xe5,0x72,0x77,0x54,0x14,0x14,0x00,0x00,0x0b,0xe5,0xdb,0x03,0x00,\ 146 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 147 | },\ 148 | },\ 149 | {0x00,\ 150 | {\ 151 | 0x16,0x06,0x20,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x14,0x03,0x02,0x00,0x0c,0x29,0x02,0x01,\ 152 | 0x00,0x00,0x00,\ 153 | },\ 154 | },\ 155 | {0x00,\ 156 | {\ 157 | 0x0d,0x06,0x40,0x00,0xe5,0xdb,0x03,0x00,0x8a,0x04,0x00,0x0b,0x00,0x0c,\ 158 | },\ 159 | },\ 160 | {0x00,\ 161 | {\ 162 | 0x1f,0x06,0x50,0x00,0x00,0xc7,0xc4,0x4e,0xe3,0x6c,0x51,0xa7,0x33,0x4b,0xe8,0xed,0x00,0x00,0xb8,0x03,\ 163 | 0xf3,0x6b,0x10,0x9d,0x66,0xf2,0xa9,0xa1,0x12,0x41,0x68,0x38,\ 164 | },\ 165 | },\ 166 | {0x00,\ 167 | {\ 168 | 0x07,0x06,0x50,0x1c,0x00,0x00,0x72,0x77,\ 169 | },\ 170 | },\ 171 | {0x00,\ 172 | {\ 173 | 0x06,0x06,0x60,0x00,0x00,0x00,0x00,\ 174 | },\ 175 | },\ 176 | {0x00,\ 177 | {\ 178 | 0x06,0x06,0xf0,0x00,0x03,0x84,0xcb,\ 179 | },\ 180 | },\ 181 | } 182 | 183 | #endif 184 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLEFirmataSketch/BLEFirmata.h: -------------------------------------------------------------------------------- 1 | /* 2 | Firmata.h - Firmata library 3 | Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | See file LICENSE.txt for further informations on licensing terms. 11 | */ 12 | 13 | #ifndef BleFirmata_h 14 | #define BleFirmata_h 15 | 16 | #include "Boards.h" /* Hardware Abstraction Layer + Wiring/Arduino */ 17 | 18 | /* Version numbers for the protocol. The protocol is still changing, so these 19 | * version numbers are important. This number can be queried so that host 20 | * software can test whether it will be compatible with the currently 21 | * installed firmware. */ 22 | #define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes 23 | #define FIRMATA_MINOR_VERSION 3 // for backwards compatible changes 24 | #define FIRMATA_BUGFIX_VERSION 1 // for bugfix releases 25 | 26 | #define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages 27 | 28 | // message command bytes (128-255/0x80-0xFF) 29 | #define DIGITAL_MESSAGE 0x90 // send data for a digital pin 30 | #define ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM) 31 | #define REPORT_ANALOG 0xC0 // enable analog input by pin # 32 | #define REPORT_DIGITAL 0xD0 // enable digital input by port pair 33 | // 34 | #define SET_PIN_MODE 0xF4 // set a pin to INPUT/OUTPUT/PWM/etc 35 | // 36 | #define REPORT_VERSION 0xF9 // report protocol version 37 | #define SYSTEM_RESET 0xFF // reset from MIDI 38 | // 39 | #define START_SYSEX 0xF0 // start a MIDI Sysex message 40 | #define END_SYSEX 0xF7 // end a MIDI Sysex message 41 | 42 | // extended command set using sysex (0-127/0x00-0x7F) 43 | /* 0x00-0x0F reserved for user-defined commands */ 44 | #define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq 45 | #define STRING_DATA 0x71 // a string message with 14-bits per char 46 | #define SHIFT_DATA 0x75 // a bitstream to/from a shift register 47 | #define I2C_REQUEST 0x76 // send an I2C read/write request 48 | #define I2C_REPLY 0x77 // a reply to an I2C read request 49 | #define I2C_CONFIG 0x78 // config I2C settings such as delay times and power pins 50 | #define EXTENDED_ANALOG 0x6F // analog write (PWM, Servo, etc) to any pin 51 | #define PIN_STATE_QUERY 0x6D // ask for a pin's current mode and value 52 | #define PIN_STATE_RESPONSE 0x6E // reply with pin's current mode and value 53 | #define CAPABILITY_QUERY 0x6B // ask for supported modes and resolution of all pins 54 | #define CAPABILITY_RESPONSE 0x6C // reply with supported modes and resolution 55 | #define ANALOG_MAPPING_QUERY 0x69 // ask for mapping of analog to pin numbers 56 | #define ANALOG_MAPPING_RESPONSE 0x6A // reply with mapping info 57 | #define REPORT_FIRMWARE 0x79 // report name and version of the firmware 58 | #define SAMPLING_INTERVAL 0x7A // set the poll rate of the main loop 59 | #define SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages 60 | #define SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages 61 | // these are DEPRECATED to make the naming more consistent 62 | #define FIRMATA_STRING 0x71 // same as STRING_DATA 63 | #define SYSEX_I2C_REQUEST 0x76 // same as I2C_REQUEST 64 | #define SYSEX_I2C_REPLY 0x77 // same as I2C_REPLY 65 | #define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL 66 | 67 | // pin modes 68 | //#define INPUT 0x00 // defined in wiring.h 69 | //#define OUTPUT 0x01 // defined in wiring.h 70 | #define ANALOG 0x02 // analog pin in analogInput mode 71 | #define PWM 0x03 // digital pin in PWM output mode 72 | #define SERVO 0x04 // digital pin in Servo output mode 73 | #define SHIFT 0x05 // shiftIn/shiftOut mode 74 | #define I2C 0x06 // pin included in I2C setup 75 | #define TOTAL_PIN_MODES 7 76 | 77 | extern "C" { 78 | // callback function types 79 | typedef void (*callbackFunction)(byte, int); 80 | typedef void (*systemResetCallbackFunction)(void); 81 | typedef void (*stringCallbackFunction)(char*); 82 | typedef void (*sysexCallbackFunction)(byte command, byte argc, byte*argv); 83 | } 84 | 85 | 86 | // TODO make it a subclass of a generic Serial/Stream base class 87 | class BleFirmataClass 88 | { 89 | public: 90 | BleFirmataClass(Stream &s); 91 | /* Arduino constructors */ 92 | void begin(); 93 | void begin(long); 94 | void begin(Stream &s); 95 | /* querying functions */ 96 | void printVersion(void); 97 | void blinkVersion(void); 98 | void printFirmwareVersion(void); 99 | //void setFirmwareVersion(byte major, byte minor); // see macro below 100 | void setFirmwareNameAndVersion(const char *name, byte major, byte minor); 101 | /* serial receive handling */ 102 | int available(void); 103 | void processInput(void); 104 | /* serial send handling */ 105 | void sendAnalog(byte pin, int value); 106 | void sendDigital(byte pin, int value); // TODO implement this 107 | void sendDigitalPort(byte portNumber, int portData); 108 | void sendString(const char* string); 109 | void sendString(byte command, const char* string); 110 | void sendSysex(byte command, byte bytec, byte* bytev); 111 | /* attach & detach callback functions to messages */ 112 | void attach(byte command, callbackFunction newFunction); 113 | void attach(byte command, systemResetCallbackFunction newFunction); 114 | void attach(byte command, stringCallbackFunction newFunction); 115 | void attach(byte command, sysexCallbackFunction newFunction); 116 | void detach(byte command); 117 | 118 | private: 119 | Stream &BleFirmataSerial; 120 | /* firmware name and version */ 121 | byte firmwareVersionCount; 122 | byte *firmwareVersionVector; 123 | /* input message handling */ 124 | byte waitForData; // this flag says the next serial input will be data 125 | byte executeMultiByteCommand; // execute this after getting multi-byte data 126 | byte multiByteChannel; // channel data for multiByteCommands 127 | byte storedInputData[MAX_DATA_BYTES]; // multi-byte data 128 | /* sysex */ 129 | boolean parsingSysex; 130 | int sysexBytesRead; 131 | /* callback functions */ 132 | callbackFunction currentAnalogCallback; 133 | callbackFunction currentDigitalCallback; 134 | callbackFunction currentReportAnalogCallback; 135 | callbackFunction currentReportDigitalCallback; 136 | callbackFunction currentPinModeCallback; 137 | systemResetCallbackFunction currentSystemResetCallback; 138 | stringCallbackFunction currentStringCallback; 139 | sysexCallbackFunction currentSysexCallback; 140 | 141 | /* private methods ------------------------------ */ 142 | void processSysexMessage(void); 143 | void systemReset(void); 144 | void pin13strobe(int count, int onInterval, int offInterval); 145 | void sendValueAsTwo7bitBytes(int value); 146 | void startSysex(void); 147 | void endSysex(void); 148 | }; 149 | 150 | extern BleFirmataClass BleFirmata; 151 | 152 | /*============================================================================== 153 | * MACROS 154 | *============================================================================*/ 155 | 156 | /* shortcut for setFirmwareNameAndVersion() that uses __FILE__ to set the 157 | * firmware name. It needs to be a macro so that __FILE__ is included in the 158 | * firmware source file rather than the library source file. 159 | */ 160 | #define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y) 161 | 162 | #endif /* Firmata_h */ 163 | 164 | -------------------------------------------------------------------------------- /nRF51822-BLEMIDI/projectconfig.h: -------------------------------------------------------------------------------- 1 | /* mbed Microcontroller Library 2 | * Copyright (c) 2006-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _PROJECTCONFIG_H_ 18 | #define _PROJECTCONFIG_H_ 19 | 20 | /*========================================================================= 21 | MCU & BOARD SELCTION 22 | 23 | CFG_BOARD is one of the value defined in board.h 24 | -----------------------------------------------------------------------*/ 25 | #define CFG_BOARD BOARD_PCA10001 26 | #define CFG_MCU_STRING "nRF51822" 27 | /*=========================================================================*/ 28 | 29 | 30 | /*========================================================================= 31 | CODE BASE VERSION SETTINGS 32 | 33 | Please do not modify this version number. To set a version number 34 | for your project or firmware, change the values in your 'boards/' 35 | config file. 36 | -----------------------------------------------------------------------*/ 37 | #define CFG_CODEBASE_VERSION_MAJOR 0 38 | #define CFG_CODEBASE_VERSION_MINOR 1 39 | #define CFG_CODEBASE_VERSION_REVISION 0 40 | /*=========================================================================*/ 41 | 42 | 43 | /*========================================================================= 44 | FIRMWARE VERSION SETTINGS 45 | -----------------------------------------------------------------------*/ 46 | #define CFG_FIRMWARE_VERSION_MAJOR 0 47 | #define CFG_FIRMWARE_VERSION_MINOR 0 48 | #define CFG_FIRMWARE_VERSION_REVISION 0 49 | /*=========================================================================*/ 50 | 51 | 52 | /*========================================================================= 53 | DEBUG LEVEL 54 | ----------------------------------------------------------------------- 55 | 56 | CFG_DEBUG Level 3: Full debug output, any failed assert 57 | will produce a breakpoint for the 58 | debugger 59 | Level 2: ATTR_ALWAYS_INLINE is null, ASSERT 60 | has text 61 | Level 1: ATTR_ALWAYS_INLINE is an attribute, 62 | ASSERT has no text 63 | Level 0: No debug information generated 64 | 65 | -----------------------------------------------------------------------*/ 66 | #define CFG_DEBUG (1) 67 | 68 | #if (CFG_DEBUG > 3) || (CFG_DEBUG < 0) 69 | #error "CFG_DEBUG must be a value between 0 (no debug) and 3" 70 | #endif 71 | /*=========================================================================*/ 72 | 73 | 74 | /*========================================================================= 75 | GENERAL NRF51 PERIPHERAL SETTINGS 76 | ----------------------------------------------------------------------- 77 | 78 | CFG_SCHEDULER_ENABLE Set this to 'true' or 'false' depending on 79 | if you use the event scheduler or not 80 | 81 | -----------------------------------------------------------------------*/ 82 | #define CFG_SCHEDULER_ENABLE false 83 | 84 | /*------------------------------- GPIOTE ------------------------------*/ 85 | #define CFG_GPIOTE_MAX_USERS 4 /**< Maximum number of users of the GPIOTE handler. */ 86 | 87 | /*-------------------------------- TIMER ------------------------------*/ 88 | #define CFG_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. freq = (32768/(PRESCALER+1)) */ 89 | #define CFG_TIMER_MAX_INSTANCE 8 /**< Maximum number of simultaneously created timers. */ 90 | #define CFG_TIMER_OPERATION_QUEUE_SIZE 5 /**< Size of timer operation queues. */ 91 | /*=========================================================================*/ 92 | 93 | 94 | /*========================================================================= 95 | BTLE SETTINGS 96 | -----------------------------------------------------------------------*/ 97 | 98 | #define CFG_BLE_TX_POWER_LEVEL 4 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */ 99 | 100 | /*---------------------------- BOND MANAGER ---------------------------*/ 101 | #define CFG_BLE_BOND_FLASH_PAGE_BOND (BLE_FLASH_PAGE_END-1) /**< Flash page used for bond manager bonding information.*/ 102 | #define CFG_BLE_BOND_FLASH_PAGE_SYS_ATTR (BLE_FLASH_PAGE_END-3) /**< Flash page used for bond manager system attribute information. TODO check if we can use BLE_FLASH_PAGE_END-2*/ 103 | #define CFG_BLE_BOND_DELETE_BUTTON_NUM 0 /**< Button to press to delete bond details during init */ 104 | 105 | /*------------------------------ SECURITY -----------------------------*/ 106 | #define CFG_BLE_SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ 107 | #define CFG_BLE_SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ 108 | #define CFG_BLE_SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ 109 | #define CFG_BLE_SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ 110 | #define CFG_BLE_SEC_PARAM_MAX_KEY_SIZE 16 111 | 112 | /*--------------------------------- GAP -------------------------------*/ 113 | #define CFG_GAP_APPEARANCE BLE_APPEARANCE_GENERIC_TAG 114 | #define CFG_GAP_LOCAL_NAME "nRF5x" 115 | 116 | #define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 8 /**< Minimum acceptable connection interval */ 117 | #define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 15 /**< Maximum acceptable connection interval */ 118 | #define CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS 2000 /**< Connection supervisory timeout */ 119 | #define CFG_GAP_CONNECTION_SLAVE_LATENCY 0 /**< Slave Latency in number of connection events. */ 120 | 121 | #define CFG_GAP_ADV_INTERVAL_MS 250 /**< The advertising interval in miliseconds, should be multiply of 0.625 */ 122 | #define CFG_GAP_ADV_TIMEOUT_S 180 /**< The advertising timeout in units of seconds. */ 123 | /*=========================================================================*/ 124 | 125 | 126 | /*========================================================================= 127 | VALIDATION 128 | -----------------------------------------------------------------------*/ 129 | #if CFG_BLE_TX_POWER_LEVEL != -40 && CFG_BLE_TX_POWER_LEVEL != -20 && CFG_BLE_TX_POWER_LEVEL != -16 && CFG_BLE_TX_POWER_LEVEL != -12 && CFG_BLE_TX_POWER_LEVEL != -8 && CFG_BLE_TX_POWER_LEVEL != -4 && CFG_BLE_TX_POWER_LEVEL != 0 && CFG_BLE_TX_POWER_LEVEL != 4 130 | #error "CFG_BLE_TX_POWER_LEVEL must be -40, -20, -16, -12, -8, -4, 0 or 4" 131 | #endif 132 | /*=========================================================================*/ 133 | 134 | #endif /* _PROJECTCONFIG_H_ */ 135 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/nRF8001-BLE-Proto.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * USB-MIDI dump utility 4 | * Copyright 2013 Yuuichi Akagawa 5 | * 6 | * for use with USB Host Shield 2.0 from Circuitsathome.com 7 | * https://github.com/felis/USB_Host_Shield_2.0 8 | * 9 | * This is sample program. Do not expect perfect behavior. 10 | ******************************************************************************* 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see 23 | ******************************************************************************* 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | // Activate to debug 34 | // this increases delay significantly due to increased I/Os 35 | #define DEBUG 1 36 | 37 | #ifdef DEBUG 38 | #define DEBUG_PRINT(x) Serial.print (x) 39 | #define DEBUG_PRINTDEC(x) Serial.print (x, DEC) 40 | #define DEBUG_PRINTHEX(x) Serial.print (x, HEX) 41 | #define DEBUG_PRINTLN(x) Serial.println (x) 42 | #else 43 | #define DEBUG_PRINT(x) 44 | #define DEBUG_PRINTDEC(x) 45 | #define DEBUG_PRINTHEX(x) 46 | #define DEBUG_PRINTLN(x) 47 | #endif 48 | 49 | 50 | /******************************************************************************* 51 | * INITIALIZE USB MIDI Variables 52 | *******************************************************************************/ 53 | USB Usb; 54 | USBH_MIDI Midi(&Usb); 55 | uint8_t usbstate; 56 | uint8_t laststate; 57 | uint8_t rcode; 58 | //uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; 59 | USB_DEVICE_DESCRIPTOR buf; 60 | 61 | void MIDI_poll(); 62 | void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime); 63 | 64 | boolean bFirst; 65 | uint16_t pid, vid; 66 | 67 | /******************************************************************************* 68 | * INITIALIZE Internal BLE Buffer 69 | *******************************************************************************/ 70 | #define MAX_TX_BUFF 64 71 | static uint8_t midiOut_buff[MAX_TX_BUFF]; 72 | static uint8_t midiOut_buff_len = 0; 73 | 74 | 75 | /******************************************************************************* 76 | * Setup USB Shield and Bluetooth Chip (nRF8001) 77 | *******************************************************************************/ 78 | 79 | void setup() 80 | { 81 | 82 | 83 | bFirst = true; 84 | vid = pid = 0; 85 | #ifdef DEBUG 86 | Serial.begin(115200); 87 | #endif 88 | // while (!Serial); 89 | //Workaround for non UHS2.0 Shield 90 | pinMode(10,OUTPUT); 91 | digitalWrite(10,HIGH); 92 | 93 | DEBUG_PRINTLN("BLE Arduino Slave"); 94 | Usb.Init(); 95 | delay( 200 ); 96 | 97 | // if (Usb.Init() == -1) { 98 | // while(1); //halt 99 | // }//if (Usb.Init() == -1... 100 | SPI.begin(); 101 | ble_begin(); 102 | ble_do_events(); 103 | } 104 | 105 | /******************************************************************************* 106 | * Main Runloop 107 | * 108 | * Polls MIDI and BLE Data when SPI bus available 109 | *******************************************************************************/ 110 | 111 | void loop() 112 | { 113 | unsigned long t1; 114 | 115 | // BLE not on SPI, go ahead 116 | if (!ble_busy()) { 117 | 118 | Usb.Task(); 119 | /* usbstate = Usb.getUsbTaskState(); 120 | 121 | if (usbstate != laststate) { 122 | laststate = usbstate; 123 | 124 | switch (usbstate) { 125 | case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE): 126 | E_Notify(PSTR("\r\nWaiting for device..."), 0x80); 127 | break; 128 | case( USB_ATTACHED_SUBSTATE_RESET_DEVICE): 129 | E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80); 130 | break; 131 | case( USB_ATTACHED_SUBSTATE_WAIT_SOF): 132 | E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80); 133 | break; 134 | case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE): 135 | E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80); 136 | break; 137 | case( USB_STATE_ADDRESSING): 138 | E_Notify(PSTR("\r\nSetting device address..."), 0x80); 139 | break; 140 | case( USB_STATE_RUNNING): 141 | E_Notify(PSTR("\r\nGetting device descriptor"), 0x80); 142 | rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf); 143 | 144 | if (rcode) { 145 | E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80); 146 | // print_hex(rcode, 8); 147 | } 148 | else { 149 | 150 | E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80); 151 | print_hex(buf.bLength, 8); 152 | E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80); 153 | print_hex(buf.bDescriptorType, 8); 154 | E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80); 155 | print_hex(buf.bcdUSB, 16); 156 | E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80); 157 | print_hex(buf.bDeviceClass, 8); 158 | E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80); 159 | print_hex(buf.bDeviceSubClass, 8); 160 | E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80); 161 | print_hex(buf.bDeviceProtocol, 8); 162 | E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80); 163 | print_hex(buf.bMaxPacketSize0, 8); 164 | E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80); 165 | print_hex(buf.idVendor, 16); 166 | E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80); 167 | print_hex(buf.idProduct, 16); 168 | E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80); 169 | print_hex(buf.bcdDevice, 16); 170 | E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80); 171 | print_hex(buf.iManufacturer, 8); 172 | E_Notify(PSTR("\r\nProd.string index:\t"), 0x80); 173 | print_hex(buf.iProduct, 8); 174 | E_Notify(PSTR("\r\nSerial number index:\t"), 0x80); 175 | print_hex(buf.iSerialNumber, 8); 176 | E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80); 177 | print_hex(buf.bNumConfigurations, 8); 178 | 179 | } 180 | break; 181 | case( USB_STATE_ERROR): 182 | E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80); 183 | break; 184 | 185 | default: 186 | break; 187 | }//switch( usbstate... 188 | } */ 189 | 190 | if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) 191 | { 192 | MIDI_poll(); 193 | 194 | // TO DO 195 | // Send MIDI to USB Device 196 | 197 | /* if (MIDI.read()) { 198 | msg[0] = MIDI.getType(); 199 | if( msg[0] == 0xf0 ) { //SysEX 200 | //TODO 201 | //SysEx implementation 202 | }else{ 203 | msg[1] = MIDI.getData1(); 204 | msg[2] = MIDI.getData2(); 205 | Midi.SendData(msg, 0); 206 | } 207 | */ 208 | } 209 | 210 | 211 | } 212 | 213 | 214 | //TO DO: 215 | // Omni-Directional MIDI 216 | /* while(ble_available()) { 217 | midiOut_buff[midiOut_buff_len] = ble_read(); 218 | midiOut_buff_len++; 219 | } */ 220 | 221 | // Send packets 222 | 223 | 224 | ble_do_events(); 225 | } 226 | 227 | 228 | 229 | /******************************************************************************* 230 | * Poll MIDI DATA from USB Port 231 | *******************************************************************************/ 232 | void MIDI_poll() 233 | { 234 | 235 | uint8_t bufMidi[64]; 236 | uint16_t rcvd; 237 | uint8_t size; 238 | byte outBuf[ 3 ]; 239 | char buf[20]; 240 | 241 | if(Midi.vid != vid || Midi.pid != pid){ 242 | vid = Midi.vid; 243 | pid = Midi.pid; 244 | } 245 | 246 | do { 247 | if( (size=Midi.RecvData(outBuf)) > 0 ){ 248 | //MIDI Output 249 | //DEBUG_PRINT("MIDI SIZE: "); 250 | //DEBUG_PRINTLN(size); 251 | /* for(int i=0; i0); 258 | 259 | } 260 | 261 | 262 | /******************************************************************************* 263 | * Convert MIDI Data to MIDI-BLE Packets 264 | * 265 | * TO DO: Implement official specification once released 266 | * as this is based on reverse-engineering 267 | * 268 | *******************************************************************************/ 269 | void parseMIDItoAppleBle(int size, byte outBuf[3]) { 270 | char time[2]; 271 | char buf[20]; 272 | 273 | unsigned long timer = 0; 274 | int lastPos; 275 | timer = millis(); 276 | 277 | uint16_t blueMidiTime = 0; 278 | blueMidiTime = 32768 + (timer % 16383); 279 | 280 | 281 | // 0x80 0x80 Prefix Bytes for Apple Protocol 282 | // buffer empty, write apple time prefix 283 | // TO DO: 284 | // Implement correct Apple Time Coding 285 | // 2nd byte (0x80) is temp workaround 286 | if (ble_buff_len() == 0) 287 | { 288 | ble_write(blueMidiTime >> 8); 289 | ble_write(0x80); 290 | for (int i = 0; i < size; i++) 291 | { 292 | ble_write(outBuf[i]); 293 | } 294 | 295 | } 296 | // Buffer already filled, append Packet 297 | // To Do: replace "80" hex seperator with relative timing data? 298 | // or wait for official spec to be released 299 | else if(ble_buff_len() >= 2) 300 | { 301 | int buffL = ble_buff_len(); 302 | ble_write(0x80); 303 | for (int i = 0; i < size; i++) 304 | { 305 | ble_write(outBuf[i]); 306 | } 307 | 308 | } 309 | 310 | //DEBUG_PRINT("MIDI SIZE: "); 311 | //DEBUG_PRINTLN(size); 312 | DEBUG_PRINTLN("---- MIDI ----"); 313 | for(int i=0; i> (num_nibbles - 1) * 4)) & 0x0f; 342 | DEBUG_PRINTHEX(digit); 343 | } 344 | while (--num_nibbles); 345 | } 346 | 347 | 348 | 349 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLEControllerSketch/BLEControllerSketch.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2012, 2013 RedBearLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Boards.h" 18 | 19 | #define PROTOCOL_MAJOR_VERSION 0 // 20 | #define PROTOCOL_MINOR_VERSION 0 // 21 | #define PROTOCOL_BUGFIX_VERSION 2 // bugfix 22 | 23 | #define PIN_CAPABILITY_NONE 0x00 24 | #define PIN_CAPABILITY_DIGITAL 0x01 25 | #define PIN_CAPABILITY_ANALOG 0x02 26 | #define PIN_CAPABILITY_PWM 0x04 27 | #define PIN_CAPABILITY_SERVO 0x08 28 | #define PIN_CAPABILITY_I2C 0x10 29 | 30 | // pin modes 31 | //#define INPUT 0x00 // defined in wiring.h 32 | //#define OUTPUT 0x01 // defined in wiring.h 33 | #define ANALOG 0x02 // analog pin in analogInput mode 34 | #define PWM 0x03 // digital pin in PWM output mode 35 | #define SERVO 0x04 // digital pin in Servo output mode 36 | 37 | byte pin_mode[TOTAL_PINS]; 38 | byte pin_state[TOTAL_PINS]; 39 | byte pin_pwm[TOTAL_PINS]; 40 | byte pin_servo[TOTAL_PINS]; 41 | 42 | Servo servos[MAX_SERVOS]; 43 | 44 | void setup() 45 | { 46 | Serial.begin(57600); 47 | Serial.println("BLE Arduino Slave"); 48 | 49 | /* Default all to digital input */ 50 | for (int pin = 0; pin < TOTAL_PINS; pin++) 51 | { 52 | // Set pin to input with internal pull up 53 | pinMode(pin, INPUT); 54 | digitalWrite(pin, HIGH); 55 | 56 | // Save pin mode and state 57 | pin_mode[pin] = INPUT; 58 | pin_state[pin] = LOW; 59 | } 60 | 61 | // Default pins set to 9 and 8 for REQN and RDYN 62 | // Set your REQN and RDYN here before ble_begin() if you need 63 | //ble_set_pins(3, 2); 64 | 65 | // Set your BLE Shield name here, max. length 10 66 | //ble_set_name("My Name"); 67 | 68 | // Init. and start BLE library. 69 | ble_begin(); 70 | } 71 | 72 | static byte buf_len = 0; 73 | 74 | void ble_write_string(byte *bytes, uint8_t len) 75 | { 76 | if (buf_len + len > 20) 77 | { 78 | for (int j = 0; j < 15000; j++) 79 | ble_do_events(); 80 | 81 | buf_len = 0; 82 | } 83 | 84 | for (int j = 0; j < len; j++) 85 | { 86 | ble_write(bytes[j]); 87 | buf_len++; 88 | } 89 | 90 | if (buf_len == 20) 91 | { 92 | for (int j = 0; j < 15000; j++) 93 | ble_do_events(); 94 | 95 | buf_len = 0; 96 | } 97 | } 98 | 99 | byte reportDigitalInput() 100 | { 101 | if (!ble_connected()) 102 | return 0; 103 | 104 | static byte pin = 0; 105 | byte report = 0; 106 | 107 | if (!IS_PIN_DIGITAL(pin)) 108 | { 109 | pin++; 110 | if (pin >= TOTAL_PINS) 111 | pin = 0; 112 | return 0; 113 | } 114 | 115 | if (pin_mode[pin] == INPUT) 116 | { 117 | byte current_state = digitalRead(pin); 118 | 119 | if (pin_state[pin] != current_state) 120 | { 121 | pin_state[pin] = current_state; 122 | byte buf[] = {'G', pin, INPUT, current_state}; 123 | ble_write_string(buf, 4); 124 | 125 | report = 1; 126 | } 127 | } 128 | 129 | pin++; 130 | if (pin >= TOTAL_PINS) 131 | pin = 0; 132 | 133 | return report; 134 | } 135 | 136 | void reportPinCapability(byte pin) 137 | { 138 | byte buf[] = {'P', pin, 0x00}; 139 | byte pin_cap = 0; 140 | 141 | if (IS_PIN_DIGITAL(pin)) 142 | pin_cap |= PIN_CAPABILITY_DIGITAL; 143 | 144 | if (IS_PIN_ANALOG(pin)) 145 | pin_cap |= PIN_CAPABILITY_ANALOG; 146 | 147 | if (IS_PIN_PWM(pin)) 148 | pin_cap |= PIN_CAPABILITY_PWM; 149 | 150 | if (IS_PIN_SERVO(pin)) 151 | pin_cap |= PIN_CAPABILITY_SERVO; 152 | 153 | buf[2] = pin_cap; 154 | ble_write_string(buf, 3); 155 | } 156 | 157 | void reportPinServoData(byte pin) 158 | { 159 | // if (IS_PIN_SERVO(pin)) 160 | // servos[PIN_TO_SERVO(pin)].write(value); 161 | // pin_servo[pin] = value; 162 | 163 | byte value = pin_servo[pin]; 164 | byte mode = pin_mode[pin]; 165 | byte buf[] = {'G', pin, mode, value}; 166 | ble_write_string(buf, 4); 167 | } 168 | 169 | byte reportPinAnalogData() 170 | { 171 | if (!ble_connected()) 172 | return 0; 173 | 174 | static byte pin = 0; 175 | byte report = 0; 176 | 177 | if (!IS_PIN_DIGITAL(pin)) 178 | { 179 | pin++; 180 | if (pin >= TOTAL_PINS) 181 | pin = 0; 182 | return 0; 183 | } 184 | 185 | if (pin_mode[pin] == ANALOG) 186 | { 187 | uint16_t value = analogRead(pin); 188 | byte value_lo = value; 189 | byte value_hi = value>>8; 190 | 191 | byte mode = pin_mode[pin]; 192 | mode = (value_hi << 4) | mode; 193 | 194 | byte buf[] = {'G', pin, mode, value_lo}; 195 | ble_write_string(buf, 4); 196 | } 197 | 198 | pin++; 199 | if (pin >= TOTAL_PINS) 200 | pin = 0; 201 | 202 | return report; 203 | } 204 | 205 | void reportPinDigitalData(byte pin) 206 | { 207 | byte state = digitalRead(pin); 208 | byte mode = pin_mode[pin]; 209 | byte buf[] = {'G', pin, mode, state}; 210 | ble_write_string(buf, 4); 211 | } 212 | 213 | void reportPinPWMData(byte pin) 214 | { 215 | byte value = pin_pwm[pin]; 216 | byte mode = pin_mode[pin]; 217 | byte buf[] = {'G', pin, mode, value}; 218 | ble_write_string(buf, 4); 219 | } 220 | 221 | void sendCustomData(uint8_t *buf, uint8_t len) 222 | { 223 | uint8_t data[20] = "Z"; 224 | memcpy(&data[1], buf, len); 225 | ble_write_string(data, len+1); 226 | } 227 | 228 | byte queryDone = false; 229 | 230 | void loop() 231 | { 232 | while(ble_available()) 233 | { 234 | byte cmd; 235 | cmd = ble_read(); 236 | Serial.write(cmd); 237 | 238 | // Parse data here 239 | switch (cmd) 240 | { 241 | case 'V': // query protocol version 242 | { 243 | byte buf[] = {'V', 0x00, 0x00, 0x01}; 244 | ble_write_string(buf, 4); 245 | } 246 | break; 247 | 248 | case 'C': // query board total pin count 249 | { 250 | byte buf[2]; 251 | buf[0] = 'C'; 252 | buf[1] = TOTAL_PINS; 253 | ble_write_string(buf, 2); 254 | } 255 | break; 256 | 257 | case 'M': // query pin mode 258 | { 259 | byte pin = ble_read(); 260 | byte buf[] = {'M', pin, pin_mode[pin]}; // report pin mode 261 | ble_write_string(buf, 3); 262 | } 263 | break; 264 | 265 | case 'S': // set pin mode 266 | { 267 | byte pin = ble_read(); 268 | byte mode = ble_read(); 269 | 270 | if (IS_PIN_SERVO(pin) && mode != SERVO && servos[PIN_TO_SERVO(pin)].attached()) 271 | servos[PIN_TO_SERVO(pin)].detach(); 272 | 273 | /* ToDo: check the mode is in its capability or not */ 274 | /* assume always ok */ 275 | if (mode != pin_mode[pin]) 276 | { 277 | pinMode(pin, mode); 278 | pin_mode[pin] = mode; 279 | 280 | if (mode == OUTPUT) 281 | { 282 | digitalWrite(pin, LOW); 283 | pin_state[pin] = LOW; 284 | } 285 | else if (mode == INPUT) 286 | { 287 | digitalWrite(pin, HIGH); 288 | pin_state[pin] = HIGH; 289 | } 290 | else if (mode == ANALOG) 291 | { 292 | if (IS_PIN_ANALOG(pin)) { 293 | if (IS_PIN_DIGITAL(pin)) { 294 | pinMode(PIN_TO_DIGITAL(pin), LOW); 295 | } 296 | } 297 | } 298 | else if (mode == PWM) 299 | { 300 | if (IS_PIN_PWM(pin)) 301 | { 302 | pinMode(PIN_TO_PWM(pin), OUTPUT); 303 | analogWrite(PIN_TO_PWM(pin), 0); 304 | pin_pwm[pin] = 0; 305 | pin_mode[pin] = PWM; 306 | } 307 | } 308 | else if (mode == SERVO) 309 | { 310 | if (IS_PIN_SERVO(pin)) 311 | { 312 | pin_servo[pin] = 0; 313 | pin_mode[pin] = SERVO; 314 | if (!servos[PIN_TO_SERVO(pin)].attached()) 315 | servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin)); 316 | } 317 | } 318 | } 319 | 320 | // if (mode == ANALOG) 321 | // reportPinAnalogData(pin); 322 | if ( (mode == INPUT) || (mode == OUTPUT) ) 323 | reportPinDigitalData(pin); 324 | else if (mode == PWM) 325 | reportPinPWMData(pin); 326 | else if (mode == SERVO) 327 | reportPinServoData(pin); 328 | } 329 | break; 330 | 331 | case 'G': // query pin data 332 | { 333 | byte pin = ble_read(); 334 | reportPinDigitalData(pin); 335 | } 336 | break; 337 | 338 | case 'T': // set pin digital state 339 | { 340 | byte pin = ble_read(); 341 | byte state = ble_read(); 342 | 343 | digitalWrite(pin, state); 344 | reportPinDigitalData(pin); 345 | } 346 | break; 347 | 348 | case 'N': // set PWM 349 | { 350 | byte pin = ble_read(); 351 | byte value = ble_read(); 352 | 353 | analogWrite(PIN_TO_PWM(pin), value); 354 | pin_pwm[pin] = value; 355 | reportPinPWMData(pin); 356 | } 357 | break; 358 | 359 | case 'O': // set Servo 360 | { 361 | byte pin = ble_read(); 362 | byte value = ble_read(); 363 | 364 | if (IS_PIN_SERVO(pin)) 365 | servos[PIN_TO_SERVO(pin)].write(value); 366 | pin_servo[pin] = value; 367 | reportPinServoData(pin); 368 | } 369 | break; 370 | 371 | case 'A': // query all pin status 372 | for (int pin = 0; pin < TOTAL_PINS; pin++) 373 | { 374 | reportPinCapability(pin); 375 | if ( (pin_mode[pin] == INPUT) || (pin_mode[pin] == OUTPUT) ) 376 | reportPinDigitalData(pin); 377 | else if (pin_mode[pin] == PWM) 378 | reportPinPWMData(pin); 379 | else if (pin_mode[pin] == SERVO) 380 | reportPinServoData(pin); 381 | } 382 | 383 | queryDone = true; 384 | { 385 | uint8_t str[] = "ABC"; 386 | sendCustomData(str, 3); 387 | } 388 | 389 | break; 390 | 391 | case 'P': // query pin capability 392 | { 393 | byte pin = ble_read(); 394 | reportPinCapability(pin); 395 | } 396 | break; 397 | 398 | case 'Z': 399 | { 400 | byte len = ble_read(); 401 | byte buf[len]; 402 | for (int i=0;i"); 405 | Serial.print("Received: "); 406 | Serial.print(len); 407 | Serial.println(" byte(s)"); 408 | Serial.print(" Hex: "); 409 | for (int i=0;i 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "BLEParser.h" 29 | 30 | 31 | #define TXRX_BUF_LEN 20 32 | #define RX_BUF_LEN 20 /** Overwriting RX Buf Len since we handle fragmentation **/ 33 | 34 | BLE ble; 35 | Ticker sendTicker; 36 | Ticker usbTicker; 37 | mfk::midi::BLEMIDIParser<256, USBH_MIDI> parser; 38 | 39 | static uint8_t rx_buf[RX_BUF_LEN]; 40 | static int rx_buf_num, rx_state = 0; 41 | static uint8_t rx_temp_buf[20]; 42 | uint8_t outBufMidi[128]; 43 | int outBufMidiPtr; 44 | 45 | // MIDI BLE Service UUIDs 46 | static const uint8_t uart_base_uuid[] = {0x03, 0xB8, 0x0E, 0x5A, 0xED, 0xE8, 0x4B, 0x33, 0xA7, 0x51, 0x6C, 0xE3, 0x4E, 0xC4, 0xC7, 0}; 47 | static const uint8_t uart_tx_uuid[] = {0x77, 0x72, 0xE5, 0xDB, 0x38, 0x68, 0x41, 0x12, 0xA1, 0xA9, 0xF2, 0x66, 0x9D, 0x10, 0x6B, 0xF3}; 48 | static const uint8_t uart_rx_uuid[] = {0x77, 0x72, 0xE5, 0xDB, 0x38, 0x68, 0x41, 0x12, 0xA1, 0xA9, 0xF2, 0x66, 0x9D, 0x10, 0x6B, 0xF3}; 49 | static const uint8_t uart_base_uuid_rev[] = {0, 0xC7, 0xC4, 0x4E, 0xE3, 0x6C, 0x51, 0xA7, 0x33, 0x4B, 0xE8, 0xED, 0x5A, 0x0E, 0xB8, 0x03}; 50 | 51 | 52 | 53 | uint8_t txPayload[TXRX_BUF_LEN] = {0,}; 54 | uint8_t rxPayload[TXRX_BUF_LEN] = {0,}; 55 | 56 | GattCharacteristic txCharacteristic 57 | (uart_tx_uuid, txPayload, 1, 20, 58 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | 59 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | 60 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | 61 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); 62 | 63 | GattCharacteristic *uartChars[] = {&txCharacteristic}; 64 | GattService uartService(uart_base_uuid, uartChars, 65 | sizeof(uartChars) / sizeof(GattCharacteristic *)); 66 | 67 | /******************************************************************************* 68 | * INITIALIZE USB MIDI Variables 69 | *******************************************************************************/ 70 | USB Usb; 71 | USBH_MIDI Midi(&Usb); 72 | uint8_t usbstate; 73 | uint8_t laststate; 74 | uint8_t rcode; 75 | USB_DEVICE_DESCRIPTOR buf; 76 | 77 | void MIDI_poll(); 78 | 79 | boolean bFirst; 80 | boolean isConnected; 81 | boolean isSysex; 82 | uint16_t pid, vid; 83 | int bufferInUse=0; 84 | 85 | /******************************************************************************* 86 | * INITIALIZE Internal BLE Buffer 87 | *******************************************************************************/ 88 | #define MAX_TX_BUFF 64 89 | static uint8_t midiOut_buff[MAX_TX_BUFF]; 90 | static uint8_t midiOut_buff_len = 0; 91 | 92 | 93 | 94 | /******************************************************************************* 95 | * Send MIDI data to BLE Stack 96 | *******************************************************************************/ 97 | void sendData(void) 98 | { 99 | if(rx_buf_num > 0 && isConnected) 100 | { 101 | int bufInc = 0; 102 | if (rx_buf_num < 17) 103 | { 104 | bufInc = rx_buf_num % 17; } 105 | else 106 | { 107 | bufInc = 17; 108 | } 109 | ble.updateCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), rx_buf, bufInc); 110 | memmove(rx_buf, rx_buf+bufInc, rx_buf_num-bufInc); // probably not best practice? needs to be fixed 111 | rx_buf_num -= bufInc; 112 | rx_state = 0; 113 | } 114 | } 115 | 116 | 117 | /******************************************************************************* 118 | * Initialize USB Communication 119 | *******************************************************************************/ 120 | void m_status_check_handle(void) 121 | { 122 | 123 | Usb.Task(); 124 | usbstate = Usb.getUsbTaskState(); 125 | 126 | if (usbstate != laststate) 127 | { 128 | laststate = usbstate; 129 | 130 | switch (usbstate) 131 | { 132 | case ( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE): 133 | E_Notify(PSTR("\r\nWaiting for device..."), 0x80); 134 | break; 135 | case ( USB_ATTACHED_SUBSTATE_RESET_DEVICE): 136 | E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80); 137 | break; 138 | case ( USB_ATTACHED_SUBSTATE_WAIT_SOF): 139 | E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80); 140 | break; 141 | case ( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE): 142 | E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80); 143 | break; 144 | case ( USB_STATE_ADDRESSING): 145 | E_Notify(PSTR("\r\nSetting device address..."), 0x80); 146 | break; 147 | case ( USB_STATE_RUNNING): 148 | E_Notify(PSTR("\r\nGetting device descriptor"), 0x80); 149 | rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf); 150 | 151 | if (rcode) 152 | { 153 | E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80); 154 | // print_hex(rcode, 8); 155 | } 156 | else 157 | { 158 | E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80); 159 | print_hex(buf.bLength, 8); 160 | E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80); 161 | print_hex(buf.bDescriptorType, 8); 162 | E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80); 163 | print_hex(buf.bcdUSB, 16); 164 | E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80); 165 | print_hex(buf.bDeviceClass, 8); 166 | E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80); 167 | print_hex(buf.bDeviceSubClass, 8); 168 | E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80); 169 | print_hex(buf.bDeviceProtocol, 8); 170 | E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80); 171 | print_hex(buf.bMaxPacketSize0, 8); 172 | E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80); 173 | print_hex(buf.idVendor, 16); 174 | E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80); 175 | print_hex(buf.idProduct, 16); 176 | E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80); 177 | print_hex(buf.bcdDevice, 16); 178 | E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80); 179 | print_hex(buf.iManufacturer, 8); 180 | E_Notify(PSTR("\r\nProd.string index:\t"), 0x80); 181 | print_hex(buf.iProduct, 8); 182 | E_Notify(PSTR("\r\nSerial number index:\t"), 0x80); 183 | print_hex(buf.iSerialNumber, 8); 184 | E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80); 185 | print_hex(buf.bNumConfigurations, 8); 186 | 187 | } 188 | break; 189 | case ( USB_STATE_ERROR): 190 | E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80); 191 | break; 192 | 193 | default: 194 | break; 195 | }//switch( usbstate... 196 | } 197 | 198 | if (Usb.getUsbTaskState() == USB_STATE_RUNNING) 199 | { 200 | MIDI_poll(); 201 | } 202 | } 203 | 204 | 205 | /******************************************************************************* 206 | * Callback for Bluetooth disconnection 207 | * Restart advertising and stop the timers. 208 | *******************************************************************************/ 209 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t*) 210 | { 211 | Serial.println("Disconnected "); 212 | Serial.println("Restart advertising "); 213 | isConnected = false; 214 | ble.startAdvertising(); 215 | } 216 | 217 | 218 | /******************************************************************************* 219 | * Callback for incoming connections 220 | * Start the timers. 221 | *******************************************************************************/ 222 | void connectionCallback(const Gap::ConnectionCallbackParams_t* params) 223 | { 224 | isConnected = true; 225 | Serial.println("Connected"); 226 | sendTicker.attach(sendData, 0.01); 227 | } 228 | 229 | 230 | /******************************************************************************* 231 | * Callback for INCOMING MIDI BLE Data 232 | *******************************************************************************/ 233 | void onDataWritten(const GattWriteCallbackParams *Handler) 234 | { 235 | uint8_t buf[TXRX_BUF_LEN]; 236 | uint16_t bytesRead; 237 | if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) 238 | { 239 | ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), 240 | buf, &bytesRead); 241 | parseIncoming(buf, bytesRead); 242 | } 243 | } 244 | 245 | 246 | /******************************************************************************* 247 | * Setup 248 | * Initialize USB Port, set Characteristics and Callbacks for BLE Stack. 249 | *******************************************************************************/ 250 | void setup(void) 251 | { 252 | bFirst = true; 253 | vid = pid = 0; 254 | isConnected = false; 255 | 256 | //Workaround for non UHS2.0 Shield 257 | pinMode(10, OUTPUT); 258 | digitalWrite(10, HIGH); 259 | 260 | Usb.Init(); 261 | delay(500); 262 | Serial.begin(9600); 263 | 264 | parser.setUSBMidiHandle(&Midi); 265 | 266 | ble.init(); 267 | ble.onDisconnection(disconnectionCallback); 268 | ble.onConnection(connectionCallback); 269 | ble.onDataWritten(onDataWritten); 270 | 271 | /* setup advertising */ 272 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); 273 | ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, 274 | (const uint8_t *)"BLIDIno", sizeof("BLIDIno") - 1); 275 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, 276 | (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev)); 277 | 278 | ble.accumulateScanResponse(GapAdvertisingData::SHORTENED_LOCAL_NAME, 279 | (const uint8_t *)"BLIDIno", sizeof("BLIDIno") - 1); 280 | ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, 281 | (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev)); 282 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 283 | 284 | /* 100ms; in multiples of 0.625ms. */ 285 | ble.setAdvertisingInterval(160); 286 | 287 | // set adv_timeout, in seconds 288 | ble.setAdvertisingTimeout(0); 289 | ble.addService(uartService); 290 | 291 | //Set Device Name 292 | ble.setDeviceName((const uint8_t *)"Blidino"); 293 | 294 | ble.startAdvertising(); 295 | usbTicker.attach(m_status_check_handle, 0.01); 296 | } 297 | 298 | 299 | /******************************************************************************* 300 | * BLE Loop 301 | *******************************************************************************/ 302 | void loop(void) 303 | { 304 | ble.waitForEvent(); 305 | } 306 | 307 | 308 | /******************************************************************************* 309 | * Poll MIDI DATA from USB Port 310 | *******************************************************************************/ 311 | void MIDI_poll() 312 | { 313 | uint8_t bufMidi[64]; 314 | uint16_t rcvd; 315 | uint8_t size; 316 | byte outBuf[ 3 ]; 317 | char buf[20]; 318 | 319 | if (Midi.vid != vid || Midi.pid != pid) 320 | { 321 | vid = Midi.vid; 322 | pid = Midi.pid; 323 | } 324 | 325 | do 326 | { 327 | if ((size = Midi.RecvData(outBuf)) > 0) 328 | { 329 | // Send data to parser 330 | parseMIDItoAppleBle(size, outBuf); 331 | } 332 | } while (size > 0); 333 | } 334 | 335 | 336 | /******************************************************************************* 337 | * Convert MIDI Data to MIDI-BLE Packets 338 | *******************************************************************************/ 339 | void parseMIDItoAppleBle(int size, byte outBuf[3]) 340 | { 341 | char time[2]; 342 | char buf[20]; 343 | unsigned long timer = 0; 344 | int lastPos; 345 | timer = millis(); 346 | uint16_t blueMidiTime = 0; 347 | blueMidiTime = 32768 + (timer % 16383); // TODO Proper Bitshifting 348 | 349 | // TODO 350 | // This section is a total mess and is in urgent need of 351 | // a rewrite. 352 | 353 | if(rx_buf_num <= 100) // arbitrary high number 354 | { 355 | if (rx_buf_num % 17 == 0) // End of packet, start a new one 356 | { 357 | rx_buf[rx_buf_num] = blueMidiTime >> 8; 358 | rx_buf_num++; 359 | rx_buf[rx_buf_num] = 0x80; 360 | rx_buf_num++; 361 | } 362 | else 363 | { 364 | rx_buf[rx_buf_num] = 0x80; 365 | rx_buf_num++; 366 | } 367 | for (int i = 0; i < size; i++) 368 | { 369 | rx_buf[rx_buf_num] = outBuf[i]; 370 | rx_buf_num++; 371 | } 372 | } 373 | } 374 | 375 | 376 | /******************************************************************************* 377 | * Convert MIDI BLE to MIDI USB 378 | *******************************************************************************/ 379 | void parseIncoming(uint8_t *buffer, uint16_t bytesRead) 380 | { 381 | for (int i = 1; i < bytesRead; i++) 382 | { 383 | parser.parseMidiEvent(buffer[0], buffer[i]); 384 | } 385 | } 386 | 387 | 388 | /******************************************************************************* 389 | * Convert USB Host debug info to Hex 390 | *******************************************************************************/ 391 | void print_hex(int v, int num_places) 392 | { 393 | int mask = 0, n, num_nibbles, digit; 394 | for (n = 1; n <= num_places; n++) 395 | { 396 | mask = (mask << 1) | 0x0001; 397 | } 398 | v = v & mask; // truncate v to specified number of places 399 | 400 | num_nibbles = num_places / 4; 401 | if ((num_places % 4) != 0) 402 | { 403 | ++num_nibbles; 404 | } 405 | do 406 | { 407 | digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; 408 | Serial.println(digit, HEX); 409 | } 410 | while (--num_nibbles); 411 | } 412 | 413 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLEFirmataSketch/BLEFirmata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Firmata.cpp - Firmata library 3 | Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | See file LICENSE.txt for further informations on licensing terms. 11 | */ 12 | 13 | //****************************************************************************** 14 | //* Includes 15 | //****************************************************************************** 16 | 17 | #include "BLEFirmata.h" 18 | #include "HardwareSerial.h" 19 | #include "RBL_nRF8001.h" 20 | 21 | extern "C" { 22 | #include 23 | #include 24 | } 25 | 26 | //****************************************************************************** 27 | //* Support Functions 28 | //****************************************************************************** 29 | 30 | void BleFirmataClass::sendValueAsTwo7bitBytes(int value) 31 | { 32 | ble_write(value & B01111111); // LSB 33 | ble_write(value >> 7 & B01111111); // MSB 34 | } 35 | 36 | void BleFirmataClass::startSysex(void) 37 | { 38 | ble_write(START_SYSEX); 39 | } 40 | 41 | void BleFirmataClass::endSysex(void) 42 | { 43 | ble_write(END_SYSEX); 44 | } 45 | 46 | //****************************************************************************** 47 | //* Constructors 48 | //****************************************************************************** 49 | 50 | BleFirmataClass::BleFirmataClass(Stream &s) : BleFirmataSerial(s) 51 | { 52 | firmwareVersionCount = 0; 53 | systemReset(); 54 | } 55 | 56 | //****************************************************************************** 57 | //* Public Methods 58 | //****************************************************************************** 59 | 60 | /* begin method for overriding default serial bitrate */ 61 | void BleFirmataClass::begin(void) 62 | { 63 | begin(57600); 64 | } 65 | 66 | /* begin method for overriding default serial bitrate */ 67 | void BleFirmataClass::begin(long speed) 68 | { 69 | // Serial.begin(speed); 70 | BleFirmataSerial = Serial; 71 | blinkVersion(); 72 | printVersion(); 73 | printFirmwareVersion(); 74 | } 75 | 76 | void BleFirmataClass::begin(Stream &s) 77 | { 78 | BleFirmataSerial = s; 79 | systemReset(); 80 | printVersion(); 81 | printFirmwareVersion(); 82 | } 83 | 84 | // output the protocol version message to the serial port 85 | void BleFirmataClass::printVersion(void) { 86 | ble_write(REPORT_VERSION); 87 | ble_write(FIRMATA_MAJOR_VERSION); 88 | ble_write(FIRMATA_MINOR_VERSION); 89 | } 90 | 91 | void BleFirmataClass::blinkVersion(void) 92 | { 93 | // flash the pin with the protocol version 94 | pinMode(VERSION_BLINK_PIN,OUTPUT); 95 | pin13strobe(FIRMATA_MAJOR_VERSION, 40, 210); 96 | delay(250); 97 | pin13strobe(FIRMATA_MINOR_VERSION, 40, 210); 98 | delay(125); 99 | } 100 | 101 | void BleFirmataClass::printFirmwareVersion(void) 102 | { 103 | byte i; 104 | 105 | if(firmwareVersionCount) { // make sure that the name has been set before reporting 106 | startSysex(); 107 | ble_write(REPORT_FIRMWARE); 108 | ble_write(firmwareVersionVector[0]); // major version number 109 | ble_write(firmwareVersionVector[1]); // minor version number 110 | for(i=2; i 0) && (inputData < 128) ) { 198 | waitForData--; 199 | storedInputData[waitForData] = inputData; 200 | if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message 201 | switch(executeMultiByteCommand) { 202 | case ANALOG_MESSAGE: 203 | if(currentAnalogCallback) { 204 | (*currentAnalogCallback)(multiByteChannel, 205 | (storedInputData[0] << 7) 206 | + storedInputData[1]); 207 | } 208 | break; 209 | case DIGITAL_MESSAGE: 210 | if(currentDigitalCallback) { 211 | (*currentDigitalCallback)(multiByteChannel, 212 | (storedInputData[0] << 7) 213 | + storedInputData[1]); 214 | } 215 | break; 216 | case SET_PIN_MODE: 217 | if(currentPinModeCallback) 218 | (*currentPinModeCallback)(storedInputData[1], storedInputData[0]); 219 | break; 220 | case REPORT_ANALOG: 221 | if(currentReportAnalogCallback) 222 | (*currentReportAnalogCallback)(multiByteChannel,storedInputData[0]); 223 | break; 224 | case REPORT_DIGITAL: 225 | if(currentReportDigitalCallback) 226 | (*currentReportDigitalCallback)(multiByteChannel,storedInputData[0]); 227 | break; 228 | } 229 | executeMultiByteCommand = 0; 230 | } 231 | } else { 232 | // remove channel info from command byte if less than 0xF0 233 | if(inputData < 0xF0) { 234 | command = inputData & 0xF0; 235 | multiByteChannel = inputData & 0x0F; 236 | } else { 237 | command = inputData; 238 | // commands in the 0xF* range don't use channel data 239 | } 240 | switch (command) { 241 | case ANALOG_MESSAGE: 242 | case DIGITAL_MESSAGE: 243 | case SET_PIN_MODE: 244 | waitForData = 2; // two data bytes needed 245 | executeMultiByteCommand = command; 246 | break; 247 | case REPORT_ANALOG: 248 | case REPORT_DIGITAL: 249 | waitForData = 1; // two data bytes needed 250 | executeMultiByteCommand = command; 251 | break; 252 | case START_SYSEX: 253 | parsingSysex = true; 254 | sysexBytesRead = 0; 255 | break; 256 | case SYSTEM_RESET: 257 | systemReset(); 258 | break; 259 | case REPORT_VERSION: 260 | BleFirmata.printVersion(); 261 | break; 262 | } 263 | } 264 | } 265 | 266 | //------------------------------------------------------------------------------ 267 | // Serial Send Handling 268 | 269 | // send an analog message 270 | void BleFirmataClass::sendAnalog(byte pin, int value) 271 | { 272 | // pin can only be 0-15, so chop higher bits 273 | ble_write(ANALOG_MESSAGE | (pin & 0xF)); 274 | sendValueAsTwo7bitBytes(value); 275 | } 276 | 277 | // send a single digital pin in a digital message 278 | void BleFirmataClass::sendDigital(byte pin, int value) 279 | { 280 | /* TODO add single pin digital messages to the protocol, this needs to 281 | * track the last digital data sent so that it can be sure to change just 282 | * one bit in the packet. This is complicated by the fact that the 283 | * numbering of the pins will probably differ on Arduino, Wiring, and 284 | * other boards. The DIGITAL_MESSAGE sends 14 bits at a time, but it is 285 | * probably easier to send 8 bit ports for any board with more than 14 286 | * digital pins. 287 | */ 288 | 289 | // TODO: the digital message should not be sent on the serial port every 290 | // time sendDigital() is called. Instead, it should add it to an int 291 | // which will be sent on a schedule. If a pin changes more than once 292 | // before the digital message is sent on the serial port, it should send a 293 | // digital message for each change. 294 | 295 | // if(value == 0) 296 | // sendDigitalPortPair(); 297 | } 298 | 299 | 300 | // send 14-bits in a single digital message (protocol v1) 301 | // send an 8-bit port in a single digital message (protocol v2) 302 | void BleFirmataClass::sendDigitalPort(byte portNumber, int portData) 303 | { 304 | ble_write(DIGITAL_MESSAGE | (portNumber & 0xF)); 305 | ble_write((byte)portData % 128); // Tx bits 0-6 306 | ble_write(portData >> 7); // Tx bits 7-13 307 | } 308 | 309 | 310 | void BleFirmataClass::sendSysex(byte command, byte bytec, byte* bytev) 311 | { 312 | byte i; 313 | startSysex(); 314 | ble_write(command); 315 | for(i=0; i 7 | 8 | #if defined(ARDUINO) && ARDUINO >= 100 9 | #include "Arduino.h" // for digitalRead, digitalWrite, etc 10 | #else 11 | #include "WProgram.h" 12 | #endif 13 | 14 | // Normally Servo.h must be included before Firmata.h (which then includes 15 | // this file). If Servo.h wasn't included, this allows the code to still 16 | // compile, but without support for any Servos. Hopefully that's what the 17 | // user intended by not including Servo.h 18 | #ifndef MAX_SERVOS 19 | #define MAX_SERVOS 0 20 | #endif 21 | 22 | /* 23 | Firmata Hardware Abstraction Layer 24 | 25 | Firmata is built on top of the hardware abstraction functions of Arduino, 26 | specifically digitalWrite, digitalRead, analogWrite, analogRead, and 27 | pinMode. While these functions offer simple integer pin numbers, Firmata 28 | needs more information than is provided by Arduino. This file provides 29 | all other hardware specific details. To make Firmata support a new board, 30 | only this file should require editing. 31 | 32 | The key concept is every "pin" implemented by Firmata may be mapped to 33 | any pin as implemented by Arduino. Usually a simple 1-to-1 mapping is 34 | best, but such mapping should not be assumed. This hardware abstraction 35 | layer allows Firmata to implement any number of pins which map onto the 36 | Arduino implemented pins in almost any arbitrary way. 37 | 38 | 39 | General Constants: 40 | 41 | These constants provide basic information Firmata requires. 42 | 43 | TOTAL_PINS: The total number of pins Firmata implemented by Firmata. 44 | Usually this will match the number of pins the Arduino functions 45 | implement, including any pins pins capable of analog or digital. 46 | However, Firmata may implement any number of pins. For example, 47 | on Arduino Mini with 8 analog inputs, 6 of these may be used 48 | for digital functions, and 2 are analog only. On such boards, 49 | Firmata can implement more pins than Arduino's pinMode() 50 | function, in order to accommodate those special pins. The 51 | Firmata protocol supports a maximum of 128 pins, so this 52 | constant must not exceed 128. 53 | 54 | TOTAL_ANALOG_PINS: The total number of analog input pins implemented. 55 | The Firmata protocol allows up to 16 analog inputs, accessed 56 | using offsets 0 to 15. Because Firmata presents the analog 57 | inputs using different offsets than the actual pin numbers 58 | (a legacy of Arduino's analogRead function, and the way the 59 | analog input capable pins are physically labeled on all 60 | Arduino boards), the total number of analog input signals 61 | must be specified. 16 is the maximum. 62 | 63 | VERSION_BLINK_PIN: When Firmata starts up, it will blink the version 64 | number. This constant is the Arduino pin number where a 65 | LED is connected. 66 | 67 | 68 | Pin Mapping Macros: 69 | 70 | These macros provide the mapping between pins as implemented by 71 | Firmata protocol and the actual pin numbers used by the Arduino 72 | functions. Even though such mappings are often simple, pin 73 | numbers received by Firmata protocol should always be used as 74 | input to these macros, and the result of the macro should be 75 | used with with any Arduino function. 76 | 77 | When Firmata is extended to support a new pin mode or feature, 78 | a pair of macros should be added and used for all hardware 79 | access. For simple 1:1 mapping, these macros add no actual 80 | overhead, yet their consistent use allows source code which 81 | uses them consistently to be easily adapted to all other boards 82 | with different requirements. 83 | 84 | IS_PIN_XXXX(pin): The IS_PIN macros resolve to true or non-zero 85 | if a pin as implemented by Firmata corresponds to a pin 86 | that actually implements the named feature. 87 | 88 | PIN_TO_XXXX(pin): The PIN_TO macros translate pin numbers as 89 | implemented by Firmata to the pin numbers needed as inputs 90 | to the Arduino functions. The corresponding IS_PIN macro 91 | should always be tested before using a PIN_TO macro, so 92 | these macros only need to handle valid Firmata pin 93 | numbers for the named feature. 94 | 95 | 96 | Port Access Inline Funtions: 97 | 98 | For efficiency, Firmata protocol provides access to digital 99 | input and output pins grouped by 8 bit ports. When these 100 | groups of 8 correspond to actual 8 bit ports as implemented 101 | by the hardware, these inline functions can provide high 102 | speed direct port access. Otherwise, a default implementation 103 | using 8 calls to digitalWrite or digitalRead is used. 104 | 105 | When porting Firmata to a new board, it is recommended to 106 | use the default functions first and focus only on the constants 107 | and macros above. When those are working, if optimized port 108 | access is desired, these inline functions may be extended. 109 | The recommended approach defines a symbol indicating which 110 | optimization to use, and then conditional complication is 111 | used within these functions. 112 | 113 | readPort(port, bitmask): Read an 8 bit port, returning the value. 114 | port: The port number, Firmata pins port*8 to port*8+7 115 | bitmask: The actual pins to read, indicated by 1 bits. 116 | 117 | writePort(port, value, bitmask): Write an 8 bit port. 118 | port: The port number, Firmata pins port*8 to port*8+7 119 | value: The 8 bit value to write 120 | bitmask: The actual pins to write, indicated by 1 bits. 121 | */ 122 | 123 | /*============================================================================== 124 | * Board Specific Configuration 125 | *============================================================================*/ 126 | 127 | #ifndef digitalPinHasPWM 128 | #define digitalPinHasPWM(p) IS_PIN_DIGITAL(p) 129 | #endif 130 | 131 | // Arduino Duemilanove, Diecimila, and NG 132 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 133 | #if defined(NUM_ANALOG_INPUTS) && NUM_ANALOG_INPUTS == 6 134 | #define TOTAL_ANALOG_PINS 6 135 | #define TOTAL_PINS 20 // 14 digital + 6 analog 136 | #else 137 | #define TOTAL_ANALOG_PINS 8 138 | #define TOTAL_PINS 22 // 14 digital + 8 analog 139 | #endif 140 | #define VERSION_BLINK_PIN 13 141 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19) 142 | #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS) 143 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 144 | #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) 145 | #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) 146 | #define PIN_TO_DIGITAL(p) (p) 147 | #define PIN_TO_ANALOG(p) ((p) - 14) 148 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 149 | #define PIN_TO_SERVO(p) ((p) - 2) 150 | #define ARDUINO_PINOUT_OPTIMIZE 1 151 | 152 | 153 | // Wiring (and board) 154 | #elif defined(WIRING) 155 | #define VERSION_BLINK_PIN WLED 156 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 157 | #define IS_PIN_ANALOG(p) ((p) >= FIRST_ANALOG_PIN && (p) < (FIRST_ANALOG_PIN+TOTAL_ANALOG_PINS)) 158 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 159 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 160 | #define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL) 161 | #define PIN_TO_DIGITAL(p) (p) 162 | #define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN) 163 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 164 | #define PIN_TO_SERVO(p) (p) 165 | 166 | 167 | // old Arduinos 168 | #elif defined(__AVR_ATmega8__) 169 | #define TOTAL_ANALOG_PINS 6 170 | #define TOTAL_PINS 20 // 14 digital + 6 analog 171 | #define VERSION_BLINK_PIN 13 172 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19) 173 | #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19) 174 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 175 | #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) 176 | #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) 177 | #define PIN_TO_DIGITAL(p) (p) 178 | #define PIN_TO_ANALOG(p) ((p) - 14) 179 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 180 | #define PIN_TO_SERVO(p) ((p) - 2) 181 | #define ARDUINO_PINOUT_OPTIMIZE 1 182 | 183 | 184 | // Arduino Mega 185 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 186 | #define TOTAL_ANALOG_PINS 16 187 | #define TOTAL_PINS 70 // 54 digital + 16 analog 188 | #define VERSION_BLINK_PIN 13 189 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 190 | #define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) 191 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 192 | #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) 193 | #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) 194 | #define PIN_TO_DIGITAL(p) (p) 195 | #define PIN_TO_ANALOG(p) ((p) - 54) 196 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 197 | #define PIN_TO_SERVO(p) ((p) - 2) 198 | 199 | 200 | // Teensy 1.0 201 | #elif defined(__AVR_AT90USB162__) 202 | #define TOTAL_ANALOG_PINS 0 203 | #define TOTAL_PINS 21 // 21 digital + no analog 204 | #define VERSION_BLINK_PIN 6 205 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 206 | #define IS_PIN_ANALOG(p) (0) 207 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 208 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 209 | #define IS_PIN_I2C(p) (0) 210 | #define PIN_TO_DIGITAL(p) (p) 211 | #define PIN_TO_ANALOG(p) (0) 212 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 213 | #define PIN_TO_SERVO(p) (p) 214 | 215 | 216 | // Teensy 2.0 217 | #elif defined(__AVR_ATmega32U4__) 218 | #define TOTAL_ANALOG_PINS 12 219 | #define TOTAL_PINS 25 // 11 digital + 12 analog 220 | #define VERSION_BLINK_PIN 11 221 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 222 | #define IS_PIN_ANALOG(p) ((p) >= 11 && (p) <= 22) 223 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 224 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 225 | #define IS_PIN_I2C(p) ((p) == 5 || (p) == 6) 226 | #define PIN_TO_DIGITAL(p) (p) 227 | #define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11) 228 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 229 | #define PIN_TO_SERVO(p) (p) 230 | 231 | 232 | // Teensy++ 1.0 and 2.0 233 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 234 | #define TOTAL_ANALOG_PINS 8 235 | #define TOTAL_PINS 46 // 38 digital + 8 analog 236 | #define VERSION_BLINK_PIN 6 237 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 238 | #define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS) 239 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 240 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 241 | #define IS_PIN_I2C(p) ((p) == 0 || (p) == 1) 242 | #define PIN_TO_DIGITAL(p) (p) 243 | #define PIN_TO_ANALOG(p) ((p) - 38) 244 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 245 | #define PIN_TO_SERVO(p) (p) 246 | 247 | 248 | // Sanguino 249 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 250 | #define TOTAL_ANALOG_PINS 8 251 | #define TOTAL_PINS 32 // 24 digital + 8 analog 252 | #define VERSION_BLINK_PIN 0 253 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 254 | #define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS) 255 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 256 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 257 | #define IS_PIN_I2C(p) ((p) == 16 || (p) == 17) 258 | #define PIN_TO_DIGITAL(p) (p) 259 | #define PIN_TO_ANALOG(p) ((p) - 24) 260 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 261 | #define PIN_TO_SERVO(p) ((p) - 2) 262 | 263 | 264 | // Illuminato 265 | #elif defined(__AVR_ATmega645__) 266 | #define TOTAL_ANALOG_PINS 6 267 | #define TOTAL_PINS 42 // 36 digital + 6 analog 268 | #define VERSION_BLINK_PIN 13 269 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 270 | #define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS) 271 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 272 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 273 | #define IS_PIN_I2C(p) ((p) == 4 || (p) == 5) 274 | #define PIN_TO_DIGITAL(p) (p) 275 | #define PIN_TO_ANALOG(p) ((p) - 36) 276 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 277 | #define PIN_TO_SERVO(p) ((p) - 2) 278 | 279 | 280 | // Arduino DUE 281 | #elif defined(__SAM3X8E__) 282 | #define TOTAL_ANALOG_PINS 12 283 | #define TOTAL_PINS 66 // 54 digital + 12 analog 284 | #define VERSION_BLINK_PIN 13 285 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 286 | #define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) 287 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 288 | #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) 289 | #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) // 70 71 290 | #define PIN_TO_DIGITAL(p) (p) 291 | #define PIN_TO_ANALOG(p) ((p) - 54) 292 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 293 | #define PIN_TO_SERVO(p) ((p) - 2) 294 | 295 | 296 | // anything else 297 | #else 298 | #error "Please edit Boards.h with a hardware abstraction for this board" 299 | #endif 300 | 301 | 302 | /*============================================================================== 303 | * readPort() - Read an 8 bit port 304 | *============================================================================*/ 305 | 306 | static inline unsigned char readPort(byte, byte) __attribute__((always_inline, unused)); 307 | static inline unsigned char readPort(byte port, byte bitmask) 308 | { 309 | #if defined(ARDUINO_PINOUT_OPTIMIZE) 310 | if (port == 0) return (PIND & 0xFC) & bitmask; // ignore Rx/Tx 0/1 311 | if (port == 1) return ((PINB & 0x3F) | ((PINC & 0x03) << 6)) & bitmask; 312 | if (port == 2) return ((PINC & 0x3C) >> 2) & bitmask; 313 | return 0; 314 | #else 315 | unsigned char out=0, pin=port*8; 316 | if (IS_PIN_DIGITAL(pin+0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(pin+0))) out |= 0x01; 317 | if (IS_PIN_DIGITAL(pin+1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(pin+1))) out |= 0x02; 318 | if (IS_PIN_DIGITAL(pin+2) && (bitmask & 0x04) && digitalRead(PIN_TO_DIGITAL(pin+2))) out |= 0x04; 319 | if (IS_PIN_DIGITAL(pin+3) && (bitmask & 0x08) && digitalRead(PIN_TO_DIGITAL(pin+3))) out |= 0x08; 320 | if (IS_PIN_DIGITAL(pin+4) && (bitmask & 0x10) && digitalRead(PIN_TO_DIGITAL(pin+4))) out |= 0x10; 321 | if (IS_PIN_DIGITAL(pin+5) && (bitmask & 0x20) && digitalRead(PIN_TO_DIGITAL(pin+5))) out |= 0x20; 322 | if (IS_PIN_DIGITAL(pin+6) && (bitmask & 0x40) && digitalRead(PIN_TO_DIGITAL(pin+6))) out |= 0x40; 323 | if (IS_PIN_DIGITAL(pin+7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(pin+7))) out |= 0x80; 324 | return out; 325 | #endif 326 | } 327 | 328 | /*============================================================================== 329 | * writePort() - Write an 8 bit port, only touch pins specified by a bitmask 330 | *============================================================================*/ 331 | 332 | static inline unsigned char writePort(byte, byte, byte) __attribute__((always_inline, unused)); 333 | static inline unsigned char writePort(byte port, byte value, byte bitmask) 334 | { 335 | #if defined(ARDUINO_PINOUT_OPTIMIZE) 336 | if (port == 0) { 337 | bitmask = bitmask & 0xFC; // do not touch Tx & Rx pins 338 | byte valD = value & bitmask; 339 | byte maskD = ~bitmask; 340 | cli(); 341 | PORTD = (PORTD & maskD) | valD; 342 | sei(); 343 | } else if (port == 1) { 344 | byte valB = (value & bitmask) & 0x3F; 345 | byte valC = (value & bitmask) >> 6; 346 | byte maskB = ~(bitmask & 0x3F); 347 | byte maskC = ~((bitmask & 0xC0) >> 6); 348 | cli(); 349 | PORTB = (PORTB & maskB) | valB; 350 | PORTC = (PORTC & maskC) | valC; 351 | sei(); 352 | } else if (port == 2) { 353 | bitmask = bitmask & 0x0F; 354 | byte valC = (value & bitmask) << 2; 355 | byte maskC = ~(bitmask << 2); 356 | cli(); 357 | PORTC = (PORTC & maskC) | valC; 358 | sei(); 359 | } 360 | #else 361 | byte pin=port*8; 362 | if ((bitmask & 0x01)) digitalWrite(PIN_TO_DIGITAL(pin+0), (value & 0x01)); 363 | if ((bitmask & 0x02)) digitalWrite(PIN_TO_DIGITAL(pin+1), (value & 0x02)); 364 | if ((bitmask & 0x04)) digitalWrite(PIN_TO_DIGITAL(pin+2), (value & 0x04)); 365 | if ((bitmask & 0x08)) digitalWrite(PIN_TO_DIGITAL(pin+3), (value & 0x08)); 366 | if ((bitmask & 0x10)) digitalWrite(PIN_TO_DIGITAL(pin+4), (value & 0x10)); 367 | if ((bitmask & 0x20)) digitalWrite(PIN_TO_DIGITAL(pin+5), (value & 0x20)); 368 | if ((bitmask & 0x40)) digitalWrite(PIN_TO_DIGITAL(pin+6), (value & 0x40)); 369 | if ((bitmask & 0x80)) digitalWrite(PIN_TO_DIGITAL(pin+7), (value & 0x80)); 370 | #endif 371 | } 372 | 373 | 374 | 375 | 376 | #ifndef TOTAL_PORTS 377 | #define TOTAL_PORTS ((TOTAL_PINS + 7) / 8) 378 | #endif 379 | 380 | 381 | #endif /* Firmata_Boards_h */ 382 | 383 | -------------------------------------------------------------------------------- /Legacy Projects/nRF8001-BLE-Proto/RBL_nRF8001/examples/BLEControllerSketch/Boards.h: -------------------------------------------------------------------------------- 1 | /* Boards.h - Hardware Abstraction Layer for Firmata library */ 2 | 3 | #ifndef Boards_h 4 | #define Boards_h 5 | 6 | #include 7 | 8 | #if defined(ARDUINO) && ARDUINO >= 100 9 | #include "Arduino.h" // for digitalRead, digitalWrite, etc 10 | #else 11 | #include "WProgram.h" 12 | #endif 13 | 14 | // Normally Servo.h must be included before Firmata.h (which then includes 15 | // this file). If Servo.h wasn't included, this allows the code to still 16 | // compile, but without support for any Servos. Hopefully that's what the 17 | // user intended by not including Servo.h 18 | #ifndef MAX_SERVOS 19 | #define MAX_SERVOS 0 20 | #endif 21 | 22 | /* 23 | Firmata Hardware Abstraction Layer 24 | 25 | Firmata is built on top of the hardware abstraction functions of Arduino, 26 | specifically digitalWrite, digitalRead, analogWrite, analogRead, and 27 | pinMode. While these functions offer simple integer pin numbers, Firmata 28 | needs more information than is provided by Arduino. This file provides 29 | all other hardware specific details. To make Firmata support a new board, 30 | only this file should require editing. 31 | 32 | The key concept is every "pin" implemented by Firmata may be mapped to 33 | any pin as implemented by Arduino. Usually a simple 1-to-1 mapping is 34 | best, but such mapping should not be assumed. This hardware abstraction 35 | layer allows Firmata to implement any number of pins which map onto the 36 | Arduino implemented pins in almost any arbitrary way. 37 | 38 | 39 | General Constants: 40 | 41 | These constants provide basic information Firmata requires. 42 | 43 | TOTAL_PINS: The total number of pins Firmata implemented by Firmata. 44 | Usually this will match the number of pins the Arduino functions 45 | implement, including any pins pins capable of analog or digital. 46 | However, Firmata may implement any number of pins. For example, 47 | on Arduino Mini with 8 analog inputs, 6 of these may be used 48 | for digital functions, and 2 are analog only. On such boards, 49 | Firmata can implement more pins than Arduino's pinMode() 50 | function, in order to accommodate those special pins. The 51 | Firmata protocol supports a maximum of 128 pins, so this 52 | constant must not exceed 128. 53 | 54 | TOTAL_ANALOG_PINS: The total number of analog input pins implemented. 55 | The Firmata protocol allows up to 16 analog inputs, accessed 56 | using offsets 0 to 15. Because Firmata presents the analog 57 | inputs using different offsets than the actual pin numbers 58 | (a legacy of Arduino's analogRead function, and the way the 59 | analog input capable pins are physically labeled on all 60 | Arduino boards), the total number of analog input signals 61 | must be specified. 16 is the maximum. 62 | 63 | VERSION_BLINK_PIN: When Firmata starts up, it will blink the version 64 | number. This constant is the Arduino pin number where a 65 | LED is connected. 66 | 67 | 68 | Pin Mapping Macros: 69 | 70 | These macros provide the mapping between pins as implemented by 71 | Firmata protocol and the actual pin numbers used by the Arduino 72 | functions. Even though such mappings are often simple, pin 73 | numbers received by Firmata protocol should always be used as 74 | input to these macros, and the result of the macro should be 75 | used with with any Arduino function. 76 | 77 | When Firmata is extended to support a new pin mode or feature, 78 | a pair of macros should be added and used for all hardware 79 | access. For simple 1:1 mapping, these macros add no actual 80 | overhead, yet their consistent use allows source code which 81 | uses them consistently to be easily adapted to all other boards 82 | with different requirements. 83 | 84 | IS_PIN_XXXX(pin): The IS_PIN macros resolve to true or non-zero 85 | if a pin as implemented by Firmata corresponds to a pin 86 | that actually implements the named feature. 87 | 88 | PIN_TO_XXXX(pin): The PIN_TO macros translate pin numbers as 89 | implemented by Firmata to the pin numbers needed as inputs 90 | to the Arduino functions. The corresponding IS_PIN macro 91 | should always be tested before using a PIN_TO macro, so 92 | these macros only need to handle valid Firmata pin 93 | numbers for the named feature. 94 | 95 | 96 | Port Access Inline Funtions: 97 | 98 | For efficiency, Firmata protocol provides access to digital 99 | input and output pins grouped by 8 bit ports. When these 100 | groups of 8 correspond to actual 8 bit ports as implemented 101 | by the hardware, these inline functions can provide high 102 | speed direct port access. Otherwise, a default implementation 103 | using 8 calls to digitalWrite or digitalRead is used. 104 | 105 | When porting Firmata to a new board, it is recommended to 106 | use the default functions first and focus only on the constants 107 | and macros above. When those are working, if optimized port 108 | access is desired, these inline functions may be extended. 109 | The recommended approach defines a symbol indicating which 110 | optimization to use, and then conditional complication is 111 | used within these functions. 112 | 113 | readPort(port, bitmask): Read an 8 bit port, returning the value. 114 | port: The port number, Firmata pins port*8 to port*8+7 115 | bitmask: The actual pins to read, indicated by 1 bits. 116 | 117 | writePort(port, value, bitmask): Write an 8 bit port. 118 | port: The port number, Firmata pins port*8 to port*8+7 119 | value: The 8 bit value to write 120 | bitmask: The actual pins to write, indicated by 1 bits. 121 | */ 122 | 123 | /*============================================================================== 124 | * Board Specific Configuration 125 | *============================================================================*/ 126 | 127 | #ifndef digitalPinHasPWM 128 | #define digitalPinHasPWM(p) IS_PIN_DIGITAL(p) 129 | #endif 130 | 131 | // Arduino Duemilanove, Diecimila, and NG 132 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 133 | #if defined(NUM_ANALOG_INPUTS) && NUM_ANALOG_INPUTS == 6 134 | #define TOTAL_ANALOG_PINS 6 135 | #define TOTAL_PINS 20 // 14 digital + 6 analog 136 | #else 137 | #define TOTAL_ANALOG_PINS 8 138 | #define TOTAL_PINS 22 // 14 digital + 8 analog 139 | #endif 140 | #define VERSION_BLINK_PIN 13 141 | #define IS_PIN_DIGITAL(p) (((p) >= 2 && (p) <= 19) && !((p) >= 8 && (p) <= 13)) 142 | //#define IS_PIN_DIGITAL(p) ( ((p) >= 2 && (p) <= 7) || ((p) >= 13 && (p) <= 19) ) 143 | #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS) 144 | #define IS_PIN_PWM(p) (digitalPinHasPWM(p) && !((p) >= 8 && (p) <= 12)) 145 | #define IS_PIN_SERVO(p) ( (p) >= 2 && (p) <= 7 ) 146 | #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) 147 | #define PIN_TO_DIGITAL(p) (p) 148 | #define PIN_TO_ANALOG(p) ((p) - 14) 149 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 150 | #define PIN_TO_SERVO(p) ((p) - 2) 151 | #define ARDUINO_PINOUT_OPTIMIZE 1 152 | 153 | 154 | // Wiring (and board) 155 | #elif defined(WIRING) 156 | #define VERSION_BLINK_PIN WLED 157 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 158 | #define IS_PIN_ANALOG(p) ((p) >= FIRST_ANALOG_PIN && (p) < (FIRST_ANALOG_PIN+TOTAL_ANALOG_PINS)) 159 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 160 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 161 | #define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL) 162 | #define PIN_TO_DIGITAL(p) (p) 163 | #define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN) 164 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 165 | #define PIN_TO_SERVO(p) (p) 166 | 167 | 168 | // old Arduinos 169 | #elif defined(__AVR_ATmega8__) 170 | #define TOTAL_ANALOG_PINS 6 171 | #define TOTAL_PINS 20 // 14 digital + 6 analog 172 | #define VERSION_BLINK_PIN 13 173 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19) 174 | #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19) 175 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 176 | #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS) 177 | #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19) 178 | #define PIN_TO_DIGITAL(p) (p) 179 | #define PIN_TO_ANALOG(p) ((p) - 14) 180 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 181 | #define PIN_TO_SERVO(p) ((p) - 2) 182 | #define ARDUINO_PINOUT_OPTIMIZE 1 183 | 184 | 185 | // Arduino Mega 186 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 187 | #define TOTAL_ANALOG_PINS 16 188 | #define TOTAL_PINS 70 // 54 digital + 16 analog 189 | #define VERSION_BLINK_PIN 13 190 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 191 | #define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) 192 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 193 | #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) 194 | #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) 195 | #define PIN_TO_DIGITAL(p) (p) 196 | #define PIN_TO_ANALOG(p) ((p) - 54) 197 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 198 | #define PIN_TO_SERVO(p) ((p) - 2) 199 | 200 | 201 | // Teensy 1.0 202 | #elif defined(__AVR_AT90USB162__) 203 | #define TOTAL_ANALOG_PINS 0 204 | #define TOTAL_PINS 21 // 21 digital + no analog 205 | #define VERSION_BLINK_PIN 6 206 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 207 | #define IS_PIN_ANALOG(p) (0) 208 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 209 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 210 | #define IS_PIN_I2C(p) (0) 211 | #define PIN_TO_DIGITAL(p) (p) 212 | #define PIN_TO_ANALOG(p) (0) 213 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 214 | #define PIN_TO_SERVO(p) (p) 215 | 216 | 217 | // Blend Micro 218 | #elif defined(BLEND_MICRO) 219 | #define TOTAL_ANALOG_PINS 6 220 | #define TOTAL_PINS 24 // 11 digital + 12 analog 221 | #define VERSION_BLINK_PIN 13 222 | #define IS_PIN_DIGITAL(p) ( (p) >= 0 && (p) < 24 && !((p) == 4) && !((p) >= 6 && (p) <= 7) && !((p) >=14 && (p) <= 17) ) 223 | #define IS_PIN_ANALOG(p) ((p) >= 18 && (p) < 24) 224 | #define IS_PIN_PWM(p) ( (p) == 3 || (p) == 5 || (p) == 9 || (p) == 10 || (p) == 11 || (p) == 13 ) 225 | #define IS_PIN_SERVO(p) ( (p) >= 0 && (p) < MAX_SERVOS && !((p) == 4) && !((p) >= 6 && (p) <= 7) ) 226 | #define IS_PIN_I2C(p) ((p) == 5 || (p) == 6) 227 | #define PIN_TO_DIGITAL(p) (p) 228 | #define PIN_TO_ANALOG(p) ((p)-18) 229 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 230 | #define PIN_TO_SERVO(p) (p) 231 | 232 | 233 | // Teensy 2.0 234 | #elif defined(__AVR_ATmega32U4__) 235 | #define TOTAL_ANALOG_PINS 6 236 | #define TOTAL_PINS 24 // 11 digital + 12 analog 237 | #define VERSION_BLINK_PIN 13 238 | #define IS_PIN_DIGITAL(p) ( (p) >= 0 && (p) < 24 && !((p) >= 8 && (p) <= 9) && !((p) >=14 && (p) <= 17) ) 239 | #define IS_PIN_ANALOG(p) ((p) >= 18 && (p) < 24) 240 | #define IS_PIN_PWM(p) ( (p) == 3 || (p) == 5 || (p) == 6 || (p) == 10 || (p) == 11 || (p) == 13 ) 241 | #define IS_PIN_SERVO(p) ( (p) >= 0 && (p) < MAX_SERVOS && !((p) >= 8 && (p) <= 9) ) 242 | #define IS_PIN_I2C(p) ((p) == 5 || (p) == 6) 243 | #define PIN_TO_DIGITAL(p) (p) 244 | #define PIN_TO_ANALOG(p) ((p)-18) 245 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 246 | #define PIN_TO_SERVO(p) (p) 247 | 248 | 249 | // Teensy++ 1.0 and 2.0 250 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 251 | #define TOTAL_ANALOG_PINS 8 252 | #define TOTAL_PINS 46 // 38 digital + 8 analog 253 | #define VERSION_BLINK_PIN 6 254 | #define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS) 255 | #define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS) 256 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 257 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 258 | #define IS_PIN_I2C(p) ((p) == 0 || (p) == 1) 259 | #define PIN_TO_DIGITAL(p) (p) 260 | #define PIN_TO_ANALOG(p) ((p) - 38) 261 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 262 | #define PIN_TO_SERVO(p) (p) 263 | 264 | 265 | // Sanguino 266 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 267 | #define TOTAL_ANALOG_PINS 8 268 | #define TOTAL_PINS 32 // 24 digital + 8 analog 269 | #define VERSION_BLINK_PIN 0 270 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 271 | #define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS) 272 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 273 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 274 | #define IS_PIN_I2C(p) ((p) == 16 || (p) == 17) 275 | #define PIN_TO_DIGITAL(p) (p) 276 | #define PIN_TO_ANALOG(p) ((p) - 24) 277 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 278 | #define PIN_TO_SERVO(p) ((p) - 2) 279 | 280 | 281 | // Illuminato 282 | #elif defined(__AVR_ATmega645__) 283 | #define TOTAL_ANALOG_PINS 6 284 | #define TOTAL_PINS 42 // 36 digital + 6 analog 285 | #define VERSION_BLINK_PIN 13 286 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 287 | #define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS) 288 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 289 | #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) 290 | #define IS_PIN_I2C(p) ((p) == 4 || (p) == 5) 291 | #define PIN_TO_DIGITAL(p) (p) 292 | #define PIN_TO_ANALOG(p) ((p) - 36) 293 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 294 | #define PIN_TO_SERVO(p) ((p) - 2) 295 | 296 | 297 | // Arduino DUE 298 | #elif defined(__SAM3X8E__) 299 | #define TOTAL_ANALOG_PINS 12 300 | #define TOTAL_PINS 66 // 54 digital + 12 analog 301 | #define VERSION_BLINK_PIN 13 302 | #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS) 303 | #define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) 304 | #define IS_PIN_PWM(p) digitalPinHasPWM(p) 305 | #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) 306 | #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) // 70 71 307 | #define PIN_TO_DIGITAL(p) (p) 308 | #define PIN_TO_ANALOG(p) ((p) - 54) 309 | #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) 310 | #define PIN_TO_SERVO(p) ((p) - 2) 311 | 312 | 313 | // anything else 314 | #else 315 | #error "Please edit Boards.h with a hardware abstraction for this board" 316 | #endif 317 | 318 | 319 | /*============================================================================== 320 | * readPort() - Read an 8 bit port 321 | *============================================================================*/ 322 | 323 | static inline unsigned char readPort(byte, byte) __attribute__((always_inline, unused)); 324 | static inline unsigned char readPort(byte port, byte bitmask) 325 | { 326 | #if defined(ARDUINO_PINOUT_OPTIMIZE) 327 | if (port == 0) return (PIND & 0xFC) & bitmask; // ignore Rx/Tx 0/1 328 | if (port == 1) return ((PINB & 0x3F) | ((PINC & 0x03) << 6)) & bitmask; 329 | if (port == 2) return ((PINC & 0x3C) >> 2) & bitmask; 330 | return 0; 331 | #else 332 | unsigned char out=0, pin=port*8; 333 | if (IS_PIN_DIGITAL(pin+0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(pin+0))) out |= 0x01; 334 | if (IS_PIN_DIGITAL(pin+1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(pin+1))) out |= 0x02; 335 | if (IS_PIN_DIGITAL(pin+2) && (bitmask & 0x04) && digitalRead(PIN_TO_DIGITAL(pin+2))) out |= 0x04; 336 | if (IS_PIN_DIGITAL(pin+3) && (bitmask & 0x08) && digitalRead(PIN_TO_DIGITAL(pin+3))) out |= 0x08; 337 | if (IS_PIN_DIGITAL(pin+4) && (bitmask & 0x10) && digitalRead(PIN_TO_DIGITAL(pin+4))) out |= 0x10; 338 | if (IS_PIN_DIGITAL(pin+5) && (bitmask & 0x20) && digitalRead(PIN_TO_DIGITAL(pin+5))) out |= 0x20; 339 | if (IS_PIN_DIGITAL(pin+6) && (bitmask & 0x40) && digitalRead(PIN_TO_DIGITAL(pin+6))) out |= 0x40; 340 | if (IS_PIN_DIGITAL(pin+7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(pin+7))) out |= 0x80; 341 | return out; 342 | #endif 343 | } 344 | 345 | /*============================================================================== 346 | * writePort() - Write an 8 bit port, only touch pins specified by a bitmask 347 | *============================================================================*/ 348 | 349 | static inline unsigned char writePort(byte, byte, byte) __attribute__((always_inline, unused)); 350 | static inline unsigned char writePort(byte port, byte value, byte bitmask) 351 | { 352 | #if defined(ARDUINO_PINOUT_OPTIMIZE) 353 | if (port == 0) { 354 | bitmask = bitmask & 0xFC; // do not touch Tx & Rx pins 355 | byte valD = value & bitmask; 356 | byte maskD = ~bitmask; 357 | cli(); 358 | PORTD = (PORTD & maskD) | valD; 359 | sei(); 360 | } else if (port == 1) { 361 | byte valB = (value & bitmask) & 0x3F; 362 | byte valC = (value & bitmask) >> 6; 363 | byte maskB = ~(bitmask & 0x3F); 364 | byte maskC = ~((bitmask & 0xC0) >> 6); 365 | cli(); 366 | PORTB = (PORTB & maskB) | valB; 367 | PORTC = (PORTC & maskC) | valC; 368 | sei(); 369 | } else if (port == 2) { 370 | bitmask = bitmask & 0x0F; 371 | byte valC = (value & bitmask) << 2; 372 | byte maskC = ~(bitmask << 2); 373 | cli(); 374 | PORTC = (PORTC & maskC) | valC; 375 | sei(); 376 | } 377 | #else 378 | byte pin=port*8; 379 | if ((bitmask & 0x01)) digitalWrite(PIN_TO_DIGITAL(pin+0), (value & 0x01)); 380 | if ((bitmask & 0x02)) digitalWrite(PIN_TO_DIGITAL(pin+1), (value & 0x02)); 381 | if ((bitmask & 0x04)) digitalWrite(PIN_TO_DIGITAL(pin+2), (value & 0x04)); 382 | if ((bitmask & 0x08)) digitalWrite(PIN_TO_DIGITAL(pin+3), (value & 0x08)); 383 | if ((bitmask & 0x10)) digitalWrite(PIN_TO_DIGITAL(pin+4), (value & 0x10)); 384 | if ((bitmask & 0x20)) digitalWrite(PIN_TO_DIGITAL(pin+5), (value & 0x20)); 385 | if ((bitmask & 0x40)) digitalWrite(PIN_TO_DIGITAL(pin+6), (value & 0x40)); 386 | if ((bitmask & 0x80)) digitalWrite(PIN_TO_DIGITAL(pin+7), (value & 0x80)); 387 | #endif 388 | } 389 | 390 | 391 | 392 | 393 | #ifndef TOTAL_PORTS 394 | #define TOTAL_PORTS ((TOTAL_PINS + 7) / 8) 395 | #endif 396 | 397 | 398 | #endif /* Firmata_Boards_h */ 399 | -------------------------------------------------------------------------------- /nRF51822-BLEMIDI/BLEParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Matthias Frick 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef ____BLEParser__ 24 | #define ____BLEParser__ 25 | #include 26 | #include 27 | #include 28 | 29 | namespace mfk 30 | { 31 | namespace midi 32 | { 33 | static int MIDI_STATE_TIMESTAMP = 0; 34 | static int MIDI_STATE_WAIT = 1; 35 | static int MIDI_STATE_SIGNAL_2BYTES_2 = 21; 36 | static int MIDI_STATE_SIGNAL_3BYTES_2 = 31; 37 | static int MIDI_STATE_SIGNAL_3BYTES_3 = 32; 38 | static int MIDI_STATE_SIGNAL_SYSEX = 41; 39 | 40 | // for Timestamp 41 | static int MAX_TIMESTAMP = 8192; 42 | static int BUFFER_LENGTH_MILLIS = 10; 43 | 44 | 45 | // for RPN/NRPN messages 46 | static int PARAMETER_MODE_NONE = 0; 47 | static int PARAMETER_MODE_RPN = 1; 48 | static int PARAMETER_MODE_NRPN = 2; 49 | int parameterMode = 0; 50 | int parameterNumber = 0x3fff; 51 | int parameterValue = 0x3fff; 52 | 53 | template 54 | class BLEMIDIParser 55 | { 56 | public: 57 | 58 | void parseMidiEvent(uint8_t header, const uint8_t event) 59 | { 60 | uint8_t midiEvent = event & 0xff; 61 | uint8_t timeToWait; 62 | // printf((char*)midiEvent); 63 | if (midiState == MIDI_STATE_TIMESTAMP) 64 | { 65 | // printf("Timestamp"); 66 | if ((midiEvent & 0x80) == 0) 67 | { 68 | // running status 69 | midiState = MIDI_STATE_WAIT; 70 | } 71 | 72 | if (midiEvent == 0xf7) 73 | { 74 | // make sure this is the end of sysex 75 | // and send alternative recovery stream 76 | if (sysExRecBufferPtr > 0) 77 | { 78 | uint8_t removed = replaceLastByteInRecoveryBuffer(midiEvent); 79 | sendSysexRecovery(); 80 | resetRecoveryBuffer(); 81 | } 82 | midiState = MIDI_STATE_TIMESTAMP; 83 | return; 84 | } 85 | else 86 | { 87 | // reset alternative sysex stream 88 | resetRecoveryBuffer(); 89 | } 90 | } // end of timestamp 91 | 92 | if (midiState == MIDI_STATE_TIMESTAMP) 93 | { 94 | timestamp = ((header & 0x3f) << 7) | (midiEvent & 0x7f); 95 | midiState = MIDI_STATE_WAIT; 96 | } 97 | else if (midiState == MIDI_STATE_WAIT) 98 | { 99 | switch (midiEvent & 0xf0) { 100 | case 0xf0: { 101 | switch (midiEvent) { 102 | case 0xf0: 103 | resetRecoveryBuffer(); 104 | resetSysExBuffer(); 105 | addByteToSysExBuffer(midiEvent); 106 | midiState = MIDI_STATE_SIGNAL_SYSEX; 107 | break; 108 | case 0xf1: 109 | case 0xf3: 110 | // 0xf1 MIDI Time Code Quarter Frame. : 2bytes 111 | // 0xf3 Song Select. : 2bytes 112 | midiEventKind = midiEvent; 113 | addByteToMidiBuffer(midiEvent); 114 | midiState = MIDI_STATE_SIGNAL_2BYTES_2; 115 | break; 116 | case 0xf2: 117 | // 0xf2 Song Position Pointer. : 3bytes 118 | midiEventKind = midiEvent; 119 | addByteToMidiBuffer(midiEvent); 120 | midiState = MIDI_STATE_SIGNAL_3BYTES_2; 121 | break; 122 | case 0xf6: 123 | // 0xf6 Tune Request : 1byte 124 | addByteToMidiBuffer(midiEvent); 125 | midiState = MIDI_STATE_TIMESTAMP; 126 | break; 127 | case 0xf8: 128 | // 0xf8 Timing Clock : 1byte 129 | #pragma mark send timeclock 130 | midiState = MIDI_STATE_TIMESTAMP; 131 | break; 132 | case 0xfa: 133 | // 0xfa Start : 1byte 134 | midiState = MIDI_STATE_TIMESTAMP; 135 | break; 136 | case 0xfb: 137 | // 0xfb Continue : 1byte 138 | midiState = MIDI_STATE_TIMESTAMP; 139 | break; 140 | case 0xfc: 141 | // 0xfc Stop : 1byte 142 | midiState = MIDI_STATE_TIMESTAMP; 143 | break; 144 | case 0xfe: 145 | // 0xfe Active Sensing : 1byte 146 | midiState = MIDI_STATE_TIMESTAMP; 147 | break; 148 | case 0xff: 149 | // 0xff Reset : 1byte 150 | midiState = MIDI_STATE_TIMESTAMP; 151 | break; 152 | 153 | default: 154 | break; 155 | } 156 | } 157 | break; 158 | case 0x80: 159 | case 0x90: 160 | case 0xa0: 161 | case 0xb0: 162 | case 0xe0: 163 | // 3bytes pattern 164 | midiEventKind = midiEvent; 165 | midiState = MIDI_STATE_SIGNAL_3BYTES_2; 166 | break; 167 | case 0xc0: // program change 168 | case 0xd0: // channel after-touch 169 | // 2bytes pattern 170 | midiEventKind = midiEvent; 171 | midiState = MIDI_STATE_SIGNAL_2BYTES_2; 172 | break; 173 | default: 174 | // 0x00 - 0x70: running status 175 | if ((midiEventKind & 0xf0) != 0xf0) { 176 | // previous event kind is multi-bytes pattern 177 | midiEventNote = midiEvent; 178 | midiState = MIDI_STATE_SIGNAL_3BYTES_3; 179 | } 180 | break; 181 | } 182 | } 183 | else if (midiState == MIDI_STATE_SIGNAL_2BYTES_2) 184 | { 185 | switch (midiEventKind & 0xf0) 186 | { 187 | // 2bytes pattern 188 | case 0xc0: // program change 189 | midiEventNote = midiEvent; 190 | midiState = MIDI_STATE_TIMESTAMP; 191 | break; 192 | case 0xd0: // channel after-touch 193 | midiEventNote = midiEvent; 194 | midiState = MIDI_STATE_TIMESTAMP; 195 | break; 196 | case 0xf0: 197 | { 198 | switch (midiEventKind) 199 | { 200 | case 0xf1: 201 | // 0xf1 MIDI Time Code Quarter Frame. : 2bytes 202 | midiEventNote = midiEvent; 203 | addByteToMidiBuffer(midiEventNote); 204 | sendMidi(2); 205 | resetMidiBuffer(); 206 | midiState = MIDI_STATE_TIMESTAMP; 207 | break; 208 | case 0xf3: 209 | // 0xf3 Song Select. : 2bytes 210 | midiEventNote = midiEvent; 211 | addByteToMidiBuffer(midiEventNote); 212 | sendMidi(2); 213 | resetMidiBuffer(); 214 | midiState = MIDI_STATE_TIMESTAMP; 215 | break; 216 | default: 217 | // illegal state 218 | midiState = MIDI_STATE_TIMESTAMP; 219 | break; 220 | } 221 | } 222 | break; 223 | default: 224 | // illegal state 225 | midiState = MIDI_STATE_TIMESTAMP; 226 | break; 227 | } 228 | } 229 | else if (midiState == MIDI_STATE_SIGNAL_3BYTES_2) 230 | { 231 | switch (midiEventKind & 0xf0) 232 | { 233 | case 0x80: 234 | case 0x90: 235 | case 0xa0: 236 | case 0xb0: 237 | case 0xe0: 238 | case 0xf0: 239 | // 3bytes pattern 240 | midiEventNote = midiEvent; 241 | midiState = MIDI_STATE_SIGNAL_3BYTES_3; 242 | break; 243 | default: 244 | // illegal state 245 | midiState = MIDI_STATE_TIMESTAMP; 246 | break; 247 | } 248 | } 249 | else if (midiState == MIDI_STATE_SIGNAL_3BYTES_3) 250 | { 251 | switch (midiEventKind & 0xf0) 252 | { 253 | // 3bytes pattern 254 | case 0x80: // note off 255 | midiEventVelocity = midiEvent; 256 | addByteToMidiBuffer(midiEventKind); 257 | addByteToMidiBuffer(midiEventNote); 258 | addByteToMidiBuffer(midiEventVelocity); 259 | sendMidi(3); 260 | resetMidiBuffer(); 261 | midiState = MIDI_STATE_TIMESTAMP; 262 | break; 263 | case 0x90: // note on 264 | midiEventVelocity = midiEvent; 265 | //timeToWait = calculateTimeToWait(timestamp); 266 | addByteToMidiBuffer(midiEventKind); 267 | addByteToMidiBuffer(midiEventNote); 268 | addByteToMidiBuffer(midiEventVelocity); 269 | sendMidi(3); 270 | resetMidiBuffer(); 271 | midiState = MIDI_STATE_TIMESTAMP; 272 | break; 273 | case 0xa0: // control polyphonic key pressure 274 | midiEventVelocity = midiEvent; 275 | addByteToMidiBuffer(midiEventKind); 276 | addByteToMidiBuffer(midiEventNote); 277 | addByteToMidiBuffer(midiEventVelocity); 278 | sendMidi(3); 279 | resetMidiBuffer(); 280 | midiState = MIDI_STATE_TIMESTAMP; 281 | break; 282 | case 0xb0: // control change 283 | midiEventVelocity = midiEvent; 284 | switch (midiEventNote & 0x7f) 285 | { 286 | case 98: 287 | // NRPN LSB 288 | parameterNumber &= 0x3f80; 289 | parameterNumber |= midiEventVelocity & 0x7f; 290 | parameterMode = PARAMETER_MODE_NRPN; 291 | break; 292 | case 99: 293 | // NRPN MSB 294 | parameterNumber &= 0x007f; 295 | parameterNumber |= (midiEventVelocity & 0x7f) << 7; 296 | parameterMode = PARAMETER_MODE_NRPN; 297 | break; 298 | case 100: 299 | // RPN LSB 300 | parameterNumber &= 0x3f80; 301 | parameterNumber |= midiEventVelocity & 0x7f; 302 | parameterMode = PARAMETER_MODE_RPN; 303 | break; 304 | case 101: 305 | // RPN MSB 306 | parameterNumber &= 0x007f; 307 | parameterNumber |= (midiEventVelocity & 0x7f) << 7; 308 | parameterMode = PARAMETER_MODE_RPN; 309 | break; 310 | case 38: 311 | // data LSB 312 | parameterValue &= 0x3f80; 313 | parameterValue |= midiEventVelocity & 0x7f; 314 | 315 | if (parameterNumber != 0x3fff) { 316 | if (parameterMode == PARAMETER_MODE_RPN) 317 | { 318 | addByteToMidiBuffer(midiEventKind); 319 | addByteToMidiBuffer(parameterNumber); 320 | addByteToMidiBuffer(parameterValue); 321 | sendMidi(3); 322 | resetMidiBuffer(); 323 | } 324 | else if (parameterMode == PARAMETER_MODE_NRPN) 325 | { 326 | addByteToMidiBuffer(midiEventKind); 327 | addByteToMidiBuffer(parameterNumber); 328 | addByteToMidiBuffer(parameterValue); 329 | sendMidi(3); 330 | resetMidiBuffer(); 331 | } 332 | } 333 | break; 334 | case 6: 335 | // data MSB 336 | parameterValue &= 0x007f; 337 | parameterValue |= (midiEventVelocity & 0x7f) << 7; 338 | 339 | if (parameterNumber != 0x3fff) 340 | { 341 | if (parameterMode == PARAMETER_MODE_RPN) 342 | { 343 | addByteToMidiBuffer(midiEventKind); 344 | addByteToMidiBuffer(parameterNumber); 345 | addByteToMidiBuffer(parameterValue); 346 | sendMidi(3); 347 | resetMidiBuffer(); 348 | } 349 | else if (parameterMode == PARAMETER_MODE_NRPN) 350 | { 351 | addByteToMidiBuffer(midiEventKind); 352 | addByteToMidiBuffer(parameterNumber); 353 | addByteToMidiBuffer(parameterValue); 354 | sendMidi(3); 355 | resetMidiBuffer(); 356 | } 357 | } 358 | break; 359 | default: 360 | // do nothing 361 | break; 362 | } 363 | addByteToMidiBuffer(midiEventKind); 364 | addByteToMidiBuffer(midiEventNote); 365 | addByteToMidiBuffer(midiEventVelocity); 366 | sendMidi(3); 367 | resetMidiBuffer(); 368 | midiState = MIDI_STATE_TIMESTAMP; 369 | break; 370 | case 0xe0: // pitch bend 371 | midiEventVelocity = midiEvent; 372 | addByteToMidiBuffer(midiEventKind); 373 | addByteToMidiBuffer(midiEventNote); 374 | addByteToMidiBuffer(midiEventVelocity); 375 | sendMidi(3); 376 | resetMidiBuffer(); 377 | midiState = MIDI_STATE_TIMESTAMP; 378 | break; 379 | case 0xf0: // Song Position Pointer. 380 | midiEventVelocity = midiEvent; 381 | addByteToMidiBuffer(midiEventKind); 382 | addByteToMidiBuffer(midiEventNote); 383 | addByteToMidiBuffer(midiEventVelocity); 384 | sendMidi(3); 385 | resetMidiBuffer(); 386 | midiState = MIDI_STATE_TIMESTAMP; 387 | break; 388 | default: 389 | // illegal state 390 | midiState = MIDI_STATE_TIMESTAMP; 391 | break; 392 | } 393 | } 394 | else if (midiState == MIDI_STATE_SIGNAL_SYSEX) 395 | { 396 | if (midiEvent == 0xf7) 397 | { 398 | uint8_t repEvt = replaceLastByteInSysExBuffer(midiEvent); 399 | 400 | resetRecoveryBuffer(); 401 | createSysExRecovery(); 402 | replaceLastByteInRecoveryBuffer(repEvt); 403 | addByteToRecoveryBuffer(midiEvent); 404 | sendSysex(); 405 | resetSysExBuffer(); 406 | midiState = MIDI_STATE_TIMESTAMP; 407 | } 408 | else 409 | { 410 | addByteToSysExBuffer(midiEvent); 411 | } 412 | 413 | } 414 | } 415 | void setUSBMidiHandle(Receiver *MidiHdl) 416 | { 417 | midiRecv = MidiHdl; 418 | } 419 | 420 | private: 421 | 422 | void addByteToMidiBuffer(uint8_t midiEvent) 423 | { 424 | midiBuffer[midiBufferPtr] = midiEvent; 425 | midiBufferPtr++; 426 | } 427 | 428 | void addByteToSysExBuffer(uint8_t midiEvent) 429 | { 430 | sysExBuffer[sysExBufferPtr] = midiEvent; 431 | sysExBufferPtr++; 432 | } 433 | 434 | uint8_t replaceLastByteInSysExBuffer(uint8_t midiEvent) 435 | { 436 | sysExBufferPtr--; 437 | uint8_t lastEvt = sysExBuffer[sysExBufferPtr]; 438 | sysExBuffer[sysExBufferPtr] = midiEvent; 439 | sysExBufferPtr++; 440 | return lastEvt; 441 | } 442 | 443 | void sendSysex() 444 | { 445 | midiRecv->SendSysEx(sysExBuffer, sysExBufferPtr, 0); 446 | } 447 | 448 | void createSysExRecovery() 449 | { 450 | sysExRecBufferPtr = sysExBufferPtr; 451 | memcpy(alterSysExBuffer, sysExBuffer, sysExBufferPtr); 452 | } 453 | 454 | void sendSysexRecovery() 455 | { 456 | midiRecv->SendSysEx(alterSysExBuffer, sysExRecBufferPtr, 0); 457 | } 458 | 459 | uint8_t replaceLastByteInRecoveryBuffer(uint8_t midiEvent) 460 | { 461 | sysExRecBufferPtr--; 462 | uint8_t lastEvt = alterSysExBuffer[sysExRecBufferPtr]; 463 | alterSysExBuffer[sysExRecBufferPtr] = midiEvent; 464 | sysExRecBufferPtr++; 465 | return lastEvt; 466 | } 467 | 468 | void addByteToRecoveryBuffer(uint8_t midiEvent) 469 | { 470 | alterSysExBuffer[sysExRecBufferPtr] = midiEvent; 471 | sysExRecBufferPtr++; 472 | } 473 | 474 | void resetMidiBuffer() 475 | { 476 | memset(&midiBuffer[0], 0, sizeof(midiBuffer)); 477 | midiBufferPtr = 0; 478 | } 479 | 480 | void resetSysExBuffer() 481 | { 482 | memset(&sysExBuffer[0], 0, kMaxBufferSize); 483 | sysExBufferPtr = 0; 484 | } 485 | 486 | void resetRecoveryBuffer() 487 | { 488 | memset(&alterSysExBuffer[0], 0, sizeof(alterSysExBuffer)); 489 | sysExRecBufferPtr = 0; 490 | } 491 | 492 | void sendMidi(uint8_t size) 493 | { 494 | midiRecv->SendData(midiBuffer, 0); 495 | } 496 | 497 | uint8_t midiBuffer[3]; 498 | uint8_t sysExBuffer[kMaxBufferSize]; 499 | uint8_t alterSysExBuffer[kMaxBufferSize]; 500 | int midiBufferPtr = 0; 501 | int sysExRecBufferPtr = 0; 502 | int sysExBufferPtr = 0; 503 | 504 | 505 | // MIDI event messages, state & stamps 506 | int midiEventKind; 507 | int midiEventNote; 508 | int midiEventVelocity; 509 | int midiState = MIDI_STATE_TIMESTAMP; 510 | int timestamp; 511 | 512 | 513 | bool useTimestamp = true; 514 | int lastTimestamp; 515 | long lastTimestampRecorded = 0; 516 | int zeroTimestampCount = 0; 517 | Receiver *midiRecv; 518 | }; 519 | } 520 | } 521 | 522 | #endif /* defined(____BLEParser__) */ 523 | --------------------------------------------------------------------------------