image.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. #define _IPECAMERA_IMAGE_C
  2. #define _BSD_SOURCE
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/time.h>
  8. #include <pthread.h>
  9. #include <assert.h>
  10. #include <ufodecode.h>
  11. #include "../tools.h"
  12. #include "../error.h"
  13. #include "pcilib.h"
  14. #include "model.h"
  15. #include "event.h"
  16. #include "image.h"
  17. #include "dma/nwl_dma.h"
  18. #ifdef IPECAMERA_DEBUG
  19. #include "dma/nwl.h"
  20. #endif /* IPECAMERA_DEBUG */
  21. #define IPECAMERA_BUG_EXTRA_DATA
  22. #define IPECAMERA_BUG_MULTIFRAME_PACKETS
  23. #define IPECAMERA_BUG_INCOMPLETE_PACKETS
  24. #define IPECAMERA_DEFAULT_BUFFER_SIZE 64 //**< should be power of 2 */
  25. #define IPECAMERA_RESERVE_BUFFERS 2 //**< Return Frame is Lost error, if requested frame will be overwritten after specified number of frames
  26. #define IPECAMERA_SLEEP_TIME 250000 //**< Michele thinks 250 should be enough, but reset failing in this case */
  27. #define IPECAMERA_NEXT_FRAME_DELAY 1000 //**< Michele requires 30000 to sync between End Of Readout and next Frame Req */
  28. #define IPECAMERA_WAIT_FRAME_RCVD_TIME 0 //**< by Uros ,wait 6 ms */
  29. #define IPECAMERA_NOFRAME_SLEEP 100
  30. #define IPECAMERA_MAX_LINES 1088
  31. #define IPECAMERA_EXPECTED_STATUS 0x08409FFFF
  32. #define IPECAMERA_END_OF_SEQUENCE 0x1F001001
  33. #define IPECAMERA_MAX_CHANNELS 16
  34. #define IPECAMERA_PIXELS_PER_CHANNEL 128
  35. #define IPECAMERA_WIDTH (IPECAMERA_MAX_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL)
  36. /*
  37. #define IPECAMERA_HEIGHT 1088
  38. #if IPECAMERA_HEIGHT < IPECAMERA_MAX_LINES
  39. # undef IPECAMERA_MAX_LINES
  40. # define IPECAMERA_MAX_LINES IPECAMERA_HEIGHT
  41. #endif
  42. */
  43. //#define IPECAMERA_MEMORY
  44. #define IPECAMERA_FRAME_REQUEST 0x1E9
  45. #define IPECAMERA_READOUT_FLAG 0x200
  46. #define IPECAMERA_READOUT 0x3E1
  47. #define IPECAMERA_IDLE 0x1E1
  48. #define IPECAMERA_START_INTERNAL_STIMULI 0x1F1
  49. typedef uint32_t ipecamera_payload_t;
  50. typedef struct {
  51. pcilib_event_id_t evid;
  52. struct timeval timestamp;
  53. } ipecamera_autostop_t;
  54. struct ipecamera_s {
  55. pcilib_context_t event;
  56. ufo_decoder ipedec;
  57. char *data;
  58. ipecamera_pixel_t *image;
  59. size_t size;
  60. pcilib_event_callback_t cb;
  61. void *cb_user;
  62. pcilib_event_id_t event_id;
  63. pcilib_event_id_t reported_id;
  64. pcilib_dma_engine_t rdma, wdma;
  65. pcilib_register_t packet_len_reg;
  66. pcilib_register_t control_reg, status_reg;
  67. pcilib_register_t start_reg, end_reg;
  68. pcilib_register_t n_lines_reg;
  69. uint16_t line_reg;
  70. pcilib_register_t exposure_reg;
  71. pcilib_register_t flip_reg;
  72. int started; /**< Camera is in grabbing mode (start function is called) */
  73. int streaming; /**< Camera is in streaming mode (we are within stream call) */
  74. int parse_data; /**< Indicates if some processing of the data is required, otherwise only rawdata_callback will be called */
  75. int run_reader; /**< Instructs the reader thread to stop processing */
  76. int run_streamer; /**< Indicates request to stop streaming events and can be set by reader_thread upon exit or by user request */
  77. ipecamera_autostop_t autostop;
  78. struct timeval autostop_time;
  79. size_t buffer_size; /**< How many images to store */
  80. size_t buffer_pos; /**< Current image offset in the buffer, due to synchronization reasons should not be used outside of reader_thread */
  81. size_t cur_size; /**< Already written part of data in bytes */
  82. size_t raw_size; /**< Size of raw data in bytes */
  83. size_t full_size; /**< Size of raw data including the padding */
  84. size_t padded_size; /**< Size of buffer for raw data, including the padding for performance */
  85. size_t image_size; /**< Size of a single image in bytes */
  86. int width, height;
  87. // void *raw_buffer;
  88. void *buffer;
  89. ipecamera_change_mask_t *cmask;
  90. ipecamera_event_info_t *frame_info;
  91. ipecamera_image_dimensions_t dim;
  92. pthread_t rthread;
  93. };
  94. #define FIND_REG(var, bank, name) \
  95. ctx->var = pcilib_find_register(pcilib, bank, name); \
  96. if (ctx->var == PCILIB_REGISTER_INVALID) { \
  97. err = PCILIB_ERROR_NOTFOUND; \
  98. pcilib_error("Unable to find a %s register", name); \
  99. }
  100. #define GET_REG(reg, var) \
  101. if (!err) { \
  102. err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \
  103. if (err) { \
  104. pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
  105. } \
  106. }
  107. #define SET_REG(reg, val) \
  108. if (!err) { \
  109. err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \
  110. if (err) { \
  111. pcilib_error("Error writting %s register", ipecamera_registers[ctx->reg].name); \
  112. } \
  113. }
  114. #define CHECK_REG(reg, check) \
  115. if (!err) { \
  116. err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \
  117. if (err) { \
  118. pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
  119. } \
  120. if (!(check)) { \
  121. pcilib_error("Unexpected value (%li) of register %s", value, ipecamera_registers[ctx->reg].name); \
  122. err = PCILIB_ERROR_INVALID_DATA; \
  123. } \
  124. }
  125. #define CHECK_VALUE(value, val) \
  126. if ((!err)&&(value != val)) { \
  127. pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \
  128. err = PCILIB_ERROR_INVALID_DATA; \
  129. }
  130. #define CHECK_FLAG(flag, check, ...) \
  131. if ((!err)&&(!(check))) { \
  132. pcilib_error("Unexpected value (0x%x) of " flag, __VA_ARGS__); \
  133. err = PCILIB_ERROR_INVALID_DATA; \
  134. }
  135. pcilib_context_t *ipecamera_init(pcilib_t *pcilib) {
  136. int err = 0;
  137. ipecamera_t *ctx = malloc(sizeof(ipecamera_t));
  138. if (ctx) {
  139. memset(ctx, 0, sizeof(ipecamera_t));
  140. ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE;
  141. ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8;
  142. // We need DMA engine initialized to resolve DMA registers
  143. // FIND_REG(packet_len_reg, "fpga", "xrawdata_packet_length");
  144. FIND_REG(status_reg, "fpga", "status");
  145. FIND_REG(control_reg, "fpga", "control");
  146. FIND_REG(start_reg, "fpga", "start_address");
  147. FIND_REG(end_reg, "fpga", "end_address");
  148. FIND_REG(n_lines_reg, "cmosis", "number_lines");
  149. FIND_REG(line_reg, "cmosis", "start1");
  150. FIND_REG(exposure_reg, "cmosis", "exp_time");
  151. FIND_REG(flip_reg, "cmosis", "image_flipping");
  152. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  153. ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
  154. if (err) {
  155. free(ctx);
  156. return NULL;
  157. }
  158. }
  159. return (pcilib_context_t*)ctx;
  160. }
  161. void ipecamera_free(pcilib_context_t *vctx) {
  162. if (vctx) {
  163. ipecamera_t *ctx = (ipecamera_t*)vctx;
  164. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  165. free(ctx);
  166. }
  167. }
  168. pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) {
  169. ipecamera_t *ctx = (ipecamera_t*)vctx;
  170. pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib);
  171. if ((!model_info->dma_api)||(!model_info->dma_api->init)) {
  172. pcilib_error("The DMA engine is not configured in model");
  173. return NULL;
  174. }
  175. #ifdef IPECAMERA_DMA_R3
  176. return model_info->dma_api->init(vctx->pcilib, PCILIB_NWL_MODIFICATION_IPECAMERA, NULL);
  177. #else
  178. return model_info->dma_api->init(vctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL);
  179. #endif
  180. }
  181. int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) {
  182. if (ctx->started) {
  183. pcilib_error("Can't change buffer size while grabbing");
  184. return PCILIB_ERROR_INVALID_REQUEST;
  185. }
  186. if (size < 2) {
  187. pcilib_error("The buffer size is too small");
  188. return PCILIB_ERROR_INVALID_REQUEST;
  189. }
  190. if (((size^(size-1)) < size) < size) {
  191. pcilib_error("The buffer size is not power of 2");
  192. }
  193. ctx->buffer_size = size;
  194. return 0;
  195. }
  196. int ipecamera_reset(pcilib_context_t *vctx) {
  197. int err = 0;
  198. ipecamera_t *ctx = (ipecamera_t*)vctx;
  199. pcilib_t *pcilib = vctx->pcilib;
  200. pcilib_register_t control, status;
  201. pcilib_register_value_t value;
  202. if (!ctx) {
  203. pcilib_error("IPECamera imaging is not initialized");
  204. return PCILIB_ERROR_NOTINITIALIZED;
  205. }
  206. pcilib = vctx->pcilib;
  207. control = ctx->control_reg;
  208. status = ctx->status_reg;
  209. // Set Reset bit to CMOSIS
  210. err = pcilib_write_register_by_id(pcilib, control, 0x1e4);
  211. if (err) {
  212. pcilib_error("Error setting FPGA reset bit");
  213. return err;
  214. }
  215. usleep(IPECAMERA_SLEEP_TIME);
  216. // Remove Reset bit to CMOSIS
  217. err = pcilib_write_register_by_id(pcilib, control, 0x1e1);
  218. if (err) {
  219. pcilib_error("Error reseting FPGA reset bit");
  220. return err;
  221. }
  222. usleep(IPECAMERA_SLEEP_TIME);
  223. // Special settings for CMOSIS v.2
  224. value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value);
  225. if (err) {
  226. pcilib_error("Error setting CMOSIS configuration");
  227. return err;
  228. }
  229. usleep(IPECAMERA_SLEEP_TIME);
  230. value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value);
  231. if (err) {
  232. pcilib_error("Error setting CMOSIS configuration");
  233. return err;
  234. }
  235. usleep(IPECAMERA_SLEEP_TIME);
  236. // Set default parameters
  237. err = pcilib_write_register_by_id(pcilib, control, IPECAMERA_IDLE);
  238. if (err) {
  239. pcilib_error("Error bringing FPGA in default mode");
  240. return err;
  241. }
  242. usleep(10000);
  243. err = pcilib_read_register_by_id(pcilib, status, &value);
  244. if (err) {
  245. pcilib_error("Error reading status register");
  246. return err;
  247. }
  248. if (value != IPECAMERA_EXPECTED_STATUS) {
  249. pcilib_error("Unexpected value (%lx) of status register, expected %lx", value, IPECAMERA_EXPECTED_STATUS);
  250. return PCILIB_ERROR_VERIFY;
  251. }
  252. return 0;
  253. }
  254. // DS: Currently, on event_id overflow we are assuming the buffer is lost
  255. static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
  256. pcilib_event_id_t diff;
  257. if (evid > ctx->event_id) {
  258. diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
  259. if (diff >= ctx->buffer_size) return -1;
  260. } else {
  261. diff = ctx->event_id - evid;
  262. if (diff >= ctx->buffer_size) return -1;
  263. }
  264. // DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
  265. return (evid - 1) % ctx->buffer_size;
  266. }
  267. static inline int ipecamera_new_frame(ipecamera_t *ctx) {
  268. ctx->frame_info[ctx->buffer_pos].raw_size = ctx->cur_size;
  269. if (ctx->cur_size < ctx->raw_size) ctx->frame_info[ctx->buffer_pos].info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN;
  270. ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size;
  271. ctx->cur_size = 0;
  272. ctx->frame_info[ctx->buffer_pos].info.type = PCILIB_EVENT0;
  273. ctx->frame_info[ctx->buffer_pos].info.flags = 0;
  274. ctx->frame_info[ctx->buffer_pos].image_ready = 0;
  275. if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) {
  276. ctx->run_reader = 0;
  277. return 1;
  278. }
  279. if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) {
  280. ctx->run_reader = 0;
  281. return 1;
  282. }
  283. return 0;
  284. }
  285. static uint32_t frame_magic[6] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555, 0x56666666 };
  286. static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
  287. int eof = 0;
  288. #ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
  289. size_t extra_data = 0;
  290. #endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
  291. ipecamera_t *ctx = (ipecamera_t*)user;
  292. if (!ctx->cur_size) {
  293. #if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
  294. size_t startpos;
  295. for (startpos = 0; (startpos + 8) < bufsize; startpos++) {
  296. if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break;
  297. }
  298. if (startpos) {
  299. buf += startpos;
  300. bufsize -= startpos;
  301. }
  302. #endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
  303. if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) {
  304. /*
  305. // Not implemented in hardware yet
  306. ctx->frame_info[ctx->buffer_pos].info.seqnum = ((uint32_t*)buf)[6] & 0xF0000000;
  307. ctx->frame_info[ctx->buffer_pos].info.offset = ((uint32_t*)buf)[7] & 0xF0000000;
  308. */
  309. gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL);
  310. } else {
  311. // pcilib_warning("Frame magic is not found, ignoring broken data...");
  312. return PCILIB_STREAMING_CONTINUE;
  313. }
  314. }
  315. #ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
  316. if (ctx->cur_size + bufsize > ctx->raw_size) {
  317. size_t need;
  318. for (need = ctx->raw_size - ctx->cur_size; need < bufsize; need += sizeof(uint32_t)) {
  319. if (*(uint32_t*)(buf + need) == frame_magic[0]) break;
  320. }
  321. if (need < bufsize) {
  322. extra_data = bufsize - need;
  323. //bufsize = need;
  324. eof = 1;
  325. }
  326. // just rip of padding
  327. bufsize = ctx->raw_size - ctx->cur_size;
  328. }
  329. #endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
  330. if (ctx->parse_data) {
  331. if (ctx->cur_size + bufsize > ctx->full_size) {
  332. pcilib_error("Unexpected event data, we are expecting at maximum (%zu) bytes, but (%zu) already read", ctx->full_size, ctx->cur_size + bufsize);
  333. return -PCILIB_ERROR_TOOBIG;
  334. }
  335. memcpy(ctx->buffer + ctx->buffer_pos * ctx->padded_size + ctx->cur_size, buf, bufsize);
  336. }
  337. ctx->cur_size += bufsize;
  338. // printf("%i: %i %i\n", ctx->buffer_pos, ctx->cur_size, bufsize);
  339. if (ctx->cur_size >= ctx->full_size) eof = 1;
  340. if (ctx->event.params.rawdata.callback) {
  341. ctx->event.params.rawdata.callback(ctx->event_id, (pcilib_event_info_t*)(ctx->frame_info + ctx->buffer_pos), (eof?PCILIB_EVENT_FLAG_EOF:PCILIB_EVENT_FLAGS_DEFAULT), bufsize, buf, ctx->event.params.rawdata.user);
  342. }
  343. if (eof) {
  344. if (ipecamera_new_frame(ctx)) {
  345. return PCILIB_STREAMING_STOP;
  346. }
  347. #ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
  348. if (extra_data) {
  349. return ipecamera_data_callback(user, flags, extra_data, buf + bufsize);
  350. }
  351. #endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
  352. }
  353. return PCILIB_STREAMING_REQ_FRAGMENT;
  354. }
  355. static void *ipecamera_reader_thread(void *user) {
  356. int err;
  357. ipecamera_t *ctx = (ipecamera_t*)user;
  358. while (ctx->run_reader) {
  359. err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, PCILIB_DMA_TIMEOUT, &ipecamera_data_callback, user);
  360. if (err) {
  361. if (err == PCILIB_ERROR_TIMEOUT) {
  362. if (ctx->cur_size > ctx->raw_size) ipecamera_new_frame(ctx);
  363. #ifdef IPECAMERA_BUG_INCOMPLETE_PACKETS
  364. else if (ctx->cur_size > 0) ipecamera_new_frame(ctx);
  365. #endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
  366. if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) {
  367. ctx->run_reader = 0;
  368. break;
  369. }
  370. usleep(IPECAMERA_NOFRAME_SLEEP);
  371. } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err);
  372. } else printf("no error\n");
  373. //usleep(1000);
  374. }
  375. ctx->run_streamer = 0;
  376. if (ctx->cur_size)
  377. pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size);
  378. return NULL;
  379. }
  380. int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
  381. int err = 0;
  382. ipecamera_t *ctx = (ipecamera_t*)vctx;
  383. pcilib_t *pcilib = vctx->pcilib;
  384. pcilib_register_value_t value;
  385. const size_t chan_size = (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3) * sizeof(ipecamera_payload_t);
  386. const size_t line_size = (IPECAMERA_MAX_CHANNELS * chan_size);
  387. const size_t header_size = 8 * sizeof(ipecamera_payload_t);
  388. const size_t footer_size = 8 * sizeof(ipecamera_payload_t);
  389. size_t raw_size;
  390. size_t padded_blocks;
  391. pthread_attr_t attr;
  392. struct sched_param sched;
  393. if (!ctx) {
  394. pcilib_error("IPECamera imaging is not initialized");
  395. return PCILIB_ERROR_NOTINITIALIZED;
  396. }
  397. if (ctx->started) {
  398. pcilib_error("IPECamera grabbing is already started");
  399. return PCILIB_ERROR_INVALID_REQUEST;
  400. }
  401. // Allow readout and clean the FRAME_REQUEST mode if set for some reason
  402. SET_REG(control_reg, IPECAMERA_IDLE|IPECAMERA_READOUT_FLAG);
  403. usleep(IPECAMERA_SLEEP_TIME);
  404. CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS);
  405. if (err) return err;
  406. ctx->event_id = 0;
  407. ctx->reported_id = 0;
  408. ctx->buffer_pos = 0;
  409. ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
  410. ctx->cur_size = 0;
  411. ctx->dim.width = IPECAMERA_WIDTH;
  412. GET_REG(n_lines_reg, ctx->dim.height);
  413. raw_size = header_size + ctx->dim.height * line_size + footer_size;
  414. padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0);
  415. ctx->image_size = ctx->dim.width * ctx->dim.height;
  416. ctx->raw_size = raw_size;
  417. ctx->full_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH;
  418. #ifdef IPECAMERA_BUG_EXTRA_DATA
  419. ctx->full_size += 8;
  420. padded_blocks ++;
  421. #endif /* IPECAMERA_BUG_EXTRA_DATA */
  422. ctx->padded_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH;
  423. ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
  424. if (!ctx->buffer) {
  425. err = PCILIB_ERROR_MEMORY;
  426. pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
  427. return err;
  428. }
  429. ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  430. if (!ctx->image) {
  431. err = PCILIB_ERROR_MEMORY;
  432. pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
  433. return err;
  434. }
  435. ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
  436. if (!ctx->cmask) {
  437. err = PCILIB_ERROR_MEMORY;
  438. pcilib_error("Unable to allocate change-mask buffer");
  439. return err;
  440. }
  441. ctx->frame_info = malloc(ctx->buffer_size * sizeof(ipecamera_event_info_t));
  442. if (!ctx->frame_info) {
  443. err = PCILIB_ERROR_MEMORY;
  444. pcilib_error("Unable to allocate frame-info buffer");
  445. return err;
  446. }
  447. ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
  448. if (!ctx->ipedec) {
  449. pcilib_error("Unable to initialize IPECamera decoder library");
  450. return PCILIB_ERROR_FAILED;
  451. }
  452. if (!err) {
  453. ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS);
  454. if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) {
  455. err = PCILIB_ERROR_NOTFOUND;
  456. pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
  457. } else {
  458. err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  459. if (err) {
  460. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  461. pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
  462. }
  463. }
  464. }
  465. /*
  466. if (!err) {
  467. ctx->wdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_TO_DEVICE, IPECAMERA_DMA_ADDRESS);
  468. if (ctx->wdma == PCILIB_DMA_ENGINE_INVALID) {
  469. err = PCILIB_ERROR_NOTFOUND;
  470. pcilib_error("The S2C channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
  471. } else {
  472. err = pcilib_start_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
  473. if (err) {
  474. ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
  475. pcilib_error("Failed to initialize S2C channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
  476. }
  477. }
  478. }
  479. */
  480. /*
  481. SET_REG(packet_len_reg, IPECAMERA_DMA_PACKET_LENGTH);
  482. if (err) return err;
  483. */
  484. // Clean DMA
  485. err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
  486. if (err) {
  487. pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
  488. return err;
  489. }
  490. if (err) {
  491. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  492. return err;
  493. }
  494. if (vctx->params.autostop.duration) {
  495. gettimeofday(&ctx->autostop.timestamp, NULL);
  496. ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
  497. if (ctx->autostop.timestamp.tv_usec > 999999) {
  498. ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000;
  499. ctx->autostop.timestamp.tv_usec -= 1000000;
  500. } else {
  501. ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000;
  502. }
  503. }
  504. if (vctx->params.autostop.max_events) {
  505. ctx->autostop.evid = vctx->params.autostop.max_events;
  506. }
  507. ctx->started = 1;
  508. ctx->run_reader = 1;
  509. pthread_attr_init(&attr);
  510. if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
  511. pcilib_warning("Can't schedule a real-time thread, you may consider running as root");
  512. } else {
  513. sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial
  514. pthread_attr_setschedparam(&attr, &sched);
  515. }
  516. if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
  517. ctx->started = 0;
  518. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  519. err = PCILIB_ERROR_THREAD;
  520. }
  521. pthread_attr_destroy(&attr);
  522. return err;
  523. }
  524. int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
  525. int err;
  526. void *retcode;
  527. ipecamera_t *ctx = (ipecamera_t*)vctx;
  528. if (!ctx) {
  529. pcilib_error("IPECamera imaging is not initialized");
  530. return PCILIB_ERROR_NOTINITIALIZED;
  531. }
  532. if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) {
  533. ctx->run_reader = 0;
  534. return 0;
  535. }
  536. if (ctx->started) {
  537. ctx->run_reader = 0;
  538. err = pthread_join(ctx->rthread, &retcode);
  539. if (err) pcilib_error("Error joining the reader thread");
  540. }
  541. if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) {
  542. pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
  543. ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
  544. }
  545. if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) {
  546. pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
  547. ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
  548. }
  549. if (ctx->ipedec) {
  550. ufo_decoder_free(ctx->ipedec);
  551. ctx->ipedec = NULL;
  552. }
  553. if (ctx->frame_info) {
  554. free(ctx->frame_info);
  555. ctx->frame_info = NULL;
  556. }
  557. if (ctx->cmask) {
  558. free(ctx->cmask);
  559. ctx->cmask = NULL;
  560. }
  561. if (ctx->image) {
  562. free(ctx->image);
  563. ctx->image = NULL;
  564. }
  565. if (ctx->buffer) {
  566. free(ctx->buffer);
  567. ctx->buffer = NULL;
  568. }
  569. memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t));
  570. ctx->event_id = 0;
  571. ctx->reported_id = 0;
  572. ctx->buffer_pos = 0;
  573. ctx->started = 0;
  574. return 0;
  575. }
  576. int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
  577. int err = 0;
  578. pcilib_register_value_t value;
  579. ipecamera_t *ctx = (ipecamera_t*)vctx;
  580. pcilib_t *pcilib = vctx->pcilib;
  581. if (!ctx) {
  582. pcilib_error("IPECamera imaging is not initialized");
  583. return PCILIB_ERROR_NOTINITIALIZED;
  584. }
  585. if (!ctx->started) {
  586. pcilib_error("Can't trigger while grabbing is not started");
  587. return PCILIB_ERROR_INVALID_REQUEST;
  588. }
  589. SET_REG(control_reg, IPECAMERA_FRAME_REQUEST|IPECAMERA_READOUT_FLAG);
  590. usleep(IPECAMERA_WAIT_FRAME_RCVD_TIME);
  591. CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS);
  592. SET_REG(control_reg, IPECAMERA_IDLE|IPECAMERA_READOUT_FLAG);
  593. // DS: Just measure when next trigger is allowed instead and wait in the beginning
  594. usleep(IPECAMERA_NEXT_FRAME_DELAY); // minimum delay between End Of Readout and next Frame Req
  595. return 0;
  596. }
  597. int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) {
  598. int err = 0;
  599. int do_stop = 0;
  600. pcilib_event_id_t reported;
  601. ipecamera_t *ctx = (ipecamera_t*)vctx;
  602. size_t events = 0;
  603. struct timeval stream_stop;
  604. if (!ctx) {
  605. pcilib_error("IPECamera imaging is not initialized");
  606. return PCILIB_ERROR_NOTINITIALIZED;
  607. }
  608. ctx->streaming = 1;
  609. ctx->run_streamer = 1;
  610. if (!ctx->started) {
  611. err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
  612. if (err) {
  613. ctx->streaming = 0;
  614. pcilib_error("IPECamera is not in grabbing state");
  615. return PCILIB_ERROR_INVALID_STATE;
  616. }
  617. do_stop = 1;
  618. }
  619. // This loop iterates while the generation
  620. while ((ctx->run_streamer)||(ctx->reported_id != ctx->event_id)) {
  621. while (ctx->reported_id != ctx->event_id) {
  622. if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1) - IPECAMERA_RESERVE_BUFFERS;
  623. else ++ctx->reported_id;
  624. callback(ctx->reported_id, (pcilib_event_info_t*)(ctx->frame_info + ((ctx->reported_id-1)%ctx->buffer_size)), user);
  625. }
  626. usleep(IPECAMERA_NOFRAME_SLEEP);
  627. }
  628. ctx->streaming = 0;
  629. if (do_stop) {
  630. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  631. }
  632. return err;
  633. }
  634. int ipecamera_next_event(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_timeout_t timeout, pcilib_event_id_t *evid, pcilib_event_info_t **info) {
  635. struct timeval tv;
  636. ipecamera_t *ctx = (ipecamera_t*)vctx;
  637. if (!ctx) {
  638. pcilib_error("IPECamera imaging is not initialized");
  639. return PCILIB_ERROR_NOTINITIALIZED;
  640. }
  641. if (!ctx->started) {
  642. pcilib_error("IPECamera is not in grabbing mode");
  643. return PCILIB_ERROR_INVALID_REQUEST;
  644. }
  645. if (ctx->reported_id == ctx->event_id) {
  646. if (timeout) {
  647. pcilib_calc_deadline(&tv, timeout);
  648. while ((pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id))
  649. usleep(IPECAMERA_NOFRAME_SLEEP);
  650. }
  651. if (ctx->reported_id == ctx->event_id) return PCILIB_ERROR_TIMEOUT;
  652. }
  653. if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1) - IPECAMERA_RESERVE_BUFFERS;
  654. else ++ctx->reported_id;
  655. if (evid) *evid = ctx->reported_id;
  656. if (info) *info = (pcilib_event_info_t*)(ctx->frame_info + ((ctx->reported_id-1)%ctx->buffer_size));
  657. return 0;
  658. }
  659. inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
  660. int err;
  661. uint32_t tmp;
  662. uint16_t *pixels;
  663. int buf_ptr = (event_id - 1) % ctx->buffer_size;
  664. if (!ctx->frame_info[buf_ptr].image_ready) {
  665. if (ctx->frame_info[buf_ptr].info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) return PCILIB_ERROR_INVALID_DATA;
  666. ufo_decoder_set_raw_data(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size);
  667. pixels = ctx->image + buf_ptr * ctx->image_size;
  668. memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  669. err = ufo_decoder_get_next_frame(ctx->ipedec, &pixels, &tmp, &tmp, ctx->cmask + ctx->buffer_pos * ctx->dim.height);
  670. if (err) return PCILIB_ERROR_FAILED;
  671. ctx->frame_info[buf_ptr].image_ready = 1;
  672. if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
  673. ctx->frame_info[buf_ptr].image_ready = 0;
  674. return PCILIB_ERROR_TIMEOUT;
  675. }
  676. }
  677. return 0;
  678. }
  679. void* ipecamera_get(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void *data) {
  680. int err;
  681. int buf_ptr;
  682. size_t raw_size;
  683. ipecamera_t *ctx = (ipecamera_t*)vctx;
  684. uint16_t *pixels;
  685. if (!ctx) {
  686. pcilib_error("IPECamera imaging is not initialized");
  687. return NULL;
  688. }
  689. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  690. if (buf_ptr < 0) return NULL;
  691. switch ((ipecamera_data_type_t)data_type) {
  692. case IPECAMERA_RAW_DATA:
  693. raw_size = ctx->frame_info[buf_ptr].raw_size;
  694. if (data) {
  695. if ((!size)||(*size < raw_size)) return NULL;
  696. memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
  697. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
  698. *size = raw_size;
  699. return data;
  700. }
  701. if (size) *size = raw_size;
  702. return ctx->buffer + buf_ptr * ctx->padded_size;
  703. case IPECAMERA_IMAGE_DATA:
  704. err = ipecamera_decode_frame(ctx, event_id);
  705. if (err) return NULL;
  706. if (data) {
  707. if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return NULL;
  708. memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
  709. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
  710. *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  711. return data;
  712. }
  713. if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  714. return ctx->image + buf_ptr * ctx->image_size;
  715. case IPECAMERA_CHANGE_MASK:
  716. err = ipecamera_decode_frame(ctx, event_id);
  717. if (err) return NULL;
  718. if (data) {
  719. if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return NULL;
  720. memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  721. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
  722. *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  723. return data;
  724. }
  725. if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  726. return ctx->cmask + buf_ptr * ctx->dim.height;
  727. case IPECAMERA_DIMENSIONS:
  728. if (size) *size = sizeof(ipecamera_image_dimensions_t);
  729. return &ctx->dim;
  730. case IPECAMERA_IMAGE_REGION:
  731. case IPECAMERA_PACKED_IMAGE:
  732. // Shall we return complete image or only changed parts?
  733. case IPECAMERA_PACKED_LINE:
  734. case IPECAMERA_PACKED_PAYLOAD:
  735. pcilib_error("Support for data type (%li) is not implemented yet", data_type);
  736. return NULL;
  737. default:
  738. pcilib_error("Unknown data type (%li) is requested", data_type);
  739. return NULL;
  740. }
  741. }
  742. int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, void *data) {
  743. ipecamera_t *ctx = (ipecamera_t*)vctx;
  744. if (!ctx) {
  745. pcilib_error("IPECamera imaging is not initialized");
  746. return PCILIB_ERROR_NOTINITIALIZED;
  747. }
  748. if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
  749. return PCILIB_ERROR_NOTAVAILABLE;
  750. }
  751. return 0;
  752. }