diff --git a/visca_controller/src/Visca.cpp b/visca_controller/src/Visca.cpp new file mode 100644 index 0000000..32aa647 --- /dev/null +++ b/visca_controller/src/Visca.cpp @@ -0,0 +1,78 @@ +#include "Visca.h" + +Visca::Visca(bool debug) +{ + Visca::debug = debug; +} + +void Visca::begin(Stream &viscaControl, Stream &debugOutput) +{ + Visca::viscaControl = viscaControl; + Visca::debugOutput = debugOutput; +} + +void Visca::sendPacket(unsigned char *packet, int byteSize) { + if (Visca::debug == true) { + Visca::debugOutput.print("Sending:"); + } + for (int i = 0; i < byteSize; i++) { + if (Visca::debug == true) { + Visca::debugOutput.print(" 0x"); + Visca::debugOutput.print(packet[i], HEX); + } + + Visca::viscaControl.write(packet[i]); + } + if (Visca::debug == true) { + Visca::debugOutput.println(); + } +} + +void Visca::receiveViscaData() { + static unsigned char ndx = 0; + while (Visca::viscaControl.available() > 0) { + unsigned char rc = Visca::viscaControl.read(); + + if (rc != 0xFF) { + Visca::viscaMessage[ndx] = rc; + ndx++; + if (ndx >= Visca::maxViscaMessageSize) { + ndx = Visca::maxViscaMessageSize - 1; + } + } else { + if (Visca::viscaMessage[0] == 0x90) { + if (Visca::debug == true) { + if (Visca::viscaMessage[1] == 0x50) { + Visca::debugOutput.println("Command: OK"); + } + } + + if (Visca::viscaMessage[1] == 0x60) { + switch (Visca::viscaMessage[2]) { + case 0x01: + Visca::debugOutput.println("Error: Message length error"); + case 0x02: + Visca::debugOutput.println("Error: Syntax error"); + case 0x03: + Visca::debugOutput.println("Error: Command buffer full"); + case 0x04: + Visca::debugOutput.println("Error: Command cancelled"); + case 0x05: + Visca::debugOutput.println("Error: No socket (to be cancelled)"); + case 0x41: + Visca::debugOutput.println("Error: Command not executable"); + default: + Visca::debugOutput.print("Unknown Error: "); + for (uint8_t i = 0; i < ndx; i++) { + Visca::debugOutput.print("0x"); + Visca::debugOutput.print(viscaMessage[i], HEX); + Visca::debugOutput.print(" "); + } + Visca::debugOutput.println("0xFF"); + } + } + } + ndx = 0; + } + } +} diff --git a/visca_controller/src/Visca.h b/visca_controller/src/Visca.h new file mode 100644 index 0000000..f6db202 --- /dev/null +++ b/visca_controller/src/Visca.h @@ -0,0 +1,80 @@ +#ifndef VISCA_CONTROLLER_VISCA_H +#define VISCA_CONTROLLER_VISCA_H + +#include + +class Visca +{ +private: + Stream& viscaControl; + Stream& debugOutput; + bool debug = false; + + // Pan/Tilt + unsigned char panTilt[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x03, 0xFF }; + unsigned char panUp[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x01, 0xFF }; // 8x 01 06 01 0p 0t 03 01 ff + unsigned char panDown[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0xFF }; // 8x 01 06 01 0p 0t 03 02 ff + unsigned char panLeft[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x01, 0x03, 0xFF }; // 8x 01 06 01 0p 0t 01 03 ff + unsigned char panRight[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x02, 0x03, 0xFF }; // 8x 01 06 01 0p 0t 02 03 ff + unsigned char panUpLeft[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x01, 0x01, 0xFF }; // 8x 01 06 01 0p 0t 01 01 ff + unsigned char panUpRight[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x02, 0x01, 0xFF }; // 8x 01 06 01 0p 0t 02 01 ff + unsigned char panDownLeft[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0xFF }; // 8x 01 06 01 0p 0t 01 02 ff + unsigned char panDownRight[9] = { 0x81, 0x01, 0x06, 0x01, 0x00, 0x00, 0x02, 0x02, 0xFF }; // 8x 01 06 01 0p 0t 02 02 ff + + unsigned char panStop[9] = { 0x81, 0x01, 0x06, 0x01, 0x09, 0x09, 0x03, 0x03, 0xFF }; // Camera Stop + unsigned char panTiltPosReq[5] = { 0x81, 0x09, 0x06, 0x12, 0xff }; // Resp: y0 50 0p 0q 0r 0s 0t 0u 0v 0w ff ; pqrs: pan position ; tuvw: tilt position + + // Zoom + // Tele: 8x 01 04 07 2p ff + // Wide: 8x 01 04 07 2p ff + unsigned char zoomCommand[6] = { 0x81, 0x01, 0x04, 0x07, 0x2F, 0xff }; // 8x 01 04 07 2p ff + unsigned char zoomTele[6] = { 0x81, 0x01, 0x04, 0x07, 0x2F, 0xff }; // 8x 01 04 07 2p ff + unsigned char zoomWide[6] = { 0x81, 0x01, 0x04, 0x07, 0x3F, 0xff }; // 8x 01 04 07 3p ff + unsigned char zoomStop[6] = { 0x81, 0x01, 0x04, 0x07, 0x00, 0xff }; + unsigned char zoomDirect[9] = { 0x81, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xff }; // 8x 01 04 47 0p 0q 0r 0s ff pqrs: zoomCommand position + unsigned char zoomPosReq[5] = { 0x81, 0x09, 0x04, 0x47, 0xff }; // Resp: y0 50 0p 0q 0r 0s ff + + + // Focus + unsigned char focusAuto[6] = { 0x81, 0x01, 0x04, 0x38, 0x02, 0xff }; + unsigned char focusManual[6] = { 0x81, 0x01, 0x04, 0x38, 0x03, 0xff }; + unsigned char focusDirect[9] = { 0x81, 0x01, 0x04, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff }; // 8x 01 04 48 0p 0q 0r 0s ff pqrs: focus position + unsigned char focusFar[6] = { 0x81, 0x01, 0x04, 0x08, 0x20, 0xff }; + unsigned char focusNear[6] = { 0x81, 0x01, 0x04, 0x08, 0x30, 0xff }; + unsigned char focusStop[6] = { 0x81, 0x01, 0x04, 0x08, 0x00, 0xff }; + unsigned char focusModeInq[5] = { 0x81, 0x09, 0x04, 0x38, 0xff }; // Resp: y0 50 0p ff ; p=2: Auto, p=3: Manual + + // Iris / Gain + unsigned char aeAuto[6] = { 0x81, 0x01, 0x04, 0x39, 0x00, 0xff }; + unsigned char aeManual[6] = { 0x81, 0x01, 0x04, 0x39, 0x03, 0xff }; + unsigned char irisDirect[9] = { 0x81, 0x01, 0x04, 0x4B, 0x00, 0x00, 0x00, 0x00, 0xff }; // 8x 01 04 4B 0p 0q 0r 0s ff pqrs: Iris position, range 0..50 + unsigned char gainDirect[9] = { 0x81, 0x01, 0x04, 0x4C, 0x00, 0x00, 0x00, 0x00, 0xff }; // 8x 01 04 4c 0p 0q 0r 0s ff pqrs: Gain position, values: 12-21dB. + unsigned char aeModeInq[5] = { 0x81, 0x09, 0x04, 0x39, 0xff }; // Resp: y0 50 0p ff ; p=0: Auto, p=3: Manual + + // White Balance + unsigned char wbAuto[6] = { 0x81, 0x01, 0x04, 0x35, 0x00, 0xff }; + unsigned char wbTableManual[6] = { 0x81, 0x01, 0x04, 0x35, 0x06, 0xff }; + unsigned char wbTableDirect[9] = { 0x81, 0x01, 0x04, 0x75, 0x00, 0x00, 0x0, 0x00, 0xff }; // 8x 01 04 75 0p 0q 0r 0s ff pqrs = wb table. + + // Config + unsigned char address_command[4] = { 0x88, 0x30, 0x01, 0xFF }; // Sets camera address (Needed for Daisy Chaining) + unsigned char if_clear[5] = { 0x88, 0x01, 0x00, 0x01, 0xFF }; // Checks to see if communication line is clear + unsigned char ir_off[6] = { 0x81, 0x01, 0x06, 0x09, 0x03, 0xff }; // Turn off IR control (required for speed control of Pan/Tilt on TelePresence cameras) + unsigned char callLedOn[6] = { 0x81, 0x01, 0x33, 0x01, 0x01, 0xff}; + unsigned char callLedOff[6] = { 0x81, 0x01, 0x33, 0x01, 0x00, 0xff}; + unsigned char callLedBlink[6] = { 0x81, 0x01, 0x33, 0x01, 0x02, 0xff}; + + const unsigned char maxViscaMessageSize = 16; + unsigned char viscaMessage[16]; +private: +// void sendPacket(unsigned char *packet, int byteSize); + +public: + Visca(bool debug = false); + void begin(Stream &viscaControl, Stream &debugOutput); + void receiveViscaData(); + void sendPacket(unsigned char *packet, int byteSize); +}; + + +#endif //VISCA_CONTROLLER_VISCA_H