base.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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(n_lines_reg, "cmosis", "cmosis_number_lines");
  78. FIND_REG(line_reg, "cmosis", "cmosis_start1");
  79. FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time");
  80. FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping");
  81. FIND_REG(firmware_version_reg, "fpga", "firmware_version");
  82. FIND_REG(adc_resolution_reg, "fpga", "adc_resolution");
  83. FIND_REG(output_mode_reg, "fpga", "output_mode");
  84. FIND_REG(max_frames_reg, "fpga", "ddr_max_frames");
  85. FIND_REG(num_frames_reg, "fpga", "ddr_num_frames");
  86. GET_REG(firmware_version_reg, value);
  87. switch (value) {
  88. case 5:
  89. ctx->firmware = value;
  90. break;
  91. default:
  92. ctx->firmware = 5;
  93. pcilib_warning("Unsupported version of firmware (%lu)", value);
  94. }
  95. #ifdef IPECAMERA_ADJUST_BUFFER_SIZE
  96. GET_REG(max_frames_reg, value);
  97. if ((value + IPECAMERA_RESERVE_BUFFERS + 3) > ctx->buffer_size) {
  98. int val, bits = 0;
  99. ctx->buffer_size = (value + 1) + IPECAMERA_RESERVE_BUFFERS + 2;
  100. for (val = ctx->buffer_size; val; val = val >> 1) bits++;
  101. ctx->buffer_size = 1 << bits;
  102. }
  103. #endif /* IPECAMERA_ADJUST_BUFFER_SIZE */
  104. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  105. ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
  106. if (err) {
  107. free(ctx);
  108. return NULL;
  109. }
  110. }
  111. return (pcilib_context_t*)ctx;
  112. }
  113. void ipecamera_free(pcilib_context_t *vctx) {
  114. if (vctx) {
  115. ipecamera_t *ctx = (ipecamera_t*)vctx;
  116. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  117. free(ctx);
  118. }
  119. }
  120. pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) {
  121. ipecamera_t *ctx = (ipecamera_t*)vctx;
  122. const pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib);
  123. if ((!model_info->dma)||(!model_info->dma->api)||(!model_info->dma->api->init)) {
  124. pcilib_error("The DMA engine is not configured in model");
  125. return NULL;
  126. }
  127. if (ctx->firmware) {
  128. return model_info->dma->api->init(vctx->pcilib, NULL, NULL);
  129. } else {
  130. return model_info->dma->api->init(vctx->pcilib, "pci", NULL);
  131. }
  132. }
  133. int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) {
  134. if (ctx->started) {
  135. pcilib_error("Can't change buffer size while grabbing");
  136. return PCILIB_ERROR_INVALID_REQUEST;
  137. }
  138. if (size < 2) {
  139. pcilib_error("The buffer size is too small");
  140. return PCILIB_ERROR_INVALID_REQUEST;
  141. }
  142. if ((size^(size-1)) < size) {
  143. pcilib_error("The buffer size is not power of 2");
  144. }
  145. ctx->buffer_size = size;
  146. return 0;
  147. }
  148. int ipecamera_reset(pcilib_context_t *vctx) {
  149. int err = 0;
  150. ipecamera_t *ctx = (ipecamera_t*)vctx;
  151. pcilib_t *pcilib = vctx->pcilib;
  152. pcilib_register_t control, status;
  153. pcilib_register_value_t value;
  154. if (!ctx) {
  155. pcilib_error("IPECamera imaging is not initialized");
  156. return PCILIB_ERROR_NOTINITIALIZED;
  157. }
  158. pcilib = vctx->pcilib;
  159. control = ctx->control_reg;
  160. status = ctx->status_reg;
  161. // Set Reset bit to CMOSIS
  162. err = pcilib_write_register_by_id(pcilib, control, 0x1e4);
  163. if (err) {
  164. pcilib_error("Error setting FPGA reset bit");
  165. return err;
  166. }
  167. usleep(IPECAMERA_CMOSIS_RESET_DELAY);
  168. // Remove Reset bit to CMOSIS
  169. err = pcilib_write_register_by_id(pcilib, control, 0x1e1);
  170. if (err) {
  171. pcilib_error("Error reseting FPGA reset bit");
  172. return err;
  173. }
  174. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  175. // Special settings for CMOSIS v.2
  176. value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value);
  177. if (err) {
  178. pcilib_error("Error setting CMOSIS configuration");
  179. return err;
  180. }
  181. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  182. value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value);
  183. if (err) {
  184. pcilib_error("Error setting CMOSIS configuration");
  185. return err;
  186. }
  187. usleep(IPECAMERA_CMOSIS_REGISTER_DELAY);
  188. // Set default parameters
  189. err = pcilib_write_register_by_id(pcilib, control, IPECAMERA_IDLE);
  190. if (err) {
  191. pcilib_error("Error bringing FPGA in default mode");
  192. return err;
  193. }
  194. usleep(10000);
  195. CHECK_STATUS();
  196. if (err) {
  197. err = pcilib_read_register_by_id(pcilib, status, &value);
  198. if (err) pcilib_error("Error reading status register");
  199. else pcilib_error("Camera returns unexpected status (status: %lx)", value);
  200. return PCILIB_ERROR_VERIFY;
  201. }
  202. return pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  203. }
  204. int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
  205. int i;
  206. int err = 0;
  207. ipecamera_t *ctx = (ipecamera_t*)vctx;
  208. pcilib_t *pcilib = vctx->pcilib;
  209. pcilib_register_value_t value;
  210. const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  211. pthread_attr_t attr;
  212. struct sched_param sched;
  213. if (!ctx) {
  214. pcilib_error("IPECamera imaging is not initialized");
  215. return PCILIB_ERROR_NOTINITIALIZED;
  216. }
  217. if (ctx->started) {
  218. pcilib_error("IPECamera grabbing is already started");
  219. return PCILIB_ERROR_INVALID_REQUEST;
  220. }
  221. ctx->event_id = 0;
  222. ctx->preproc_id = 0;
  223. ctx->reported_id = 0;
  224. ctx->buffer_pos = 0;
  225. ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
  226. ctx->cur_size = 0;
  227. ctx->dim.width = IPECAMERA_WIDTH;
  228. ctx->dim.height = IPECAMERA_MAX_LINES;
  229. // GET_REG(n_lines_reg, ctx->dim.height);
  230. GET_REG(output_mode_reg, value);
  231. switch (value) {
  232. case IPECAMERA_MODE_16_CHAN_IO:
  233. ctx->cmosis_outputs = 16;
  234. break;
  235. case IPECAMERA_MODE_4_CHAN_IO:
  236. ctx->cmosis_outputs = 4;
  237. break;
  238. default:
  239. pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value);
  240. return PCILIB_ERROR_INVALID_STATE;
  241. }
  242. ipecamera_compute_buffer_size(ctx, ctx->dim.height);
  243. ctx->raw_size = ctx->roi_raw_size;
  244. ctx->padded_size = ctx->roi_padded_size;
  245. ctx->image_size = ctx->dim.width * ctx->dim.height;
  246. GET_REG(max_frames_reg, value);
  247. ctx->max_frames = value;
  248. ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
  249. if (!ctx->buffer) {
  250. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  251. pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
  252. return PCILIB_ERROR_MEMORY;
  253. }
  254. ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  255. if (!ctx->image) {
  256. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  257. pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  258. return PCILIB_ERROR_MEMORY;
  259. }
  260. ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
  261. if (!ctx->cmask) {
  262. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  263. pcilib_error("Unable to allocate change-mask buffer");
  264. return PCILIB_ERROR_MEMORY;
  265. }
  266. ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t));
  267. if (!ctx->frame) {
  268. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  269. pcilib_error("Unable to allocate frame-info buffer");
  270. return PCILIB_ERROR_MEMORY;
  271. }
  272. memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
  273. for (i = 0; i < ctx->buffer_size; i++) {
  274. err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
  275. if (err) break;
  276. }
  277. ctx->frame_mutex_destroy = i;
  278. if (err) {
  279. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  280. pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed");
  281. return PCILIB_ERROR_FAILED;
  282. }
  283. ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
  284. if (!ctx->ipedec) {
  285. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  286. pcilib_error("Unable to initialize IPECamera decoder library");
  287. return PCILIB_ERROR_FAILED;
  288. }
  289. if (!err) {
  290. ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS);
  291. if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) {
  292. err = PCILIB_ERROR_NOTFOUND;
  293. pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
  294. } else {
  295. err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  296. if (err) {
  297. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  298. pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
  299. }
  300. }
  301. }
  302. if (err) {
  303. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  304. return err;
  305. }
  306. #ifdef IPECAMERA_CLEAN_ON_START
  307. err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  308. if (err) {
  309. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  310. pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
  311. return err;
  312. }
  313. #endif /* IPECAMERA_CLEAN_ON_START */
  314. if (vctx->params.autostop.duration) {
  315. gettimeofday(&ctx->autostop.timestamp, NULL);
  316. ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
  317. if (ctx->autostop.timestamp.tv_usec > 999999) {
  318. ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000;
  319. ctx->autostop.timestamp.tv_usec -= 1000000;
  320. } else {
  321. ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000;
  322. }
  323. }
  324. if (vctx->params.autostop.max_events) {
  325. ctx->autostop.evid = vctx->params.autostop.max_events;
  326. }
  327. if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) {
  328. ctx->n_preproc = pcilib_get_cpu_count();
  329. // it would be greate to detect hyperthreading cores and ban them
  330. switch (ctx->n_preproc) {
  331. case 1: break;
  332. case 2 ... 3: ctx->n_preproc -= 1; break;
  333. default: ctx->n_preproc -= 2; break;
  334. }
  335. if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc))
  336. ctx->n_preproc = vctx->params.parallel.max_threads;
  337. ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  338. if (!ctx->preproc) {
  339. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  340. pcilib_error("Unable to allocate memory for preprocessor contexts");
  341. return PCILIB_ERROR_MEMORY;
  342. }
  343. memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  344. err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
  345. if (err) {
  346. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  347. pcilib_error("Failed to initialize event mutex");
  348. return PCILIB_ERROR_FAILED;
  349. }
  350. ctx->preproc_mutex_destroy = 1;
  351. ctx->run_preprocessors = 1;
  352. for (i = 0; i < ctx->n_preproc; i++) {
  353. ctx->preproc[i].i = i;
  354. ctx->preproc[i].ipecamera = ctx;
  355. err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i);
  356. if (err) {
  357. err = PCILIB_ERROR_FAILED;
  358. break;
  359. } else {
  360. ctx->preproc[i].started = 1;
  361. }
  362. }
  363. if (err) {
  364. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  365. pcilib_error("Failed to schedule some of the preprocessor threads");
  366. return err;
  367. }
  368. } else {
  369. ctx->n_preproc = 0;
  370. }
  371. ctx->started = 1;
  372. ctx->run_reader = 1;
  373. pthread_attr_init(&attr);
  374. if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
  375. pcilib_warning("Can't schedule a real-time thread, you may consider running as root");
  376. } else {
  377. sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial
  378. pthread_attr_setschedparam(&attr, &sched);
  379. }
  380. if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
  381. ctx->started = 0;
  382. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  383. err = PCILIB_ERROR_FAILED;
  384. }
  385. pthread_attr_destroy(&attr);
  386. return err;
  387. }
  388. int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
  389. int i;
  390. int err;
  391. void *retcode;
  392. ipecamera_t *ctx = (ipecamera_t*)vctx;
  393. if (!ctx) {
  394. pcilib_error("IPECamera imaging is not initialized");
  395. return PCILIB_ERROR_NOTINITIALIZED;
  396. }
  397. if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) {
  398. ctx->run_reader = 0;
  399. return 0;
  400. }
  401. if (ctx->started) {
  402. ctx->run_reader = 0;
  403. err = pthread_join(ctx->rthread, &retcode);
  404. if (err) pcilib_error("Error joining the reader thread");
  405. }
  406. if (ctx->preproc) {
  407. ctx->run_preprocessors = 0;
  408. for (i = 0; i < ctx->n_preproc; i++) {
  409. if (ctx->preproc[i].started) {
  410. pthread_join(ctx->preproc[i].thread, &retcode);
  411. ctx->preproc[i].started = 0;
  412. }
  413. }
  414. if (ctx->preproc_mutex_destroy) {
  415. pthread_mutex_destroy(&ctx->preproc_mutex);
  416. ctx->preproc_mutex_destroy = 0;
  417. }
  418. free(ctx->preproc);
  419. ctx->preproc = NULL;
  420. }
  421. if (ctx->frame_mutex_destroy) {
  422. for (i = 0; i < ctx->frame_mutex_destroy; i++) {
  423. pthread_rwlock_destroy(&ctx->frame[i].mutex);
  424. }
  425. ctx->frame_mutex_destroy = 0;
  426. }
  427. if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) {
  428. pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
  429. ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
  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. }