26 #include <core/exceptions/system.h>
27 #include <sys/ioctl.h>
104 Visca::Visca(
const char *device_file,
unsigned int def_timeout_ms,
bool blocking)
106 inquire_ = VISCA_RUNINQ_NONE;
107 device_file_ = strdup(device_file);
108 blocking_ = blocking;
110 default_timeout_ms_ = def_timeout_ms;
115 nonblocking_sockets_[i] = 0;
116 nonblocking_running_[i] =
false;
136 struct termios param;
138 fd_ =
::open(device_file_, O_RDWR);
143 if (tcgetattr(fd_, ¶m) == -1) {
149 cfsetospeed(¶m, B9600);
150 cfsetispeed(¶m, B9600);
152 param.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
153 param.c_cflag |= CREAD;
154 param.c_cflag |= CLOCAL;
157 param.c_cc[VMIN] = 1;
158 param.c_cc[VTIME] = 0;
160 param.c_iflag |= IGNBRK;
161 param.c_iflag &= ~PARMRK;
162 param.c_iflag &= ~ISTRIP;
163 param.c_iflag &= ~INLCR;
164 param.c_iflag &= ~IGNCR;
165 param.c_iflag &= ~ICRNL;
166 param.c_iflag &= ~IXON;
167 param.c_iflag &= ~IXOFF;
169 param.c_lflag &= ~ECHO;
172 param.c_lflag |= IEXTEN;
173 param.c_oflag &= ~OPOST;
179 param.c_cflag &= ~CS5 & ~CS6 & ~CS7 & ~CS8;
181 param.c_cflag |= CS8;
184 param.c_cflag &= ~(PARENB & PARODD);
187 param.c_cflag &= ~CSTOPB;
189 if (tcsetattr(fd_, TCSANOW, ¶m) != 0) {
197 sender_ = VISCA_BUS_0;
198 recipient_ = VISCA_BUS_1;
200 #ifdef TIMETRACKER_VISCA
201 tt_ =
new TimeTracker();
202 ttc_pantilt_get_send_ = tt_->addClass(
"getPanTilt: send");
203 ttc_pantilt_get_read_ = tt_->addClass(
"getPanTilt: read");
204 ttc_pantilt_get_handle_ = tt_->addClass(
"getPanTilt: handling responses");
205 ttc_pantilt_get_interpret_ = tt_->addClass(
"getPanTilt: interpreting");
223 unsigned char recp_backup = recipient_;
224 recipient_ = VISCA_BUS_BROADCAST;
233 recipient_ = recp_backup;
237 recipient_ = recp_backup;
256 e.
append(
"clear() failed");
270 obuffer_[0] |= (sender_ << 4);
271 obuffer_[0] |= recipient_;
273 obuffer_[++obuffer_length_] = VISCA_TERMINATOR;
276 int written = write(fd_, obuffer_, obuffer_length_);
282 if (written < obuffer_length_) {
294 ioctl(fd_, FIONREAD, &num_bytes);
295 return (num_bytes > 0);
304 if (timeout_ms == 0xFFFFFFFF)
305 timeout_ms = default_timeout_ms_;
307 recv_packet(timeout_ms);
309 e.
append(
"Receiving failed, recv_packet() call failed");
314 unsigned char type = ibuffer_[1] & 0xF0;
315 while (type == VISCA_RESPONSE_ACK) {
317 recv_packet(timeout_ms);
319 e.
append(
"Receiving failed, recv_packet() call 2 failed");
322 type = ibuffer_[1] & 0xF0;
326 case VISCA_RESPONSE_CLEAR:
327 case VISCA_RESPONSE_ADDRESS:
328 case VISCA_RESPONSE_COMPLETED:
329 case VISCA_RESPONSE_ERROR:
break;
330 default:
throw fawkes::Exception(
"Receiving failed, unexpected packet type %u received", type);
341 recv_packet(default_timeout_ms_);
347 unsigned char type = ibuffer_[1] & 0xF0;
348 while (type != VISCA_RESPONSE_ACK) {
351 recv_packet(default_timeout_ms_);
353 e.
append(
"Handling message of type %u failed", type);
356 type = ibuffer_[1] & 0xF0;
360 if (socket != NULL) {
361 *socket = ibuffer_[1] & 0x0F;
376 e.
append(
"Non-blocking send failed!");
385 Visca::finish_nonblocking(
unsigned int socket)
388 if (nonblocking_sockets_[i] == socket) {
389 nonblocking_sockets_[i] = 0;
390 nonblocking_running_[i] =
false;
395 throw ViscaException(
"finish_nonblocking() failed: socket not found");
408 return !nonblocking_running_[item];
418 if (obuffer_[1] == VISCA_COMMAND) {
435 e.
append(
"Sending with reply failed");
444 Visca::recv_packet(
unsigned int timeout_ms)
447 timeval timeout = {0, (suseconds_t)timeout_ms * 1000};
451 FD_SET(fd_, &read_fds);
454 rv = select(fd_ + 1, &read_fds, NULL, NULL, &timeout);
458 }
else if (rv == 0) {
463 if (read(fd_, ibuffer_, 1) != 1) {
468 while ((pos <
sizeof(ibuffer_) - 1) && ibuffer_[pos] != VISCA_TERMINATOR) {
469 if (read(fd_, &ibuffer_[++pos], 1) != 1) {
474 ibuffer_length_ = pos + 1;
484 Visca::handle_response()
486 unsigned int type = ibuffer_[1] & 0xF0;
487 unsigned int socket = ibuffer_[1] & 0x0F;
495 if (type == VISCA_RESPONSE_COMPLETED) {
498 finish_nonblocking(ibuffer_[1] & 0x0F);
504 }
else if (type == VISCA_RESPONSE_ERROR) {
505 finish_nonblocking(ibuffer_[1] & 0x0F);
521 unsigned char cancel_socket = socket & 0x0000000F;
523 obuffer_[1] = VISCA_CANCEL | cancel_socket;
529 e.
append(
"cancel_command() failed");
533 if (((ibuffer_[1] & 0xF0) == VISCA_RESPONSE_ERROR) && ((ibuffer_[1] & 0x0F) == cancel_socket)
534 && ((ibuffer_[2] == VISCA_ERROR_CANCELLED))) {
545 inquire_ = VISCA_RUNINQ_NONE;
564 obuffer_[1] = VISCA_COMMAND;
565 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
566 obuffer_[3] = VISCA_POWER;
567 obuffer_[4] = powered ? VISCA_POWER_ON : VISCA_POWER_OFF;
573 e.
append(
"set_power() failed");
584 obuffer_[1] = VISCA_INQUIRY;
585 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
586 obuffer_[3] = VISCA_POWER;
592 e.
append(
"Failed to get power data");
597 if (ibuffer_[1] == VISCA_RESPONSE_COMPLETED) {
598 return (ibuffer_[2] == VISCA_POWER_ON);
601 "is_powered(): inquiry failed, response code not VISCA_RESPONSE_COMPLETED");
625 unsigned short int tilt_val = 0 + tilt;
626 unsigned short int pan_val = 0 + pan;
628 obuffer_[1] = VISCA_COMMAND;
629 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
630 obuffer_[3] = VISCA_PT_ABSOLUTE_POSITION;
631 obuffer_[4] = pan_speed_;
632 obuffer_[5] = tilt_speed_;
635 obuffer_[6] = (pan_val & 0xf000) >> 12;
636 obuffer_[7] = (pan_val & 0x0f00) >> 8;
637 obuffer_[8] = (pan_val & 0x00f0) >> 4;
638 obuffer_[9] = (pan_val & 0x000f);
640 obuffer_[10] = (tilt_val & 0xf000) >> 12;
641 obuffer_[11] = (tilt_val & 0x0f00) >> 8;
642 obuffer_[12] = (tilt_val & 0x00f0) >> 4;
643 obuffer_[13] = (tilt_val & 0x000f);
645 obuffer_length_ = 13;
655 e.
append(
"setPanTilt() failed");
675 pan_speed_ = pan_speed;
676 tilt_speed_ = tilt_speed;
686 pan_speed = pan_speed_;
687 tilt_speed = tilt_speed_;
697 inquire_ = VISCA_RUNINQ_PANTILT;
699 obuffer_[1] = VISCA_INQUIRY;
700 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
701 obuffer_[3] = VISCA_PT_POSITION_INQ;
707 e.
append(
"startGetPanTilt() failed");
723 if (inquire_ != VISCA_RUNINQ_PANTILT) {
724 throw ViscaException(
"Inquiry running, but it is not a pan/tilt inquiry");
726 #ifdef TIMETRACKER_VISCA
727 tt_->ping_start(ttc_pantilt_get_read_);
735 #ifdef TIMETRACKER_VISCA
736 tt_->ping_end(ttc_pantilt_get_read_);
740 obuffer_[1] = VISCA_INQUIRY;
741 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
742 obuffer_[3] = VISCA_PT_POSITION_INQ;
746 #ifdef TIMETRACKER_VISCA
747 tt_->ping_start(ttc_pantilt_get_send_);
749 tt_->ping_end(ttc_pantilt_get_send_);
750 tt_->ping_start(ttc_pantilt_get_read_);
752 tt_->ping_end(ttc_pantilt_get_read_);
761 #ifdef TIMETRACKER_VISCA
762 tt_->ping_start(ttc_pantilt_get_handle_);
765 while (ibuffer_[1] != VISCA_RESPONSE_COMPLETED) {
776 #ifdef TIMETRACKER_VISCA
777 tt_->ping_end(ttc_pantilt_get_handle_);
778 tt_->ping_start(ttc_pantilt_get_interpret_);
782 if (ibuffer_[1] == VISCA_RESPONSE_COMPLETED) {
783 unsigned short int pan_val = 0;
784 unsigned short int tilt_val = 0;
786 pan_val |= (ibuffer_[2] & 0x0F) << 12;
787 pan_val |= (ibuffer_[3] & 0x0F) << 8;
788 pan_val |= (ibuffer_[4] & 0x0F) << 4;
789 pan_val |= (ibuffer_[5] & 0x0F);
791 tilt_val |= (ibuffer_[6] & 0x0F) << 12;
792 tilt_val |= (ibuffer_[7] & 0x0F) << 8;
793 tilt_val |= (ibuffer_[8] & 0x0F) << 4;
794 tilt_val |= (ibuffer_[9] & 0x0F);
796 if (pan_val < 0x8000) {
801 pan = pan_val - 0xFFFF;
804 if (tilt_val < 0x8000) {
809 tilt = tilt_val - 0xFFFF;
815 #ifdef TIMETRACKER_VISCA
816 tt_->ping_end(ttc_pantilt_get_interpret_);
817 tt_->print_to_stdout();
820 inquire_ = VISCA_RUNINQ_NONE;
827 obuffer_[1] = VISCA_COMMAND;
828 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
829 obuffer_[3] = VISCA_PT_LIMITSET;
830 obuffer_[3] = VISCA_PT_LIMITSET_CLEAR;
831 obuffer_[4] = VISCA_PT_LIMITSET_SET_UR;
840 obuffer_length_ = 12;
845 obuffer_[4] = VISCA_PT_LIMITSET_SET_DL;
849 e.
append(
"resetPanTiltLimit() failed");
864 obuffer_[1] = VISCA_COMMAND;
865 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
866 obuffer_[3] = VISCA_PT_LIMITSET;
867 obuffer_[3] = VISCA_PT_LIMITSET_SET;
868 obuffer_[4] = VISCA_PT_LIMITSET_SET_UR;
870 obuffer_[5] = (pan_right & 0xf000) >> 12;
871 obuffer_[6] = (pan_right & 0x0f00) >> 8;
872 obuffer_[7] = (pan_right & 0x00f0) >> 4;
873 obuffer_[8] = (pan_right & 0x000f);
875 obuffer_[9] = (tilt_up & 0xf000) >> 12;
876 obuffer_[10] = (tilt_up & 0x0f00) >> 8;
877 obuffer_[11] = (tilt_up & 0x00f0) >> 4;
878 obuffer_[12] = (tilt_up & 0x000f);
880 obuffer_length_ = 12;
884 obuffer_[4] = VISCA_PT_LIMITSET_SET_DL;
886 obuffer_[5] = (pan_left & 0xf000) >> 12;
887 obuffer_[6] = (pan_left & 0x0f00) >> 8;
888 obuffer_[7] = (pan_left & 0x00f0) >> 4;
889 obuffer_[8] = (pan_left & 0x000f);
891 obuffer_[9] = (tilt_down & 0xf000) >> 12;
892 obuffer_[10] = (tilt_down & 0x0f00) >> 8;
893 obuffer_[11] = (tilt_down & 0x00f0) >> 4;
894 obuffer_[12] = (tilt_down & 0x000f);
898 e.
append(
"setPanTiltLimit() failed");
907 obuffer_[1] = VISCA_COMMAND;
908 obuffer_[2] = VISCA_CATEGORY_PAN_TILTER;
909 obuffer_[3] = VISCA_PT_HOME;
915 e.
append(
"resetPanTilt() failed");
924 obuffer_[1] = VISCA_COMMAND;
925 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
926 obuffer_[3] = VISCA_ZOOM;
927 obuffer_[4] = VISCA_ZOOM_STOP;
933 e.
append(
"resetZoom() failed");
944 obuffer_[1] = VISCA_COMMAND;
945 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
946 obuffer_[3] = VISCA_ZOOM;
947 obuffer_[4] = VISCA_ZOOM_TELE_SPEED;
949 obuffer_[5] = (speed & 0x000f) | 0x0020;
955 e.
append(
"setZoomSpeedTele() failed");
966 obuffer_[1] = VISCA_COMMAND;
967 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
968 obuffer_[3] = VISCA_ZOOM;
969 obuffer_[4] = VISCA_ZOOM_WIDE_SPEED;
971 obuffer_[5] = (speed & 0x000f) | 0x0020;
977 e.
append(
"setZoomSpeedWide() failed");
988 obuffer_[1] = VISCA_COMMAND;
989 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
990 obuffer_[3] = VISCA_ZOOM_VALUE;
992 obuffer_[4] = (zoom & 0xf000) >> 12;
993 obuffer_[5] = (zoom & 0x0f00) >> 8;
994 obuffer_[6] = (zoom & 0x00f0) >> 4;
995 obuffer_[7] = (zoom & 0x000f);
1007 e.
append(
"setZoom() failed");
1018 obuffer_[1] = VISCA_INQUIRY;
1019 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1020 obuffer_[3] = VISCA_ZOOM_VALUE;
1021 obuffer_length_ = 3;
1026 e.
append(
"Failed to get zoom data");
1031 if (ibuffer_[1] == VISCA_RESPONSE_COMPLETED) {
1032 unsigned short int zoom_val = 0;
1034 zoom_val |= (ibuffer_[2] & 0x0F) << 12;
1035 zoom_val |= (ibuffer_[3] & 0x0F) << 8;
1036 zoom_val |= (ibuffer_[4] & 0x0F) << 4;
1037 zoom_val |= (ibuffer_[5] & 0x0F);
1042 "Failed to get zoom data failed, response code not VISCA_RESPONSE_COMPLETED");
1052 obuffer_[1] = VISCA_COMMAND;
1053 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1054 obuffer_[3] = VISCA_DZOOM;
1056 obuffer_[4] = VISCA_DZOOM_ON;
1058 obuffer_[4] = VISCA_DZOOM_OFF;
1060 obuffer_length_ = 4;
1065 e.
append(
"setZoomDigitalEnabled() failed");
1076 obuffer_[1] = VISCA_COMMAND;
1077 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1078 obuffer_[3] = VISCA_PICTURE_EFFECT;
1079 obuffer_[4] = filter;
1080 obuffer_length_ = 4;
1085 e.
append(
"applyEffect() failed");
1097 e.
append(
"resetEffect() failed");
1109 e.
append(
"applyEffectPastel() failed");
1121 e.
append(
"applyEffectNegArt() failed");
1133 e.
append(
"applyEffectSepia() failed");
1145 e.
append(
"applyEffectBnW() failed");
1157 e.
append(
"applyEffectSolarize() failed");
1169 e.
append(
"applyEffectMosaic() failed");
1181 e.
append(
"applyEffectSlim() failed");
1193 e.
append(
"applyEffectStretch() failed");
1204 obuffer_[1] = VISCA_INQUIRY;
1205 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1206 obuffer_[3] = VISCA_WB;
1207 obuffer_length_ = 3;
1212 e.
append(
"getWhiteBalanceMode() failed");
1216 while (ibuffer_[1] != VISCA_RESPONSE_COMPLETED) {
1223 e.
append(
"getWhiteBalanceMode() failed");
1229 if (ibuffer_[1] == VISCA_RESPONSE_COMPLETED) {
1232 throw ViscaException(
"Did not get 'request completed' response");
1242 obuffer_[1] = VISCA_COMMAND;
1243 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1244 obuffer_[3] = VISCA_MIRROR;
1245 obuffer_[4] = mirror ? VISCA_MIRROR_ON : VISCA_MIRROR_OFF;
1246 obuffer_length_ = 4;
1251 e.
append(
"set_mirror() failed");
1262 obuffer_[1] = VISCA_INQUIRY;
1263 obuffer_[2] = VISCA_CATEGORY_CAMERA1;
1264 obuffer_[3] = VISCA_MIRROR;
1265 obuffer_length_ = 3;
1270 e.
append(
"Failed to get mirror data");
1275 if (ibuffer_[1] == VISCA_RESPONSE_COMPLETED) {
1276 return (ibuffer_[2] != 0);
1278 throw ViscaException(
"Failed to get mirror data: zoom inquiry failed, "
1279 "response code not VISCA_RESPONSE_COMPLETED");
ViscaException(const char *msg)
Constructor.
Visca inquire running exception.
ViscaInquiryRunningException()
Constructor.
void set_mirror(bool mirror)
Sett mirror sate.
static const unsigned int VISCA_WHITEBALANCE_MANUAL
Manual white balance.
void set_pan_tilt(int pan, int tilt)
Set pan tilt.
static const unsigned int MAX_TILT_SPEED
Number of non-blocking items.
static const unsigned int VISCA_WHITEBALANCE_ATW
ATW white balance preset.
static const unsigned int NONBLOCKING_ZOOM
Non-blocking zoom item.
void set_zoom_speed_tele(unsigned int speed)
Set zoom speed in tele.
bool is_powered()
Check if camera is powered.
void open()
Open serial port.
void reset_zoom()
Reset zoom.
static const unsigned int VISCA_WHITEBALANCE_ONE_PUSH
One push white balance preset.
void clear()
Clear command buffers.
void recv_ack(unsigned int *socket=NULL)
Receive ACK packet.
void apply_effect_bnw()
Apply B/W effect.
void get_pan_tilt_speed(unsigned char &pan_speed, unsigned char &tilt_speed)
Get pan/tilt speed.
void recv(unsigned int timeout_ms=0xFFFFFFFF)
Receive data.
static const unsigned int VISCA_WHITEBALANCE_INDOOR
Indoor white balance preset.
bool is_nonblocking_finished(unsigned int item) const
Check if a non-blocking operation has been finished.
void cancel_command(unsigned int socket)
Cancel a running command.
static const unsigned int NONBLOCKING_NUM
Number of non-blocking items.
void get_pan_tilt(int &pan, int &tilt)
Get pan and tilt values.
void apply_effect_stretch()
Apply stretch effect.
void reset_effect()
Reset effects.
void get_zoom(unsigned int &zoom)
Get zoom.
static const unsigned int VISCA_WHITEBLANCE_AUTO
Automatic white balance.
void reset_pan_tilt_limit()
Reset pan/tilt limit.
void apply_effect_sepia()
Apply sepia effect.
void reset_pan_tilt()
Reset pan/tilt.
void set_zoom_speed_wide(unsigned int speed)
Set zoom speed in wide angle.
void apply_effect_mosaic()
Apply mosaic effect.
void apply_effect_neg_art()
Apply negative art effect.
void apply_effect_solarize()
Apply solarize effect.
void process()
Process incoming data.
void apply_effect_pastel()
Apply pastel effect.
bool data_available()
Check data availability.
void set_pan_tilt_speed(unsigned char pan_speed, unsigned char tilt_speed)
Set pan/tilt speed.
void set_power(bool powered)
Set power state.
void send_nonblocking(unsigned int *socket=NULL)
Send non-blocking.
void send()
Send outbound queue.
void set_address()
Set addresses of cameras.
virtual ~Visca()
Destructor.
void set_zoom(unsigned int zoom)
Set zoom.
static const unsigned int MAX_PAN_SPEED
Number of non-blocking items.
void set_zoom_digital_enabled(bool enabled)
Enable or disable digital zoome.
void apply_effect(unsigned char effect)
Apply effect.
unsigned int get_white_balance_mode()
Get white balance mode.
static const unsigned int NONBLOCKING_PANTILT
Non-blocking pan/tilt item.
void set_pan_tilt_limit(int pan_left, int pan_right, int tilt_up, int tilt_down)
Set pan tilt limit.
bool get_mirror()
Get mirror sate.
static const unsigned int VISCA_WHITEBALANCE_OUTDOOR
Outdoor white balance preset.
Visca(const char *device_file, unsigned int def_timeout_ms=10, bool blocking=true)
Constructor.
void send_with_reply()
Send and wait for reply, blocking.
void apply_effect_slim()
Apply slim effect.
void start_get_pan_tilt()
Query for pan/tilt but do not wait until finished This will send an inquire to the camera that asks f...
Base class for exceptions in Fawkes.
void append(const char *format,...)
Append messages to the message list.
The current system call has timed out before completion.