forked from mooshim/Mooshimeter-IOSApp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOADProfile.m
188 lines (145 loc) · 6.61 KB
/
OADProfile.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
BLETIOADProfile.m
TIOADExample
Created by Ole Andreas Torvmark on 11/22/12.
Copyright (c) 2013 Texas Instruments. All rights reserved.
*/
#import "OADProfile.h"
#import "BLEUtility.h"
@implementation OADProfile
-(id) init:(NSString*) filename {
self = [super init];
if (self) {
self.canceled = FALSE;
self.inProgramming = FALSE;
self.start = YES;
self.imageFile = [NSData dataWithContentsOfFile:filename];
NSLog(@"Loaded firmware \"%@\"of size : %d",filename,self.imageFile.length);
[self.imageFile getBytes:&self->imageHeader length:sizeof(img_hdr_t)];
}
return self;
}
-(void) startUpload {
NSLog(@"Configuring OAD Profile");
self.start = YES;
LGCharacteristic* image_notify = [g_meter getLGChar:OAD_IMAGE_NOTIFY];
LGCharacteristic* image_block = [g_meter getLGChar:OAD_IMAGE_BLOCK_REQ];
self.pacer_sem = dispatch_semaphore_create(8);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleDisconnect:)
name:kLGPeripheralDidDisconnect
object:nil];
[image_block setNotifyValue:YES completion:^(NSError *error) {
[image_notify setNotifyValue:YES completion:^(NSError *error) {
[self uploadImage];
} onUpdate:^(NSData *data, NSError *error) {
NSLog(@"OAD Notify: %@", data);
}];
} onUpdate:^(NSData *data, NSError *error) {
uint16 bn;
[data getBytes:&bn length:2];
NSLog(@"Received block notification %d",bn);
dispatch_semaphore_signal(self.pacer_sem);
}];
}
-(void)handleDisconnect:(NSNotification *) notification {
[[NSNotificationCenter defaultCenter] removeObserver:self];
if(self.iBlocks == self.nBlocks) {
// We finished before disconnecting, don't display a failure.
}
[self.navCtrl popToRootViewControllerAnimated:YES];
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"FW Upgrade Failed !" message:@"Device disconnected during programming, firmware upgrade was not finished !" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
alertView.tag = 0;
[alertView show];
self.inProgramming = NO;
self.canceled = YES;
}
-(void) uploadImage {
self.inProgramming = YES;
self.canceled = NO;
unsigned char imageFileData[self.imageFile.length];
[self.imageFile getBytes:imageFileData length:self.imageFile.length];
uint8_t requestData[OAD_IMG_HDR_SIZE + 2 + 2]; // 12Bytes
for(int ii = 0; ii < 20; ii++) {
NSLog(@"%02hhx",imageFileData[ii]);
}
img_hdr_t imgHeader;
memcpy(&imgHeader, &imageFileData[0 + OAD_IMG_HDR_OSET], sizeof(img_hdr_t));
requestData[0] = LO_UINT16(imgHeader.ver);
requestData[1] = HI_UINT16(imgHeader.ver);
requestData[2] = LO_UINT16(imgHeader.len);
requestData[3] = HI_UINT16(imgHeader.len);
NSLog(@"Image version = %04hx, len = %04hx",imgHeader.ver,imgHeader.len);
memcpy(requestData + 4, &imgHeader.build_time, sizeof(imgHeader.build_time));
requestData[OAD_IMG_HDR_SIZE + 0] = LO_UINT16(12);
requestData[OAD_IMG_HDR_SIZE + 1] = HI_UINT16(12);
requestData[OAD_IMG_HDR_SIZE + 2] = LO_UINT16(15);
requestData[OAD_IMG_HDR_SIZE + 1] = HI_UINT16(15);
LGCharacteristic* image_notify = [g_meter getLGChar:OAD_IMAGE_NOTIFY];
[image_notify writeValue:[NSData dataWithBytes:requestData length:OAD_IMG_HDR_SIZE + 2 + 2] completion:nil];
self.nBlocks = imgHeader.len / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE);
self.nBytes = imgHeader.len * HAL_FLASH_WORD_SIZE;
self.iBlocks = 0;
self.iBytes = 0;
if (self.start) {
self.start = NO;
[self.navCtrl pushViewController:self.progressView animated:YES];
}
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgressBars:) userInfo:nil repeats:YES];
dispatch_queue_t rq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_async(rq, ^{
[self sendNextBlock];
});
}
-(void)sendNextBlock {
if (self.canceled) {
self.canceled = FALSE;
return;
}
unsigned char imageFileData[self.imageFile.length];
[self.imageFile getBytes:imageFileData length:self.imageFile.length];
NSLog(@"Sending block %d of %d", self.iBlocks, self.nBlocks);
//Prepare Block
uint8_t requestData[2 + OAD_BLOCK_SIZE];
requestData[0] = LO_UINT16(self.iBlocks);
requestData[1] = HI_UINT16(self.iBlocks);
memcpy(&requestData[2] , &imageFileData[self.iBytes], OAD_BLOCK_SIZE);
LGCharacteristic* image_block_req = [g_meter getLGChar:OAD_IMAGE_BLOCK_REQ];
dispatch_semaphore_wait(self.pacer_sem, DISPATCH_TIME_FOREVER);
[image_block_req writeValue:[NSData dataWithBytes:requestData length:2 + OAD_BLOCK_SIZE] completion:nil];
self.iBlocks++;
self.iBytes += OAD_BLOCK_SIZE;
if(self.iBlocks == self.nBlocks) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self.navCtrl popToRootViewControllerAnimated:YES];
self.inProgramming = NO;
dispatch_queue_t mq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(mq, ^{
[self completionDialog];
});
return;
}
dispatch_queue_t rq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_async(rq, ^{
[self sendNextBlock];
});
}
-(void) updateProgressBars:(NSTimer *)timer {
dispatch_async(dispatch_get_main_queue(), ^{
if(self.canceled || !self.inProgramming) {
[timer invalidate];
}
NSLog(@"Updating progress bars...");
float secondsPerBlock = 0.03 / 4;
float secondsLeft = (float)(self.nBlocks - self.iBlocks) * secondsPerBlock;
self.progressView.progressBar.progress = (float)((float)self.iBlocks / (float)self.nBlocks);
self.progressView.label1.text = [NSString stringWithFormat:@"%0.1f%%",(float)((float)self.iBlocks / (float)self.nBlocks) * 100.0f];
self.progressView.label2.text = [NSString stringWithFormat:@"Time remaining : %d:%02d",(int)(secondsLeft / 60),(int)secondsLeft - (int)(secondsLeft / 60) * (int)60];
});
}
-(void) completionDialog {
UIAlertView *complete;
complete = [[UIAlertView alloc]initWithTitle:@"Firmware upgrade complete" message:@"Firmware upgrade was successfully completed, device needs to be reconnected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[complete show];
}
@end