-
Notifications
You must be signed in to change notification settings - Fork 0
/
vc0706.c
286 lines (253 loc) · 11.2 KB
/
vc0706.c
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*****************************************************************************/
/* Legal */
/*****************************************************************************/
/*
** Copyright ©2015. Lantronix, Inc. All Rights Reserved.
** By using this software, you are agreeing to the terms of the Software
** Development Kit (SDK) License Agreement included in the distribution package
** for this software (the “License Agreement”).
** Under the License Agreement, this software may be used solely to create
** custom applications for use on the Lantronix xPico Wi-Fi product.
** THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION IS PROVIDED "AS IS".
** LANTRONIX SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS
** FOR A PARTICULAR PURPOSE.
** LANTRONIX HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
** ENHANCEMENTS, OR MODIFICATIONS TO THIS SOFTWARE.
** IN NO EVENT SHALL LANTRONIX BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
** SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
** ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
** LANTRONIX HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************/
/* Includes */
/*****************************************************************************/
#include "vc0706_module_defs.h" /* Automatically generated by make. */
#include "ltrx_compile_defines.h" /* Delivered with SDK. */
#include "ltrx_line.h" /* Delivered with SDK. */
#include "main_module_libs.h" /* Delivered with SDK. */
#include "string.h"
/*****************************************************************************/
/* Defines */
/*****************************************************************************/
#define EXPECTED_MAIN_INTERFACE_VERSION 1
#define CAMERA_MAX_BUFFER_READ 32
/*****************************************************************************/
/* Prototypes */
/*****************************************************************************/
void sendCommand(int zeroBasedIndex, char cmd, char* args, uint8_t argn);
bool cameraBuffCtrl(int zeroBasedIndex, char command);
static bool myCBfunc(struct ltrx_http_client *client);
void checkConfig(void*);
uint32_t getFrameLength(int zeroBasedIndex);
uint8_t* readPicture(int zeroBasedIndex, uint8_t n);
bool setImageSize(int zeroBasedIndex, uint8_t size);
/*****************************************************************************/
/* Globals */
/*****************************************************************************/
const struct main_external_functions *g_mainExternalFunctionEntry_pointer = 0;
uint16_t frameptr = 0;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
// Define a callback function to be attached to the Lantronix web server
// when the camera URI is accessed.
static const struct ltrx_http_dynamic_callback cb = {
.uriPath = "/camera",
.callback = myCBfunc
};
// The <name>_module_initialization function is called automatically by the
// Lantronix OS when bringing up modules. This is the entry point.
void vc0706_module_initialization(const struct main_external_functions *mef)
{
if(
mef &&
mef->current_interface_version >= EXPECTED_MAIN_INTERFACE_VERSION &&
mef->backward_compatible_down_to_version <= EXPECTED_MAIN_INTERFACE_VERSION
)
{
g_mainExternalFunctionEntry_pointer = mef;
// Register the module so the OS does the proper initialization, like creating
// the module directory in the filesystem to put the embedded files
ltrx_module_register(&g_vc0706ModuleInfo);
ltrx_thread_create(
"SetConfiguration", // Make sure configuration is set right.
checkConfig,
NULL,
8000
);
// Attach the callback to the web server. We don't need to run any more code
// since this module will only execute code when it receives a web request
ltrx_http_dynamic_callback_register(&cb);
}
}
static const char* http_header = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n";
// This is the callback function
bool myCBfunc(struct ltrx_http_client *client)
{
char buf[200];
int zeroBasedIndex = 0;
// Get the socket connection that made the request to our URI
struct ltrx_ip_socket *socket = ltrx_http_get_socket(client);
// Receive the rest of the URI line to get parameters, the URI format is:
// /camera/x/command[/i] where:
// x is the UART that the camera is attached to
// command is either photo.jpg or resize
// if command is resize, /i is the image size (1 for small, 2 for medium, 3 for large)
const char *path = ltrx_http_get_request_path(client);
if ( (strlen(path) > 3) && ((path[1] == '0') || (path[1] == '1')) ) {
zeroBasedIndex = path[1]-'0';
} else {
return true;
}
if( strstr(path,"photo.jpg" ) != NULL ) {
if (ltrx_line_open(zeroBasedIndex,1000))
{
if (!cameraBuffCtrl(zeroBasedIndex,0x0)) { // Stop the Frame Buffer
TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL,"Couldn't stop buffer");
ltrx_line_close(zeroBasedIndex);
return true;
}
uint32_t jpglen = getFrameLength(zeroBasedIndex); // Get the size of the image
//TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL,"Buffer size: %d", jpglen);
snprintf(buf, 200, http_header,jpglen);
ltrx_ip_socket_send(socket, buf, strlen(buf), false); // Send the HTTP header to the browser
frameptr = 0;
while (jpglen > 0) {
uint8_t *buffer;
uint8_t bytesToRead = CAMERA_MAX_BUFFER_READ;
if (jpglen < CAMERA_MAX_BUFFER_READ) { bytesToRead = jpglen; }
// Transfer from camera transfer to our buffer. The VC0706 has a lot of errors if
// we try to transfer more than 32 bytes at a time, so that's what CAMERA_MAX_BUFFER_READ
// should be. Then send the data from the buffer out to the browser.
buffer = readPicture(zeroBasedIndex,bytesToRead);
ltrx_tcp_socket_send(socket, buffer, bytesToRead, true);
jpglen -= bytesToRead;
}
cameraBuffCtrl(zeroBasedIndex,0x3); // Restart the frame buffer
}
ltrx_line_close(zeroBasedIndex);
return true;
} else if( strstr(path,"resize") != NULL) {
uint8_t size = *(strrchr(path, '/')+1)-'0';
ltrx_tcp_socket_send(socket, strrchr(path,'/')+1, 1, true);
setImageSize(zeroBasedIndex,size);
}
return true;
}
void checkConfig(void* opaque) {
(void)opaque;
struct output_stream_to_buffer osb;
struct input_stream_from_const_char ifs;
char buffer[10];
char buffer2[40];
ltrx_thread_sleep(2000);
static const char *xmlValue = "<?xml version=\"1.0\" standalone=\"yes\"?><!DOCTYPE configrecord [<!ELEMENT configrecord (configgroup+)><!ELEMENT configgroup (configitem+)><!ELEMENT configitem (value+)><!ELEMENT value (#PCDATA)><!ATTLIST configrecord version CDATA #IMPLIED><!ATTLIST configgroup name CDATA #IMPLIED><!ATTLIST configgroup instance CDATA #IMPLIED><!ATTLIST configitem name CDATA #IMPLIED><!ATTLIST configitem instance CDATA #IMPLIED><!ATTLIST value name CDATA #IMPLIED>]><configrecord version = \"0.1.0.1\"><configgroup name = \"Line\" instance = \"1\"><configitem name = \"Protocol\"><value>None</value></configitem><configitem name = \"Baud Rate\"><value>38400 bits per second</value></configitem></configgroup></configrecord>";
static const struct xml_emit_value_specification s_xevs = {
.type = XML_EMIT_VALUE_TYPE__CONFIGURATION,
.groupName = "Line",
.optGroupInstance = "1",
.itemName = "Protocol"
};
static const struct xml_emit_value_specification s_xevs2 = {
.type = XML_EMIT_VALUE_TYPE__CONFIGURATION,
.groupName = "Line",
.optGroupInstance = "1",
.itemName = "Baud Rate"
};
ltrx_output_stream_init_to_buffer(&osb, buffer, sizeof(buffer), OUTPUT_STREAM_TO_BUFFER_MODE__ZERO_TERMINATE);
ltrx_xml_emit_value(&s_xevs, &osb.outStream);
ltrx_output_stream_init_to_buffer(&osb, buffer2, sizeof(buffer2), OUTPUT_STREAM_TO_BUFFER_MODE__ZERO_TERMINATE);
ltrx_xml_emit_value(&s_xevs2, &osb.outStream);
if(strstr(buffer,"None") == NULL || strstr(buffer2,"38400") == NULL){
ltrx_thread_sleep(2000);
TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL,"Protocol: %s, baud: %s", buffer, buffer2);
ltrx_input_stream_init_from_const_char(&ifs,xmlValue);
ltrx_xml_import_from_stream(&ifs.inStream, NULL);
}
}
/* The following functions implement the protocol to talk to the VC0706 camera module.
** More information on the protocol is here:
** http://www.adafruit.com/datasheets/VC0706protocol.pdf
**
** The camera can be found here: http://www.adafruit.com/product/397
**
** Adapted from the Adafruit VC0706 Arduino library:
** https://github.com/adafruit/Adafruit-VC0706-Serial-Camera-Library
*/
void sendCommand(int zeroBasedIndex,char cmd, char* args, uint8_t argn) {
char head[] = {0x56,0x0};
ltrx_line_write(zeroBasedIndex,&head,2, NULL);
ltrx_line_write(zeroBasedIndex,&cmd,1, NULL);
ltrx_line_write(zeroBasedIndex,&args[0],argn,NULL);
}
bool setImageSize(int zeroBasedIndex, uint8_t size) {
char args[] = {0x05,0x04, 0x01, 0x00, 0x19, 0x22};
uint8_t *buf;
if (size == 2) {
args[5] = 0x11;
} else if (size == 3) {
args[5] = 0x0;
}
sendCommand(zeroBasedIndex, 0x31, args, sizeof(args));
if ( (ltrx_line_read(zeroBasedIndex,&buf,5,NULL,200) != 5) ||
(buf[0] != 0x76) ||
(buf[1] != 0x00) ||
(buf[2] != 0x31) ||
(buf[3] != 0x0) )
return false;
return true;
}
bool cameraBuffCtrl(int zeroBasedIndex, char command) {
char args[] = {0x1,command};
uint8_t *buf;
sendCommand(zeroBasedIndex, 0x36, args, sizeof(args));
if ( (ltrx_line_read(0,&buf,5,NULL,200) != 5) ||
(buf[0] != 0x76) ||
(buf[1] != 0x00) ||
(buf[2] != 0x36) ||
(buf[3] != 0x0) )
return false;
return true;
}
uint32_t getFrameLength(int zeroBasedIndex) {
char args[] = {0x1, 0x00};
uint8_t *camerabuff;
sendCommand(zeroBasedIndex,0x34, args, sizeof(args));
ltrx_line_read(zeroBasedIndex,&camerabuff,9, NULL, 2000);
uint32_t len;
len = camerabuff[5];
len <<= 8;
len |= camerabuff[6];
len <<= 8;
len |= camerabuff[7];
len <<= 8;
len |= camerabuff[8];
return len;
}
uint8_t* readPicture(int zeroBasedIndex,uint8_t n) {
uint8_t *camerabuff;
char args[] = {0x0C, 0x0, 0x0A,
0, 0, frameptr >> 8, frameptr & 0xFF,
0, 0, 0, n,
0, 0x10};
while (true) {
sendCommand(zeroBasedIndex,0x32, args, sizeof(args));
ltrx_line_read(zeroBasedIndex,&camerabuff,5,NULL, 200);
if (camerabuff[3] != 0x0) {
//TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL, "Frame error");
ltrx_thread_sleep(200);
ltrx_line_purge(zeroBasedIndex);
continue;
}
if ((ltrx_line_read(zeroBasedIndex,&camerabuff,n+5,NULL, 200) != n+5)) {
//TLOG(TLOG_SEVERITY_LEVEL__INFORMATIONAL, "Could not read buffer");
ltrx_thread_sleep(200);
ltrx_line_purge(zeroBasedIndex);
continue;
}
break;
};
frameptr+=n;
return camerabuff;
}