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@…>, 6 years ago
  • Property mode set to 100644
File size: 10.2 KB
Line 
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
17#import "StatisticsViewController.h"
18
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 {
26   SignalConverter *signalConverter;
27   int deviceStatus;
28   BOOL warned;
29}
30
31@synthesize attention, meditation, signal, power, attentionThreshold, meditationThreshold, connectButton, testButton, statusImage, signalPercent, attentionPercent, meditationPercent, powerPercent;
32
33- (void)viewDidLoad
34{
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;
42   
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];
50   
51}
52
53#pragma mark view updates
54
55// Set all levels back to zero
56- (void) resetViews
57{
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";
68}
69
70- (void) updateStatusImage:(int) statusNo
71{
72   if (statusNo != deviceStatus) {
73      [statusImage setImage: [UIImage imageNamed:[NSString stringWithFormat:@"status_%u", statusNo]]];
74      deviceStatus = statusNo;
75   }
76}
77
78- (void) setThresholds
79{
80   [signalConverter setValuesForAttention:attentionThreshold.value meditation:meditationThreshold.value];
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{
90   
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   }
97   
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]];
107   
108   [self updateScores];
109   
110}
111
112- (int) statusFromSignal: (float)signalLevel power:(float)powerLevel
113{
114   
115   //   NSLog(@"signalLevel: %f | powerLevel: %f", signalLevel, powerLevel);
116   
117   if (signalLevel == 0.0) { // no signal
118      return STATUS_CONNECTING;
119   }
120   
121   if (signalLevel < 100.0) { // poor signal
122      return STATUS_CONNECTED;
123   }
124   
125   if (powerLevel == 0.0) { // strong signal but thresholds not met
126      return STATUS_PROCESSING;
127   } else { // flight command sent to orbit
128      return STATUS_ACTIVE;
129   }
130   
131}
132
133- (void) notifyHeadsetConnect
134{
135   [self updateStatusImage:STATUS_CONNECTING];
136}
137
138- (void) notifyHeadsetDisconnect
139{
140   // Reset the outputs back to zero
141   [self resetViews];
142}
143
144- (void) notifyDeviceConnected:(NSString *)name
145{
146   [self updateStatusImage:STATUS_CONNECTING];
147   connectButton.title = @"Disconnect";
148}
149
150- (void) appStopped
151{
152   [self resetViews]; // just in case it didn't happen on close
153}
154
155#pragma mark - button press events
156
157- (IBAction) connectButtonPressed:(id) sender {
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   }
186}
187
188- (IBAction) testButtonPressed:(id) sender {
189   
190   //   NSLog(@"Available fonts: %@", [UIFont familyNames]);
191   
192//   StatisticsViewController *statisticsViewController=[[StatisticsViewController alloc] init];
193//   [statisticsViewController.graphBottom reloadData];
194   
195   [signalConverter isAudioJackPlugged];
196   if (signalConverter.running) {
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];
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   }
208}
209
210- (void) updateScores
211{
212   
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    */
232   
233   int eegAttentionScore = 0;
234   int eegAttention = self.attention.progress * 100;
235   int eegAttentionTarget = self.attentionThreshold.value * 100;
236   
237   int eegMeditationScore = 0;
238   int eegMeditation = self.meditation.progress * 100;
239   int eegMeditationTarget = self.meditationThreshold.value * 100;
240   
241   
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   
256   // High score
257   if (scoreCurrent > scoreHigh) {
258      scoreHigh = scoreCurrent;
259   }
260   
261   // Reset score
262   if (power.progress == 0)
263      [self resetCurrentScore];
264   
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   
282}
283
284- (void) displayScore
285{
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;
296}
297
298- (void) resetCurrentScore
299{
300   if (scoreCurrent > 0)
301      scoreLast = scoreCurrent;
302   
303   scoreCurrent = 0;
304   
305}
306
307@end
Note: See TracBrowser for help on using the repository browser.