base.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  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 IPECAMERA_FIRMWARE_UFO5:
  85. ctx->firmware = value;
  86. err = pcilib_add_registers(pcilib, 0, cmosis_registers);
  87. break;
  88. case IPECAMERA_FIRMWARE_CMOSIS20:
  89. ctx->firmware = value;
  90. err = pcilib_add_registers(pcilib, 0, cmosis20000_registers);
  91. break;
  92. default:
  93. ctx->firmware = IPECAMERA_FIRMWARE_UNKNOWN;
  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. switch (ctx->firmware) {
  232. case IPECAMERA_FIRMWARE_UFO5:
  233. ctx->dim.width = CMOSIS_WIDTH;
  234. ctx->dim.height = CMOSIS_MAX_LINES;
  235. break;
  236. case IPECAMERA_FIRMWARE_CMOSIS20:
  237. ctx->dim.width = CMOSIS20_WIDTH;
  238. ctx->dim.height = CMOSIS20_MAX_LINES;
  239. ctx->cmosis_outputs = CMOSIS20_MAX_CHANNELS;
  240. break;
  241. default:
  242. pcilib_error("Can't start undefined version (%lu) of IPECamera", ctx->firmware);
  243. return PCILIB_ERROR_INVALID_REQUEST;
  244. }
  245. if (ctx->firmware == IPECAMERA_FIRMWARE_UFO5) {
  246. GET_REG(output_mode_reg, value);
  247. switch (value) {
  248. case IPECAMERA_MODE_16_CHAN_IO:
  249. ctx->cmosis_outputs = 16;
  250. break;
  251. case IPECAMERA_MODE_4_CHAN_IO:
  252. ctx->cmosis_outputs = 4;
  253. break;
  254. default:
  255. pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value);
  256. return PCILIB_ERROR_INVALID_STATE;
  257. }
  258. }
  259. // We should be careful here (currently firmware matches format, but this may not be the case in future)
  260. ipecamera_compute_buffer_size(ctx, ctx->firmware, CMOSIS_FRAME_HEADER_SIZE, ctx->dim.height);
  261. ctx->raw_size = ctx->roi_raw_size;
  262. ctx->padded_size = ctx->roi_padded_size;
  263. ctx->image_size = ctx->dim.width * ctx->dim.height;
  264. GET_REG(max_frames_reg, value);
  265. ctx->max_frames = value;
  266. ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
  267. if (!ctx->buffer) {
  268. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  269. pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
  270. return PCILIB_ERROR_MEMORY;
  271. }
  272. ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  273. if (!ctx->image) {
  274. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  275. pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  276. return PCILIB_ERROR_MEMORY;
  277. }
  278. ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
  279. if (!ctx->cmask) {
  280. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  281. pcilib_error("Unable to allocate change-mask buffer");
  282. return PCILIB_ERROR_MEMORY;
  283. }
  284. ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t));
  285. if (!ctx->frame) {
  286. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  287. pcilib_error("Unable to allocate frame-info buffer");
  288. return PCILIB_ERROR_MEMORY;
  289. }
  290. memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
  291. for (i = 0; i < ctx->buffer_size; i++) {
  292. err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
  293. if (err) break;
  294. }
  295. ctx->frame_mutex_destroy = i;
  296. if (err) {
  297. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  298. pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed");
  299. return PCILIB_ERROR_FAILED;
  300. }
  301. ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
  302. if (!ctx->ipedec) {
  303. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  304. pcilib_error("Unable to initialize IPECamera decoder library");
  305. return PCILIB_ERROR_FAILED;
  306. }
  307. if (!err) {
  308. ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS);
  309. if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) {
  310. err = PCILIB_ERROR_NOTFOUND;
  311. pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
  312. } else {
  313. err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  314. if (err) {
  315. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  316. pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
  317. }
  318. }
  319. }
  320. if (err) {
  321. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  322. return err;
  323. }
  324. #ifdef IPECAMERA_CLEAN_ON_START
  325. err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  326. if (err) {
  327. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  328. pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
  329. return err;
  330. }
  331. #endif /* IPECAMERA_CLEAN_ON_START */
  332. if (vctx->params.autostop.duration) {
  333. gettimeofday(&ctx->autostop.timestamp, NULL);
  334. ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
  335. if (ctx->autostop.timestamp.tv_usec > 999999) {
  336. ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000;
  337. ctx->autostop.timestamp.tv_usec -= 1000000;
  338. } else {
  339. ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000;
  340. }
  341. }
  342. if (vctx->params.autostop.max_events) {
  343. ctx->autostop.evid = vctx->params.autostop.max_events;
  344. }
  345. if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) {
  346. ctx->n_preproc = pcilib_get_cpu_count();
  347. // it would be greate to detect hyperthreading cores and ban them
  348. switch (ctx->n_preproc) {
  349. case 1: break;
  350. case 2 ... 3: ctx->n_preproc -= 1; break;
  351. default: ctx->n_preproc -= 2; break;
  352. }
  353. if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc))
  354. ctx->n_preproc = vctx->params.parallel.max_threads;
  355. ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  356. if (!ctx->preproc) {
  357. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  358. pcilib_error("Unable to allocate memory for preprocessor contexts");
  359. return PCILIB_ERROR_MEMORY;
  360. }
  361. memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
  362. err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
  363. if (err) {
  364. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  365. pcilib_error("Failed to initialize event mutex");
  366. return PCILIB_ERROR_FAILED;
  367. }
  368. ctx->preproc_mutex_destroy = 1;
  369. ctx->run_preprocessors = 1;
  370. for (i = 0; i < ctx->n_preproc; i++) {
  371. ctx->preproc[i].i = i;
  372. ctx->preproc[i].ipecamera = ctx;
  373. err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i);
  374. if (err) {
  375. err = PCILIB_ERROR_FAILED;
  376. break;
  377. } else {
  378. ctx->preproc[i].started = 1;
  379. }
  380. }
  381. if (err) {
  382. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  383. pcilib_error("Failed to schedule some of the preprocessor threads");
  384. return err;
  385. }
  386. } else {
  387. ctx->n_preproc = 0;
  388. }
  389. ctx->started = 1;
  390. ctx->run_reader = 1;
  391. pthread_attr_init(&attr);
  392. if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
  393. pcilib_warning("Can't schedule a real-time thread, you may consider running as root");
  394. } else {
  395. sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial
  396. pthread_attr_setschedparam(&attr, &sched);
  397. }
  398. if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
  399. ctx->started = 0;
  400. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  401. err = PCILIB_ERROR_FAILED;
  402. }
  403. pthread_attr_destroy(&attr);
  404. return err;
  405. }
  406. int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
  407. int i;
  408. int err;
  409. void *retcode;
  410. ipecamera_t *ctx = (ipecamera_t*)vctx;
  411. if (!ctx) {
  412. pcilib_error("IPECamera imaging is not initialized");
  413. return PCILIB_ERROR_NOTINITIALIZED;
  414. }
  415. if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) {
  416. ctx->run_reader = 0;
  417. return 0;
  418. }
  419. if (ctx->started) {
  420. ctx->run_reader = 0;
  421. err = pthread_join(ctx->rthread, &retcode);
  422. if (err) pcilib_error("Error joining the reader thread");
  423. }
  424. if (ctx->preproc) {
  425. ctx->run_preprocessors = 0;
  426. for (i = 0; i < ctx->n_preproc; i++) {
  427. if (ctx->preproc[i].started) {
  428. pthread_join(ctx->preproc[i].thread, &retcode);
  429. ctx->preproc[i].started = 0;
  430. }
  431. }
  432. if (ctx->preproc_mutex_destroy) {
  433. pthread_mutex_destroy(&ctx->preproc_mutex);
  434. ctx->preproc_mutex_destroy = 0;
  435. }
  436. free(ctx->preproc);
  437. ctx->preproc = NULL;
  438. }
  439. if (ctx->frame_mutex_destroy) {
  440. for (i = 0; i < ctx->frame_mutex_destroy; i++) {
  441. pthread_rwlock_destroy(&ctx->frame[i].mutex);
  442. }
  443. ctx->frame_mutex_destroy = 0;
  444. }
  445. if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) {
  446. pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  447. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  448. }
  449. while (ctx->streaming) {
  450. usleep(IPECAMERA_NOFRAME_SLEEP);
  451. }
  452. if (ctx->ipedec) {
  453. ufo_decoder_free(ctx->ipedec);
  454. ctx->ipedec = NULL;
  455. }
  456. if (ctx->frame) {
  457. free(ctx->frame);
  458. ctx->frame = NULL;
  459. }
  460. if (ctx->cmask) {
  461. free(ctx->cmask);
  462. ctx->cmask = NULL;
  463. }
  464. if (ctx->image) {
  465. free(ctx->image);
  466. ctx->image = NULL;
  467. }
  468. if (ctx->buffer) {
  469. free(ctx->buffer);
  470. ctx->buffer = NULL;
  471. }
  472. memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t));
  473. ctx->event_id = 0;
  474. ctx->reported_id = 0;
  475. ctx->buffer_pos = 0;
  476. ctx->started = 0;
  477. return 0;
  478. }
  479. int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
  480. int err = 0;
  481. pcilib_register_value_t value;
  482. ipecamera_t *ctx = (ipecamera_t*)vctx;
  483. pcilib_t *pcilib = vctx->pcilib;
  484. const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  485. if (!ctx) {
  486. pcilib_error("IPECamera imaging is not initialized");
  487. return PCILIB_ERROR_NOTINITIALIZED;
  488. }
  489. pcilib_sleep_until_deadline(&ctx->next_trigger);
  490. /*
  491. GET_REG(num_frames_reg, value);
  492. if (value == ctx->max_frames) {
  493. return PCILIB_ERROR_BUSY;
  494. }
  495. */
  496. GET_REG(status2_reg, value);
  497. if (value&0x40000000) {
  498. if (value == 0xffffffff)
  499. pcilib_info("Failed to read status2_reg while triggering");
  500. #ifdef IPECAMERA_TRIGGER_TIMEOUT
  501. if (IPECAMERA_TRIGGER_TIMEOUT) {
  502. struct timeval deadline;
  503. pcilib_calc_deadline(&deadline, IPECAMERA_TRIGGER_TIMEOUT);
  504. do {
  505. usleep(IPECAMERA_READ_STATUS_DELAY);
  506. GET_REG(status2_reg, value);
  507. } while ((value&0x40000000)&&(pcilib_calc_time_to_deadline(&deadline) > 0));
  508. }
  509. if (value&0x40000000)
  510. #endif /* IPECAMERA_TRIGGER_WAIT_IDLE */
  511. return PCILIB_ERROR_BUSY;
  512. }
  513. GET_REG(control_reg, value);
  514. SET_REG(control_reg, value|IPECAMERA_FRAME_REQUEST);
  515. usleep(IPECAMERA_TRIGGER_DELAY);
  516. SET_REG(control_reg, value);
  517. // DS: We need to compute it differently, on top of that add exposure time and the time FPGA takes to read frame from CMOSIS
  518. pcilib_calc_deadline(&ctx->next_trigger, IPECAMERA_NEXT_FRAME_DELAY);
  519. return 0;
  520. }