-
Notifications
You must be signed in to change notification settings - Fork 204
Expand file tree
/
Copy pathLeptonThread.cpp
More file actions
181 lines (147 loc) · 4.16 KB
/
LeptonThread.cpp
File metadata and controls
181 lines (147 loc) · 4.16 KB
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
#include "LeptonThread.h"
#include "stdio.h"
#include "Palettes.h"
#include "SPI.h"
#include "Lepton_I2C.h"
#include <errno.h>
//We are using a struct for the entire image, made up of 4 segments, 60 lines
//each, with 164 bytes of data. Allows easy use of sizeof() in code.
typedef struct __attribute__((packed)) _packet {
uint16_t packet_number;
uint16_t crc;
uint8_t video_src[160];
} packet;
typedef struct __attribute__((packed)) _segment {
packet line[60];
} segment;
typedef struct __attribute__((packed)) _image {
segment seg[4];
} image;
#define FPS (27)
#define HAND_TEMP_THRESHOLD 8050
int readyToToggle = 1;
LeptonThread::LeptonThread() : QThread(){}
LeptonThread::~LeptonThread() {}
void LeptonThread::run()
{
//Create the initial image and open the Spi port.
uint16_t spi_port = 1;
myImage = QImage(160, 120, QImage::Format_RGB888);
SpiOpenPort(spi_port);
uint32_t totalCounts = 0;
uint16_t minValue = 65535;
uint16_t maxValue = 0;
int resets = 0;
//Camera Loop
while (true) {
int spi_port_fd = spi_port == 1 ? spi_cs1_fd : spi_cs0_fd;
image img;
bool flag = false;
for (int segNum = 0; segNum < 4; segNum++) {
//Read through until the 0th packet.
int packet_num = 1;
while (packet_num != 0) {
read(spi_port_fd, &img.seg[segNum], sizeof(packet));
packet_num = img.seg[segNum].line[0].packet_number>>8;
}
//Read the rest of this 1/3 segment.
read(spi_port_fd, &img.seg[segNum].line[1], 19*sizeof(packet));
//Read the remainder of the segment.
for (int part=1;part<3;part++) {
read(spi_port_fd, &img.seg[segNum].line[20*(part%3)], 20*sizeof(packet));
}
//If the segment number is 0, the frame is invalid.
if ((img.seg[segNum].line[20].packet_number & 0xff) == 0) {
flag = true;
if ((img.seg[segNum].line[20].packet_number >> 8) != 0x14) {
resets++;
}
break;
}
}
if (flag) {
continue;
}
//Check to make sure packet number is correct, or else the Lepton is out of sync.
//We have 750 'resets' before re-syncing.
if (resets == 750) {
SpiClosePort(spi_port);
usleep(750000);
SpiOpenPort(spi_port);
resets = 0;
continue;
}
int row, column;
uint16_t value;
//Iterate through the current segment pixel at a time. In this loop, we find the
//minimum and maximum values of the image for AGC.
int lineNum = 0;
int pixelNum = 0;
int segNum = 0;
for (unsigned i=0;i<sizeof(image)/2;i++) {
//Skip the header of each line
if (i % (sizeof(packet)/2) < 2) {
continue;
}
//80 pixels per line, 60 lines per segment.
pixelNum++;
if (pixelNum == 80) {
pixelNum = 0;
lineNum++;
}
if (lineNum == 60) {
lineNum = 0;
segNum++;
}
//Flip the MSB and LSB for correct coloring.
frameBuffer[i] = img.seg[segNum].
line[lineNum].
video_src[2*pixelNum] << 8 |
img.seg[segNum].
line[lineNum].
video_src[2*pixelNum+1] << 0;
value = frameBuffer[i];
totalCounts += value;
if (value > maxValue) {
maxValue = value;
}
if (value < minValue && value > 0) {
minValue = value;
}
}
//If the difference between Max and Min is 0, we need to get a new frame before emitting.
float diff = maxValue - minValue;
if (diff != 0) {
float scale = 255/diff;
QRgb color;
//Iterates through the entire frame, one pixel at a time, for colorization.
for (unsigned i=0;i<sizeof(image)/2;i++) {
//Skip the header of each line.
if (i % (sizeof(packet)/2) < 2) {
continue;
}
value = (frameBuffer[i] - minValue) * scale;
const int *colormap = colormap_ironblack;
if (value > 255) {
value = 255;
}
color = qRgb(colormap[3*value], colormap[3*value+1], colormap[3*value+2]);
column = (i % (sizeof(packet)/2)) - 2;
row = i / (sizeof(packet)/2);
int newColumn = (row % 2 == 0) ? column : column + 80 ;
int newRow = row/2;
myImage.setPixel(newColumn, newRow, color);
}
//Emit the finalized image for update.
emit updateImage(myImage);
}
minValue = 65535;
maxValue = 0;
totalCounts = 0;
resets = 0;
}
SpiClosePort(spi_port);
}
void LeptonThread::performFFC() {
lepton_perform_ffc();
}