base.c 17 KB

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