base.c 20 KB

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