base.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #define _IPECAMERA_IMAGE_C
  2. #define _DEFAULT_SOURCE
  3. #define _BSD_SOURCE
  4. #define _GNU_SOURCE
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <string.h>
  9. #include <sys/time.h>
  10. #include <pthread.h>
  11. #include <assert.h>
  12. #include <ufodecode.h>
  13. #include <pcilib.h>
  14. #include <pcilib/tools.h>
  15. #include <pcilib/error.h>
  16. #include <pcilib/event.h>
  17. #include <pcilib/cpu.h>
  18. #include <pcilib/timing.h>
  19. #include "private.h"
  20. #include "model.h"
  21. #include "reader.h"
  22. #include "events.h"
  23. #include "data.h"
  24. #define FIND_REG(var, bank, name) \
  25. ctx->var = pcilib_find_register(pcilib, bank, name); \
  26. if (ctx->var == PCILIB_REGISTER_INVALID) { \
  27. err = PCILIB_ERROR_NOTFOUND; \
  28. pcilib_error("Unable to find a %s register", name); \
  29. }
  30. #define GET_REG(reg, var) \
  31. if (!err) { \
  32. err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \
  33. if (err) { \
  34. pcilib_error("Error reading %s register", model_info->registers[ctx->reg].name); \
  35. } \
  36. }
  37. #define SET_REG(reg, val) \
  38. if (!err) { \
  39. err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \
  40. if (err) { \
  41. pcilib_error("Error writting %s register", model_info->registers[ctx->reg].name); \
  42. } \
  43. }
  44. #define CHECK_REG(reg, check) \
  45. if (!err) { \
  46. err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \
  47. if (err) { \
  48. pcilib_error("Error reading %s register", model_info->registers[ctx->reg].name); \
  49. } \
  50. if (value != check) { \
  51. pcilib_error("Unexpected value (0x%lx) of register %s", value, model_info->registers[ctx->reg].name); \
  52. err = PCILIB_ERROR_INVALID_DATA; \
  53. } \
  54. }
  55. #define CHECK_STATUS()
  56. //CHECK_REG(status_reg, IPECAMERA_GET_EXPECTED_STATUS(ctx))
  57. #define CHECK_VALUE(value, val) \
  58. if ((!err)&&(value != val)) { \
  59. pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \
  60. err = PCILIB_ERROR_INVALID_DATA; \
  61. }
  62. #define CHECK_FLAG(flag, check, ...) \
  63. if ((!err)&&(!(check))) { \
  64. pcilib_error("Unexpected value (0x%x) of " flag, __VA_ARGS__); \
  65. err = PCILIB_ERROR_INVALID_DATA; \
  66. }
  67. #define LOCK(lock_name) \
  68. err = pcilib_try_lock(ctx->lock_name##_lock); \
  69. if (err) { \
  70. pcilib_error("IPECamera is busy"); \
  71. return PCILIB_ERROR_BUSY; \
  72. } \
  73. ctx->lock_name##_locked = 1;
  74. #define UNLOCK(lock_name) \
  75. if (ctx->lock_name##_locked) { \
  76. pcilib_unlock(ctx->lock_name##_lock); \
  77. ctx->lock_name##_locked = 0; \
  78. }
  79. pcilib_context_t *ipecamera_init(pcilib_t *pcilib) {
  80. int err = 0;
  81. const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  82. ipecamera_t *ctx = malloc(sizeof(ipecamera_t));
  83. if (ctx) {
  84. pcilib_register_value_t value;
  85. memset(ctx, 0, sizeof(ipecamera_t));
  86. ctx->run_lock = pcilib_get_lock(pcilib, PCILIB_LOCK_FLAGS_DEFAULT, "ipecamera");
  87. ctx->stream_lock = pcilib_get_lock(pcilib, PCILIB_LOCK_FLAGS_DEFAULT, "ipecamera/stream");
  88. ctx->trigger_lock = pcilib_get_lock(pcilib, PCILIB_LOCK_FLAGS_DEFAULT, "ipecamera/trigger");
  89. if (!ctx->run_lock||!ctx->stream_lock||!ctx->trigger_lock) {
  90. free(ctx);
  91. pcilib_error("Failed to initialize locks to protect ipecamera operation");
  92. return NULL;
  93. }
  94. ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8;
  95. ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE;
  96. FIND_REG(status_reg, "fpga", "status");
  97. FIND_REG(control_reg, "fpga", "control");
  98. FIND_REG(status2_reg, "fpga", "status2");
  99. FIND_REG(status3_reg, "fpga", "status3");
  100. FIND_REG(firmware_version_reg, "fpga", "firmware_version");
  101. FIND_REG(adc_resolution_reg, "fpga", "adc_resolution");
  102. FIND_REG(output_mode_reg, "fpga", "output_mode");
  103. FIND_REG(max_frames_reg, "fpga", "ddr_max_frames");
  104. FIND_REG(num_frames_reg, "fpga", "ddr_num_frames");
  105. GET_REG(firmware_version_reg, value);
  106. switch (value) {
  107. case IPECAMERA_FIRMWARE_UFO5:
  108. ctx->firmware = value;
  109. err = pcilib_add_registers(pcilib, 0, 0, cmosis_registers, NULL);
  110. break;
  111. case IPECAMERA_FIRMWARE_CMOSIS20:
  112. ctx->firmware = value;
  113. ctx->buffer_size = IPECAMERA_DEFAULT_CMOSIS20_BUFFER_SIZE;
  114. err = pcilib_add_registers(pcilib, 0, 0, cmosis20000_registers, NULL);
  115. break;
  116. default:
  117. ctx->firmware = IPECAMERA_FIRMWARE_UNKNOWN;
  118. pcilib_warning("Unsupported version of firmware (%lu)", value);
  119. }
  120. // FIND_REG(n_lines_reg, "cmosis", "cmosis_number_lines"); // cmosis_number_lines_single v.6 ?
  121. // FIND_REG(line_reg, "cmosis", "cmosis_start1"); // cmosis_start_single v.6 ?
  122. // FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time");
  123. // FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping");
  124. #ifdef IPECAMERA_ADJUST_BUFFER_SIZE
  125. GET_REG(max_frames_reg, value);
  126. if ((value + IPECAMERA_RESERVE_BUFFERS + 3) > ctx->buffer_size) {
  127. int val, bits = 0;
  128. ctx->buffer_size = (value + 1) + IPECAMERA_RESERVE_BUFFERS + 2;
  129. for (val = ctx->buffer_size; val; val = val >> 1) bits++;
  130. ctx->buffer_size = 1 << bits;
  131. }
  132. #endif /* IPECAMERA_ADJUST_BUFFER_SIZE */
  133. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  134. if (err) {
  135. free(ctx);
  136. return NULL;
  137. }
  138. }
  139. return (pcilib_context_t*)ctx;
  140. }
  141. void ipecamera_free(pcilib_context_t *vctx) {
  142. if (vctx) {
  143. ipecamera_t *ctx = (ipecamera_t*)vctx;
  144. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  145. if (ctx->trigger_lock)
  146. pcilib_return_lock(vctx->pcilib, PCILIB_LOCK_FLAGS_DEFAULT, ctx->trigger_lock);
  147. if (ctx->stream_lock)
  148. pcilib_return_lock(vctx->pcilib, PCILIB_LOCK_FLAGS_DEFAULT, ctx->stream_lock);
  149. if (ctx->run_lock)
  150. pcilib_return_lock(vctx->pcilib, PCILIB_LOCK_FLAGS_DEFAULT, ctx->run_lock);
  151. free(ctx);
  152. }
  153. }
  154. pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) {
  155. ipecamera_t *ctx = (ipecamera_t*)vctx;
  156. const pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib);
  157. if ((!model_info->dma)||(!model_info->dma->api)||(!model_info->dma->api->init)) {
  158. pcilib_error("The DMA engine is not configured in model");
  159. return NULL;
  160. }
  161. if (ctx->firmware) {
  162. return model_info->dma->api->init(vctx->pcilib, "ipecamera", NULL);
  163. } else {
  164. return model_info->dma->api->init(vctx->pcilib, "pci", NULL);
  165. }
  166. }
  167. int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) {
  168. if (ctx->started) {
  169. pcilib_error("Can't change buffer size while grabbing");
  170. return PCILIB_ERROR_INVALID_REQUEST;
  171. }
  172. if (size < 2) {
  173. pcilib_error("The buffer size is too small");
  174. return PCILIB_ERROR_INVALID_REQUEST;
  175. }
  176. if ((size^(size-1)) < size) {
  177. pcilib_error("The buffer size is not power of 2");
  178. }
  179. ctx->buffer_size = size;
  180. return 0;
  181. }
  182. int ipecamera_reset(pcilib_context_t *vctx) {
  183. int err = 0;
  184. ipecamera_t *ctx = (ipecamera_t*)vctx;
  185. pcilib_t *pcilib = vctx->pcilib;
  186. pcilib_register_t control, status;
  187. pcilib_register_value_t value;
  188. if (!ctx) {
  189. pcilib_error("IPECamera imaging is not initialized");
  190. return PCILIB_ERROR_NOTINITIALIZED;
  191. }
  192. pcilib = vctx->pcilib;
  193. control = ctx->control_reg;
  194. status = ctx->status_reg;
  195. LOCK(run);
  196. ipecamera_debug(API, "ipecamera: starting");
  197. if (ctx->firmware == IPECAMERA_FIRMWARE_UFO5) {
  198. // Set Reset bit to CMOSIS
  199. err = pcilib_write_register_by_id(pcilib, control, 0x1e4);
  200. if (err) {
  201. UNLOCK(run);
  202. pcilib_error("Error setting FPGA reset bit");
  203. return err;
  204. }
  205. usleep(IPECAMERA_CMOSIS_RESET_DELAY);
  206. // Remove Reset bit to CMOSIS
  207. err = pcilib_write_register_by_id(pcilib, control, 0x1e1);
  208. if (err) {
  209. UNLOCK(run);
  210. pcilib_error("Error reseting FPGA reset bit");
  211. return err;
  212. }
  213. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  214. // Special settings for CMOSIS v.2
  215. value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value);
  216. if (err) {
  217. UNLOCK(run);
  218. pcilib_error("Error setting CMOSIS configuration");
  219. return err;
  220. }
  221. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  222. value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value);
  223. if (err) {
  224. UNLOCK(run);
  225. pcilib_error("Error setting CMOSIS configuration");
  226. return err;
  227. }
  228. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  229. pcilib_warning("Reset procedure is not complete");
  230. } else {
  231. pcilib_warning("Reset procedure is not implemented");
  232. }
  233. usleep(10000);
  234. CHECK_STATUS();
  235. if (err) {
  236. err = pcilib_read_register_by_id(pcilib, status, &value);
  237. UNLOCK(run);
  238. if (err) pcilib_error("Error reading status register");
  239. else pcilib_error("Camera returns unexpected status (status: %lx)", value);
  240. return PCILIB_ERROR_VERIFY;
  241. }
  242. err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  243. UNLOCK(run);
  244. ipecamera_debug(API, "ipecamera: reset done");
  245. return err;
  246. }
  247. int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
  248. int i;
  249. int err = 0;
  250. ipecamera_t *ctx = (ipecamera_t*)vctx;
  251. pcilib_t *pcilib = vctx->pcilib;
  252. pcilib_register_value_t value;
  253. const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  254. pthread_attr_t attr;
  255. struct sched_param sched;
  256. if (!ctx) {
  257. pcilib_error("IPECamera imaging is not initialized");
  258. return PCILIB_ERROR_NOTINITIALIZED;
  259. }
  260. if (ctx->started) {
  261. pcilib_error("IPECamera grabbing is already started");
  262. return PCILIB_ERROR_INVALID_REQUEST;
  263. }
  264. LOCK(run);
  265. ipecamera_debug(API, "ipecamera: starting");
  266. ctx->event_id = 0;
  267. ctx->preproc_id = 0;
  268. ctx->reported_id = 0;
  269. ctx->buffer_pos = 0;
  270. ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
  271. ctx->cur_size = 0;
  272. #ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS
  273. ctx->saved_header_size = 0;
  274. #endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */
  275. switch (ctx->firmware) {
  276. case IPECAMERA_FIRMWARE_UFO5:
  277. ctx->dim.width = CMOSIS_WIDTH;
  278. ctx->dim.height = CMOSIS_MAX_LINES;
  279. ctx->data_line_size = (1 + CMOSIS_PIXELS_PER_CHANNEL) * 32;
  280. break;
  281. case IPECAMERA_FIRMWARE_CMOSIS20:
  282. ctx->dim.width = CMOSIS20_WIDTH;
  283. ctx->dim.height = CMOSIS20_MAX_LINES;
  284. // There is skipped C0 line once per every two lines (which are in fact encoded together)
  285. ctx->data_line_size = CMOSIS20_PIXELS_PER_CHANNEL * 32 + 16;
  286. break;
  287. default:
  288. UNLOCK(run);
  289. pcilib_error("Can't start undefined version (%lu) of IPECamera", ctx->firmware);
  290. return PCILIB_ERROR_INVALID_REQUEST;
  291. }
  292. if ((1)||(ctx->firmware == IPECAMERA_FIRMWARE_UFO5)) {
  293. GET_REG(output_mode_reg, value);
  294. switch (value) {
  295. case IPECAMERA_MODE_16_CHAN_IO:
  296. ctx->cmosis_outputs = 16;
  297. break;
  298. case IPECAMERA_MODE_4_CHAN_IO:
  299. ctx->cmosis_outputs = 4;
  300. break;
  301. default:
  302. UNLOCK(run);
  303. pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value);
  304. return PCILIB_ERROR_INVALID_STATE;
  305. }
  306. }
  307. // We should be careful here (currently firmware matches format, but this may not be the case in future)
  308. ipecamera_compute_buffer_size(ctx, ctx->firmware, CMOSIS_FRAME_HEADER_SIZE, ctx->dim.height);
  309. ctx->raw_size = ctx->roi_raw_size;
  310. ctx->padded_size = ctx->roi_padded_size;
  311. ctx->image_size = ctx->dim.width * ctx->dim.height;
  312. GET_REG(max_frames_reg, value);
  313. ctx->max_frames = value;
  314. ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
  315. if (!ctx->buffer) {
  316. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  317. pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
  318. return PCILIB_ERROR_MEMORY;
  319. }
  320. ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  321. if (!ctx->image) {
  322. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  323. pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  324. return PCILIB_ERROR_MEMORY;
  325. }
  326. ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
  327. if (!ctx->cmask) {
  328. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  329. pcilib_error("Unable to allocate change-mask buffer");
  330. return PCILIB_ERROR_MEMORY;
  331. }
  332. ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t));
  333. if (!ctx->frame) {
  334. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  335. pcilib_error("Unable to allocate frame-info buffer");
  336. return PCILIB_ERROR_MEMORY;
  337. }
  338. memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
  339. for (i = 0; i < ctx->buffer_size; i++) {
  340. err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
  341. if (err) break;
  342. }
  343. ctx->frame_mutex_destroy = i;
  344. if (err) {
  345. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  346. pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed");
  347. return PCILIB_ERROR_FAILED;
  348. }
  349. ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
  350. if (!ctx->ipedec) {
  351. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  352. pcilib_error("Unable to initialize IPECamera decoder library");
  353. return PCILIB_ERROR_FAILED;
  354. }
  355. if (!err) {
  356. ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS);
  357. if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) {
  358. err = PCILIB_ERROR_NOTFOUND;
  359. pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
  360. } else {
  361. err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  362. if (err) {
  363. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  364. pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
  365. }
  366. }
  367. }
  368. if (err) {
  369. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  370. return err;
  371. }
  372. #ifdef IPECAMERA_CLEAN_ON_START
  373. err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  374. if (err) {
  375. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  376. pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
  377. return err;
  378. }
  379. #endif /* IPECAMERA_CLEAN_ON_START */
  380. if (vctx->params.autostop.duration) {
  381. gettimeofday(&ctx->autostop.timestamp, NULL);
  382. ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
  383. if (ctx->autostop.timestamp.tv_usec > 999999) {
  384. ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000;
  385. ctx->autostop.timestamp.tv_usec -= 1000000;
  386. } else {
  387. ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000;
  388. }
  389. }
  390. if (vctx->params.autostop.max_events) {
  391. ctx->autostop.evid = vctx->params.autostop.max_events;
  392. }
  393. if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) {
  394. ctx->n_preproc = pcilib_get_cpu_count();
  395. // it would be greate to detect hyperthreading cores and ban them
  396. switch (ctx->n_preproc) {
  397. case 1: break;
  398. case 2 ... 3: ctx->n_preproc -= 1; break;
  399. default: ctx->n_preproc -= 2; break;
  400. }
  401. if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc))
  402. ctx->n_preproc = vctx->params.parallel.max_threads;
  403. ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  404. if (!ctx->preproc) {
  405. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  406. pcilib_error("Unable to allocate memory for preprocessor contexts");
  407. return PCILIB_ERROR_MEMORY;
  408. }
  409. memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  410. err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
  411. if (err) {
  412. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  413. pcilib_error("Failed to initialize event mutex");
  414. return PCILIB_ERROR_FAILED;
  415. }
  416. ctx->preproc_mutex_destroy = 1;
  417. ctx->run_preprocessors = 1;
  418. for (i = 0; i < ctx->n_preproc; i++) {
  419. ctx->preproc[i].i = i;
  420. ctx->preproc[i].ipecamera = ctx;
  421. err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i);
  422. if (err) {
  423. err = PCILIB_ERROR_FAILED;
  424. break;
  425. } else {
  426. ctx->preproc[i].started = 1;
  427. }
  428. }
  429. if (err) {
  430. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  431. pcilib_error("Failed to schedule some of the preprocessor threads");
  432. return err;
  433. }
  434. } else {
  435. ctx->n_preproc = 0;
  436. }
  437. ctx->started = 1;
  438. ctx->run_reader = 1;
  439. pthread_attr_init(&attr);
  440. if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
  441. pcilib_warning("Can't schedule a real-time thread, you may consider running as root");
  442. } else {
  443. sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial
  444. pthread_attr_setschedparam(&attr, &sched);
  445. }
  446. if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
  447. ctx->started = 0;
  448. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  449. err = PCILIB_ERROR_FAILED;
  450. }
  451. pthread_attr_destroy(&attr);
  452. ipecamera_debug(API, "ipecamera: started");
  453. return err;
  454. }
  455. int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
  456. int i;
  457. int err;
  458. void *retcode;
  459. ipecamera_t *ctx = (ipecamera_t*)vctx;
  460. if (!ctx) {
  461. pcilib_error("IPECamera imaging is not initialized");
  462. return PCILIB_ERROR_NOTINITIALIZED;
  463. }
  464. if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) {
  465. ctx->run_reader = 0;
  466. return 0;
  467. }
  468. ipecamera_debug(API, "ipecamera: stopping");
  469. if (ctx->started) {
  470. ctx->run_reader = 0;
  471. err = pthread_join(ctx->rthread, &retcode);
  472. if (err) pcilib_error("Error joining the reader thread");
  473. }
  474. if (ctx->preproc) {
  475. ctx->run_preprocessors = 0;
  476. for (i = 0; i < ctx->n_preproc; i++) {
  477. if (ctx->preproc[i].started) {
  478. pthread_join(ctx->preproc[i].thread, &retcode);
  479. ctx->preproc[i].started = 0;
  480. }
  481. }
  482. if (ctx->preproc_mutex_destroy) {
  483. pthread_mutex_destroy(&ctx->preproc_mutex);
  484. ctx->preproc_mutex_destroy = 0;
  485. }
  486. free(ctx->preproc);
  487. ctx->preproc = NULL;
  488. }
  489. if (ctx->frame_mutex_destroy) {
  490. for (i = 0; i < ctx->frame_mutex_destroy; i++) {
  491. pthread_rwlock_destroy(&ctx->frame[i].mutex);
  492. }
  493. ctx->frame_mutex_destroy = 0;
  494. }
  495. if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) {
  496. pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  497. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  498. }
  499. while (ctx->streaming) {
  500. usleep(IPECAMERA_NOFRAME_SLEEP);
  501. }
  502. if (ctx->ipedec) {
  503. ufo_decoder_free(ctx->ipedec);
  504. ctx->ipedec = NULL;
  505. }
  506. if (ctx->frame) {
  507. free(ctx->frame);
  508. ctx->frame = NULL;
  509. }
  510. if (ctx->cmask) {
  511. free(ctx->cmask);
  512. ctx->cmask = NULL;
  513. }
  514. if (ctx->image) {
  515. free(ctx->image);
  516. ctx->image = NULL;
  517. }
  518. if (ctx->buffer) {
  519. free(ctx->buffer);
  520. ctx->buffer = NULL;
  521. }
  522. memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t));
  523. ctx->event_id = 0;
  524. ctx->reported_id = 0;
  525. ctx->buffer_pos = 0;
  526. ctx->started = 0;
  527. ipecamera_debug(API, "ipecamera: stopped");
  528. UNLOCK(run);
  529. return 0;
  530. }
  531. int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
  532. int err = 0;
  533. pcilib_register_value_t value;
  534. ipecamera_t *ctx = (ipecamera_t*)vctx;
  535. pcilib_t *pcilib = vctx->pcilib;
  536. const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  537. if (!ctx) {
  538. pcilib_error("IPECamera imaging is not initialized");
  539. return PCILIB_ERROR_NOTINITIALIZED;
  540. }
  541. ipecamera_debug(API, "ipecamera: trigger");
  542. LOCK(trigger);
  543. pcilib_sleep_until_deadline(&ctx->next_trigger);
  544. /*
  545. GET_REG(num_frames_reg, value);
  546. if (value == ctx->max_frames) {
  547. return PCILIB_ERROR_BUSY;
  548. }
  549. */
  550. GET_REG(status2_reg, value);
  551. if (value&0x40000000) {
  552. if (value == 0xffffffff)
  553. pcilib_info("Failed to read status2_reg while triggering");
  554. #ifdef IPECAMERA_TRIGGER_TIMEOUT
  555. if (IPECAMERA_TRIGGER_TIMEOUT) {
  556. struct timeval deadline;
  557. pcilib_calc_deadline(&deadline, IPECAMERA_TRIGGER_TIMEOUT);
  558. do {
  559. usleep(IPECAMERA_READ_STATUS_DELAY);
  560. GET_REG(status2_reg, value);
  561. } while ((value&0x40000000)&&(pcilib_calc_time_to_deadline(&deadline) > 0));
  562. }
  563. if (value&0x40000000) {
  564. #endif /* IPECAMERA_TRIGGER_WAIT_IDLE */
  565. UNLOCK(trigger);
  566. return PCILIB_ERROR_BUSY;
  567. #ifdef IPECAMERA_TRIGGER_TIMEOUT
  568. }
  569. #endif /* IPECAMERA_TRIGGER_WAIT_IDLE */
  570. }
  571. GET_REG(control_reg, value);
  572. SET_REG(control_reg, value|IPECAMERA_FRAME_REQUEST);
  573. usleep(IPECAMERA_TRIGGER_DELAY);
  574. SET_REG(control_reg, value);
  575. // DS: We need to compute it differently, on top of that add exposure time and the time FPGA takes to read frame from CMOSIS
  576. pcilib_calc_deadline(&ctx->next_trigger, IPECAMERA_NEXT_FRAME_DELAY);
  577. UNLOCK(trigger);
  578. return 0;
  579. }