base.c 18 KB

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