Changeset 9015b1e in orbit for iOS


Ignore:
Timestamp:
07/19/13 15:59:47 (7 years ago)
Author:
Jonathon Horsman <jonathon@…>
Branches:
master, RawEEG, Servo, Tab_Interface, pyramid
Children:
ce0a7ee, c61115c
Parents:
ab9d63b
Message:

UI working with headset correctly now.
Check Bluetooth enabled and volume at full

Location:
iOS/Orbit
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • iOS/Orbit/Orbit/AppDelegate.m

    rab9d63b r9015b1e  
    2121{ 
    2222    // Override point for customization after application launch. 
     23    NSLog(@"didFinsihLaunching - signal convertor init"); 
    2324    signalConverter = [[SignalConverter alloc] init]; 
    2425//    [[TGAccessoryManager sharedTGAccessoryManager] setupManagerWithInterval:0.05]; 
     
    3334//    ViewController *rootController = (ViewController *)self.window.rootViewController; 
    3435//    [rootController appClosed]; 
     36    [signalConverter appStopped]; 
     37    NSLog(@"Application will resign active - appClosed"); 
    3538} 
    3639 
     
    4952{ 
    5053    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    51 //    ViewController *rootController = (ViewController *)self.window.rootViewController; 
    52 //    [rootController appForegrounded]; 
    5354} 
    5455 
     
    5657{ 
    5758    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     59    NSLog(@"Application will terminate - teardownManager"); 
    5860    [[TGAccessoryManager sharedTGAccessoryManager] teardownManager]; 
    5961} 
  • iOS/Orbit/Orbit/SignalConverter.h

    rab9d63b r9015b1e  
    2525- (void) setValuesForAttention:(float) attention meditation:(float) meditation; 
    2626- (void) prepare; 
    27 - (void) startProcessing; 
     27- (BOOL) startProcessing; 
    2828- (void) stopProcessing; 
    29 - (void) appClosed; 
     29- (void) appStopped; 
     30- (BOOL) isBluetoothReady; 
     31- (BOOL) isVolumeMax; 
    3032 
    3133@end 
  • iOS/Orbit/Orbit/SignalConverter.m

    rab9d63b r9015b1e  
    1313#define ATTENTION_KEY @"eSenseAttention" 
    1414#define MEDITATION_KEY @"eSenseMeditation" 
     15 
     16#define CHANNEL_A 1 
    1517 
    1618// Converts signals received from the EEG headset to the audio played to fly the helicopter. 
     
    2931@synthesize attentionThreshold, meditationThreshold, running; 
    3032 
     33 
     34- (id) init 
     35{ 
     36    self = [super init]; 
     37    if (self) 
     38    { 
     39        [[TGAccessoryManager sharedTGAccessoryManager] setupManagerWithInterval:0.05]; 
     40        [[TGAccessoryManager sharedTGAccessoryManager] setDelegate:self]; 
     41    } 
     42    return self; 
     43} 
     44 
    3145- (void) setValuesForAttention:(float) attention meditation:(float) meditation 
    3246{ 
     
    4559} 
    4660 
    47 - (void) appClosed 
    48 { 
    49     if ([[TGAccessoryManager sharedTGAccessoryManager] connected]) { 
     61- (void) appStopped 
     62{ 
     63    running = NO; 
     64    if ([TGAccessoryManager sharedTGAccessoryManager].accessory != nil) { 
    5065        [[TGAccessoryManager sharedTGAccessoryManager] stopStream]; 
     66    } 
     67    [audioPlayer stop]; 
     68    if (_delegate != nil) { 
     69        [_delegate appStopped]; 
    5170    } 
    5271} 
     
    105124// The headset was switched on, start the data stream 
    106125- (void)accessoryDidConnect:(EAAccessory *)accessory { 
    107     if (_delegate != nil) 
    108     { 
    109         [_delegate notifyHeadsetConnect]; 
    110     } 
    111     if ([[TGAccessoryManager sharedTGAccessoryManager] accessory] != nil) { 
    112         [[TGAccessoryManager sharedTGAccessoryManager] startStream]; 
    113     } 
    114126} 
    115127 
     
    122134} 
    123135 
     136- (BOOL) isBluetoothReady 
     137{ 
     138    return [[TGAccessoryManager sharedTGAccessoryManager] accessory] != NULL; 
     139} 
     140 
     141- (BOOL) isVolumeMax 
     142{ 
     143    float volume = [[AVAudioSession sharedInstance] outputVolume]; 
     144//    Float32 volume; 
     145//    UInt32 dataSize = sizeof(Float32); 
     146//     
     147//    AudioSessionGetProperty ( 
     148//                             kAudioSessionProperty_CurrentHardwareOutputVolume, 
     149//                             &dataSize, 
     150//                             &volume 
     151//                             ); 
     152    return volume == 1.0; 
     153} 
     154 
    124155#pragma mark start / stop methods 
    125156 
    126 - (void) startProcessing 
    127 { 
    128     running = YES; 
     157- (BOOL) startProcessing 
     158{ 
    129159    EAAccessory *accessory = [[TGAccessoryManager sharedTGAccessoryManager] accessory]; 
    130160    if (accessory != nil) { 
    131         if (_delegate != nil) 
    132         { 
     161        running = YES; 
     162        if (_delegate != nil) { 
    133163            [_delegate notifyDeviceConnected: accessory.name]; 
    134164        } 
    135165        [[TGAccessoryManager sharedTGAccessoryManager] startStream]; 
    136166    } 
     167    return running; 
    137168} 
    138169 
    139170- (void) stopProcessing 
    140171{ 
    141     running = NO; 
    142     if ([[TGAccessoryManager sharedTGAccessoryManager] connected]) { 
    143         [[TGAccessoryManager sharedTGAccessoryManager] stopStream]; 
    144     } 
    145     [audioPlayer stop]; 
     172    [self appStopped]; 
    146173    [self prepare];     
    147174} 
     
    202229} 
    203230 
     231// calculate the checksum for the generated code used to generate the WAV array 
     232- (int) codeChecksum:(int)code 
     233{ 
     234    int checksum = 0; 
     235    for (int i = 0; i < 7; i++) { 
     236        checksum += (code >> 4*i) & 15; 
     237    } 
     238    return 16 - (checksum & 15); 
     239} 
     240 
     241// Generate the code used to create the WAV file based on the given throttle, yaw and pitch. 
     242// Copied from AudioService.java in the Android app 
     243// throttle: 0~127, nothing will happen if this value is below 30. 
     244// yaw: 0~127, normally 78 will keep orbit from rotating. 
     245// pitch: 0~63, normally 31 will stop the top propeller. 
     246// channel: 1=Channel A, 0=Channel B 2= Channel C, depend on which channel you want to pair to the orbit. You can fly at most 3 orbit in a same room. 
     247- (int) generateCodeFromThrottle: (int)throttle yaw: (int)yaw pitch: (int)pitch channel: (int)channel 
     248{ 
     249    int code = (throttle << 21) + 1048576 + (yaw << 12) + (pitch << 4) + (((channel >> 1) & 1) << 19) + ((channel & 1) << 11); 
     250    return code;// + codeChecksum(code); 
     251} 
     252 
    204253@end 
  • iOS/Orbit/Orbit/SignalConverterDelegate.h

    rab9d63b r9015b1e  
    1919- (void) notifyHeadsetDisconnect; 
    2020- (void) notifyDeviceConnected:(NSString *)name; 
     21- (void) appStopped; 
    2122@end 
  • iOS/Orbit/Orbit/controllers/FlightViewController.m

    rab9d63b r9015b1e  
    2323@implementation FlightViewController { 
    2424    SignalConverter *signalConverter; 
     25    int deviceStatus; 
    2526} 
    2627 
    27 @synthesize status, attention, meditation, signal, power, attentionThreshold, meditationThreshold, connectButton, statusImage; 
     28@synthesize status, attention, meditation, signal, power, attentionThreshold, meditationThreshold, connectButton, statusImage, signalPercent, attentionPercent, meditationPercent, powerPercent; 
    2829 
    2930- (void)viewDidLoad 
     
    3940} 
    4041 
    41 // Start the data stream from the bluetooth headset if it's attached, and reset the display output 
    42 - (void) appForegrounded 
    43 { 
    44     [self resetViews]; // just in case it didn't happen on close 
    45 } 
    46  
    4742#pragma mark view updates 
    4843 
     
    5146{ 
    5247    signal.progress = 0; 
     48    signalPercent.text = @"0%"; 
    5349    attention.progress = 0; 
     50    attentionPercent.text = @"0%"; 
    5451    meditation.progress = 0; 
     52    meditationPercent.text = @"0%"; 
    5553    power.progress = 0; 
     54    powerPercent.text = @"0%"; 
    5655    [self logMessage:@"Disconnected"]; 
     56    [self updateStatusImage:STATUS_DEFAULT]; 
     57    connectButton.title = @"Connect"; 
    5758} 
    5859 
    5960- (void) updateStatusImage:(int) statusNo 
    6061{ 
    61     [statusImage setImage: [UIImage imageNamed:[NSString stringWithFormat:@"status_%u", statusNo]]]; 
     62    if (statusNo != deviceStatus) { 
     63        [statusImage setImage: [UIImage imageNamed:[NSString stringWithFormat:@"status_%u", statusNo]]]; 
     64        deviceStatus = statusNo; 
     65        if (statusNo == STATUS_CONNECTED) { 
     66            [self logMessage:@"Check headset fitted properly"]; 
     67        } else if (statusNo == STATUS_PROCESSING) { 
     68            [self logMessage:@"Increase your concentration"]; 
     69        } else if (statusNo == STATUS_ACTIVE) { 
     70            [self logMessage:@"Flying!"]; 
     71        } 
     72    } 
    6273} 
    6374 
     
    6576{ 
    6677    [signalConverter setValuesForAttention:attentionThreshold.value meditation:meditationThreshold.value]; 
    67 //     
    68 //    if (attentionThreshold.value < 0.2) { 
    69 //        [self updateStatusImage:STATUS_DEFAULT]; 
    70 //    } else if (attentionThreshold.value < 0.4) { 
    71 //        [self updateStatusImage:STATUS_CONNECTING]; 
    72 //    } else if (attentionThreshold.value < 0.6) { 
    73 //        [self updateStatusImage:STATUS_CONNECTED]; 
    74 //    } else if (attentionThreshold.value < 0.8) { 
    75 //        [self updateStatusImage:STATUS_PROCESSING]; 
    76 //    } else { 
    77 //        [self updateStatusImage:STATUS_ACTIVE]; 
    78 //    } 
    7978} 
    8079 
     
    9998    self.power.progress = powerLevel; 
    10099    self.powerPercent.text = [NSString stringWithFormat:@"%i%%", (int)(powerLevel * 100)]; 
     100    [self updateStatusImage:[self statusFromSignal:signalStrength power:powerLevel]]; 
     101} 
     102 
     103- (int) statusFromSignal: (float)signalLevel power:(float)powerLevel 
     104{ 
     105    if (signalLevel < 0.9) { // weak signal 
     106        return STATUS_CONNECTED; 
     107    } else if (powerLevel == 0.0) { // strong signal but thresholds not met 
     108        return STATUS_PROCESSING; 
     109    } else { // flight command sent to orbit 
     110        return STATUS_ACTIVE; 
     111    } 
    101112} 
    102113 
    103114- (void) notifyHeadsetConnect 
    104115{ 
    105     [self logMessage:@"Headet connected"]; 
     116    [self logMessage:@"Headset connected"]; 
     117    [self updateStatusImage:STATUS_CONNECTING]; 
    106118} 
    107119 
     
    110122    // Reset the outputs back to zero 
    111123    [self resetViews]; 
    112     [self logMessage:@"Headet disconnected"];     
    113124} 
    114125 
    115126- (void) notifyDeviceConnected:(NSString *)name 
    116127{ 
    117     [self logMessage:[NSString stringWithFormat:@"EEG device %@ connected", name]];     
     128    [self logMessage:[NSString stringWithFormat:@"EEG device %@ connected", name]]; 
     129    [self updateStatusImage:STATUS_CONNECTING]; 
     130    connectButton.title = @"Disconnect"; 
     131} 
     132 
     133- (void) appStopped 
     134{ 
     135    [self resetViews]; // just in case it didn't happen on close 
    118136} 
    119137 
     
    124142    if (signalConverter.running) { 
    125143        [signalConverter stopProcessing]; 
    126         connectButton.title = @"Connect"; 
    127144        [self resetViews]; 
     145    } else if (!signalConverter.isBluetoothReady) { 
     146        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Device not found" message:@"No Bluetooth device detected. Ensure Bluetooth is on and the Mindwave headset is paired" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     147        [alert show]; 
     148    } else if (!signalConverter.isVolumeMax) { 
     149        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Turn Up The Volume" message:@"Your device volume must be at the maximum for proper operation" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     150        [alert show]; 
     151    } else if ([signalConverter startProcessing]) { 
     152        [self logMessage:@"Searching for device"]; 
     153//        [self updateStatusImage:STATUS_CONNECTING]; 
     154        connectButton.title = @"Disconnect"; 
    128155    } else { 
    129         [self logMessage:@"Searching for device"]; 
    130         [signalConverter startProcessing]; 
    131         connectButton.title = @"Disconnect"; 
     156        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to connect" message:@"Check the device is correctly paired on Bluetooth" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     157        [alert show]; 
    132158    } 
    133159} 
  • iOS/Orbit/Orbit/en.lproj/MainStoryboard.storyboard

    rab9d63b r9015b1e  
    385385                    <navigationItem key="navigationItem" id="iTN-dz-EXc"/> 
    386386                    <connections> 
     387                        <outlet property="attention" destination="Dly-NW-R1i" id="XDF-jJ-Fgu"/> 
    387388                        <outlet property="attentionPercent" destination="bZn-rG-svm" id="1Ap-Cq-hIM"/> 
    388389                        <outlet property="attentionThreshold" destination="ym8-zN-dSb" id="baB-wY-lJS"/> 
    389390                        <outlet property="connectButton" destination="Lwp-ZU-iKO" id="zdp-si-XhL"/> 
     391                        <outlet property="meditation" destination="tsc-gq-wnT" id="y0Z-Xa-LgD"/> 
    390392                        <outlet property="meditationPercent" destination="Rhw-9S-ZP1" id="Wws-f9-lVM"/> 
    391393                        <outlet property="meditationThreshold" destination="LJj-vt-JUw" id="UKy-Vg-8gL"/> 
     394                        <outlet property="power" destination="KeR-cO-90u" id="wwM-U5-g6n"/> 
    392395                        <outlet property="powerPercent" destination="ah9-c0-kCb" id="IF6-xV-7Xf"/> 
     396                        <outlet property="signal" destination="AuD-cU-2pt" id="uuu-hc-E2e"/> 
    393397                        <outlet property="signalPercent" destination="yYn-76-IoI" id="4Ei-JM-jZ1"/> 
    394398                        <outlet property="status" destination="BOS-Js-1rx" id="fDM-Of-lza"/> 
  • iOS/Orbit/orbit.xcodeproj/project.pbxproj

    rab9d63b r9015b1e  
    3838                28C10EEC16875BC100ECFD59 /* throttle_hover_ios.wav in Resources */ = {isa = PBXBuildFile; fileRef = 28C10EEB16875BC100ECFD59 /* throttle_hover_ios.wav */; }; 
    3939                28C10EF1168760CA00ECFD59 /* HOW_TO_USE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 28C10EF0168760CA00ECFD59 /* HOW_TO_USE.txt */; }; 
     40                28F901301799436F003FB5ED /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28F9012F1799436F003FB5ED /* CoreBluetooth.framework */; }; 
    4041                52922BA817004D1400A39146 /* libCorePlot-CocoaTouch.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 52922BA717004D1400A39146 /* libCorePlot-CocoaTouch.a */; }; 
    4142                52FA364416899B5D004C280A /* ic_launcher-57x57.png in Resources */ = {isa = PBXBuildFile; fileRef = 52FA364316899B5D004C280A /* ic_launcher-57x57.png */; }; 
     
    8889                28C10EEB16875BC100ECFD59 /* throttle_hover_ios.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = throttle_hover_ios.wav; sourceTree = "<group>"; }; 
    8990                28C10EF0168760CA00ECFD59 /* HOW_TO_USE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HOW_TO_USE.txt; sourceTree = "<group>"; }; 
     91                28F9012F1799436F003FB5ED /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; 
    9092                52922BA717004D1400A39146 /* libCorePlot-CocoaTouch.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libCorePlot-CocoaTouch.a"; sourceTree = "<group>"; }; 
    9193                52922BA917004D4400A39146 /* CorePlot-CocoaTouch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CorePlot-CocoaTouch.h"; sourceTree = "<group>"; }; 
     
    174176                        buildActionMask = 2147483647; 
    175177                        files = ( 
     178                                28F901301799436F003FB5ED /* CoreBluetooth.framework in Frameworks */, 
    176179                                52922BA817004D1400A39146 /* libCorePlot-CocoaTouch.a in Frameworks */, 
    177180                                2815BC15167F496C00F7E6DA /* QuartzCore.framework in Frameworks */, 
     
    205208                        isa = PBXGroup; 
    206209                        children = ( 
     210                                28F9012F1799436F003FB5ED /* CoreBluetooth.framework */, 
    207211                                289C7D0F178D7A21005C08EC /* Images */, 
    208212                                52FA364716899C63004C280A /* Default-568h@2x.png */, 
Note: See TracChangeset for help on using the changeset viewer.