source: orbit/iOS/Orbit/Orbit/controllers/FlightViewController.m @ 2246ba0

Servo
Last change on this file since 2246ba0 was 2246ba0, checked in by Steve Castellotti <sc@…>, 8 years ago
  • Property mode set to 100644
File size: 10.2 KB
RevLine 
[ab9d63b]1//
2//  FlightViewController.m
3//  Orbit
4//
5//  Copyright (c) 2013 Puzzlebox Productions, LLC. All rights reserved.
6//  Originally created by Jonathon Horsman.
7//
8//  This code is released under the GNU Public License (GPL) version 2
9//  For more information please refer to http://www.gnu.org/copyleft/gpl.html
10//
11
12#import <QuartzCore/QuartzCore.h>
13#import "FlightViewController.h"
14#import "AppDelegate.h"
15#import "SignalConverter.h"
16
[2246ba0]17#import "StatisticsViewController.h"
18
[ab9d63b]19#define STATUS_DEFAULT 0
20#define STATUS_CONNECTING 1
21#define STATUS_CONNECTED 2
22#define STATUS_PROCESSING 3
23#define STATUS_ACTIVE 4
24
25@implementation FlightViewController {
[ad80ed2]26   SignalConverter *signalConverter;
27   int deviceStatus;
28   BOOL warned;
[ab9d63b]29}
30
[8a0f920f]31@synthesize attention, meditation, signal, power, attentionThreshold, meditationThreshold, connectButton, testButton, statusImage, signalPercent, attentionPercent, meditationPercent, powerPercent;
[ab9d63b]32
33- (void)viewDidLoad
34{
[ad80ed2]35   [super viewDidLoad];
36   
37   attention.progressTintColor = [UIColor redColor];
38   self.attentionThreshold.minimumTrackTintColor = [UIColor grayColor];
39   meditation.progressTintColor = [UIColor blueColor];
40   self.meditationThreshold.minimumTrackTintColor = [UIColor grayColor];
41   self.meditationThreshold.value = 0;
[ba2b6ff]42   
[ad80ed2]43   AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
44   signalConverter = appDelegate.signalConverter;
45   
46   signalConverter.delegate = self;
47   [self setThresholds];
48   [self.attentionThreshold addTarget:self action:@selector(setThresholds) forControlEvents:UIControlEventValueChanged];
49   [self.meditationThreshold addTarget:self action:@selector(setThresholds) forControlEvents:UIControlEventValueChanged];
[ad40faa]50   
[ab9d63b]51}
52
53#pragma mark view updates
54
55// Set all levels back to zero
56- (void) resetViews
57{
[ad80ed2]58   signal.progress = 0;
59   signalPercent.text = @"0%";
60   attention.progress = 0;
61   attentionPercent.text = @"0%";
62   meditation.progress = 0;
63   meditationPercent.text = @"0%";
64   power.progress = 0;
65   powerPercent.text = @"0%";
66   [self updateStatusImage:STATUS_DEFAULT];
67   connectButton.title = @"Connect";
[ab9d63b]68}
69
70- (void) updateStatusImage:(int) statusNo
71{
[ad80ed2]72   if (statusNo != deviceStatus) {
73      [statusImage setImage: [UIImage imageNamed:[NSString stringWithFormat:@"status_%u", statusNo]]];
74      deviceStatus = statusNo;
75   }
[ab9d63b]76}
77
[8a0f920f]78- (void) setThresholds
[ab9d63b]79{
[ad80ed2]80   [signalConverter setValuesForAttention:attentionThreshold.value meditation:meditationThreshold.value];
[ab9d63b]81}
82
83#pragma mark - SignalConverterDelegate methods
84
85- (void) updatedValuesForSignal: (float)signalStrength
86                      attention: (float)attentionLevel
87                     meditation: (float)meditationLevel
88                          power: (float)powerLevel
89{
[af91708]90   
[ad80ed2]91   // Set Attention and Meditation to zero if we've lost signal
92   if (signalStrength < 100.0) {
93      attentionLevel = 0.000000;
94      meditationLevel = 0.000000;
95      powerLevel = 0.000000;
96   }
[d249b65]97   
[ad80ed2]98   self.signal.progress = signalStrength / 100;
99   self.signalPercent.text = [NSString stringWithFormat:@"%i%%", (int)(signalStrength)];
100   self.attention.progress = attentionLevel;
101   self.attentionPercent.text = [NSString stringWithFormat:@"%i%%", (int)(attentionLevel * 100)];
102   self.meditation.progress = meditationLevel;
103   self.meditationPercent.text = [NSString stringWithFormat:@"%i%%", (int)(meditationLevel * 100)];
104   self.power.progress = powerLevel;
105   self.powerPercent.text = [NSString stringWithFormat:@"%i%%", (int)(powerLevel * 100)];
106   [self updateStatusImage:[self statusFromSignal:signalStrength power:powerLevel]];
[d249b65]107   
[b5aa714]108   [self updateScores];
109   
[9015b1e]110}
111
112- (int) statusFromSignal: (float)signalLevel power:(float)powerLevel
113{
[812f274]114   
[af91708]115   //   NSLog(@"signalLevel: %f | powerLevel: %f", signalLevel, powerLevel);
[812f274]116   
117   if (signalLevel == 0.0) { // no signal
118      return STATUS_CONNECTING;
119   }
120   
121   if (signalLevel < 100.0) { // poor signal
[ad80ed2]122      return STATUS_CONNECTED;
[812f274]123   }
124   
125   if (powerLevel == 0.0) { // strong signal but thresholds not met
[ad80ed2]126      return STATUS_PROCESSING;
127   } else { // flight command sent to orbit
128      return STATUS_ACTIVE;
129   }
[812f274]130   
[ab9d63b]131}
132
133- (void) notifyHeadsetConnect
134{
[ad80ed2]135   [self updateStatusImage:STATUS_CONNECTING];
[ab9d63b]136}
137
138- (void) notifyHeadsetDisconnect
139{
[ad80ed2]140   // Reset the outputs back to zero
141   [self resetViews];
[ab9d63b]142}
143
144- (void) notifyDeviceConnected:(NSString *)name
145{
[ad80ed2]146   [self updateStatusImage:STATUS_CONNECTING];
147   connectButton.title = @"Disconnect";
[9015b1e]148}
149
150- (void) appStopped
151{
[ad80ed2]152   [self resetViews]; // just in case it didn't happen on close
[ab9d63b]153}
154
155#pragma mark - button press events
156
157- (IBAction) connectButtonPressed:(id) sender {
[ad80ed2]158   
159   if (signalConverter.running) {
160      [signalConverter stopProcessing];
161      [self resetViews];
162   } else {
163      BOOL volumeMax  = [signalConverter isVolumeMax];
164      BOOL headphones = [signalConverter isAudioJackPlugged];
165     
166      if (!warned && !volumeMax && !headphones) {
167         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Check Volume & Transmitter" message:@"Ensure the volume is at max and the transmitter is plugged into the headphones" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
168         [alert show];
169      } else if (!warned && !volumeMax) {
170         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];
171         [alert show];
172      } else if (!warned && !headphones) {
173         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Plug In The Transmitter" message:@"Ensure the infrared transmitter is plugged into the headphone jack" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
174         [alert show];
175      } else if (!signalConverter.isBluetoothReady) {
176         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];
177         [alert show];
178      } else if ([signalConverter startProcessing]) {
179         connectButton.title = @"Disconnect";
180      } else {
181         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to connect" message:@"Check the device is correctly paired on Bluetooth" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
182         [alert show];
183      }
184      warned = YES;
185   }
[ab9d63b]186}
187
[de10cbc]188- (IBAction) testButtonPressed:(id) sender {
[4a56cfb]189   
[af91708]190   //   NSLog(@"Available fonts: %@", [UIFont familyNames]);
[4a56cfb]191   
[2246ba0]192//   StatisticsViewController *statisticsViewController=[[StatisticsViewController alloc] init];
193//   [statisticsViewController.graphBottom reloadData];
194   
[ad80ed2]195   [signalConverter isAudioJackPlugged];
196   if (signalConverter.running) {
[3434fbc]197      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Signal Processing Active" message:@"Please press the Disconnect button before sending a Test signal" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[ad80ed2]198      [alert show];
199   } else {
200      if (signalConverter.testing) {
201         testButton.title = @"Test";
202         [signalConverter stopTestSound];
203      } else {
204         testButton.title = @"Stop";
205         [signalConverter playTestSound];
206      }
207   }
[de10cbc]208}
209
[b5aa714]210- (void) updateScores
211{
[af91708]212   
[f45b70a]213   /**
214    * Score points based on target slider levels
215    * If you pass your goal with either Attention or Meditation
216    * the higher target of the two will counts as points per second.
217    *
218    * Minimum threshold for points is set as "minimumScoreTarget"
219    *
220    * For example, assume minimumScoreTarget is 40%.
221    * If your target Attention is 60% and you go past to reach 80%
222    * you will receive 20 points per second (60-40). If your
223    * target is 80% and you reach 80% you will receive 40
224    * points per second (80-40).
225    *
226    * You can set both Attention and Meditation targets at the
227    * same time. Reaching either will fly the helicopter but you
228    * will only receive points for the higher-scoring target of
229    * the two.
230    *
231    */
[b5aa714]232   
233   int eegAttentionScore = 0;
234   int eegAttention = self.attention.progress * 100;
235   int eegAttentionTarget = self.attentionThreshold.value * 100;
[af91708]236   
[b5aa714]237   int eegMeditationScore = 0;
238   int eegMeditation = self.meditation.progress * 100;
239   int eegMeditationTarget = self.meditationThreshold.value * 100;
240   
[af91708]241   
[b5aa714]242   if ((eegAttention >= eegAttentionTarget) &&
243       (eegAttentionTarget > minimumScoreTarget))
244      eegAttentionScore = eegAttentionTarget - minimumScoreTarget;
245   
246   if ((eegMeditation >= eegMeditationTarget) &&
247       (eegMeditationTarget > minimumScoreTarget))
248      eegMeditationScore = eegMeditationTarget - minimumScoreTarget;
249   
250   if (eegAttentionScore > eegMeditationScore)
251      scoreCurrent = scoreCurrent + eegAttentionScore;
252   else
253      scoreCurrent = scoreCurrent + eegMeditationScore;
254   
255   
[af91708]256   // High score
257   if (scoreCurrent > scoreHigh) {
258      scoreHigh = scoreCurrent;
259   }
[b5aa714]260   
[af91708]261   // Reset score
262   if (power.progress == 0)
263      [self resetCurrentScore];
[b5aa714]264   
[af91708]265   
266   // Catch anyone gaming the system with one slider
267   // below the minimum threshold and the other over.
268   // For example, setting Meditation to 1% will keep helicopter
269   // activated even if Attention is below target
270   if ((eegAttention < eegAttentionTarget) && (eegMeditation < minimumScoreTarget))
271      [self resetCurrentScore];
272   
273   if ((eegMeditation < eegMeditationTarget) && (eegAttention < minimumScoreTarget))
274      [self resetCurrentScore];
275   
276   if ((eegAttention < minimumScoreTarget) && (eegMeditation < minimumScoreTarget))
277      [self resetCurrentScore];
278   
279   
280   [self displayScore];
281   
[f45b70a]282}
[b5aa714]283
[af91708]284- (void) displayScore
285{
[c6dde93]286   
287   NSString* newScore = [NSString stringWithFormat:@"Scores      Current: %i    Last: %i    High: %i", (int)scoreCurrent, (int)scoreLast, (int)scoreHigh];
288   
289   if (newScore.length >= 50)
290      newScore = [NSString stringWithFormat:@"Scores  Current: %i  Last: %i  High: %i", (int)scoreCurrent, (int)scoreLast, (int)scoreHigh];
291
292   if (newScore.length >= 50)
293      newScore = [NSString stringWithFormat:@"Scores Current: %i Last: %i High: %i", (int)scoreCurrent, (int)scoreLast, (int)scoreHigh];
294
295   self.scoresDisplay.text = newScore;
[af91708]296}
[b5aa714]297
[af91708]298- (void) resetCurrentScore
299{
300   if (scoreCurrent > 0)
301      scoreLast = scoreCurrent;
302   
303   scoreCurrent = 0;
304   
[f45b70a]305}
[b5aa714]306
[ab9d63b]307@end
Note: See TracBrowser for help on using the repository browser.