Zoom_H6: Library for controling Zoom H6 Recorder

This library enables sending control commands and receiving device
status from the Zoom H6 audio recorder
This commit is contained in:
Tomer Rubinstein 2019-10-28 16:19:31 +02:00
commit 9442036542
4 changed files with 198 additions and 0 deletions

19
library.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "Zoom_H6_Remote",
"version": "1.0.0-rc",
"frameworks": "arduino",
"platforms": "*",
"keywords": "ZOOM,H6,Remote",
"description": "Library for controling Zoom H6 audio recorder with Arduino framework",
"repository": {
"type": "git",
"url": "https://github.com/tomer99r/ZoomH6_Arduino.git"
},
"authors": [
{
"name": "Tomer Rubinstein",
"email": "tomer99r@gmail.com",
"maintainer": true
}
]
}

10
library.properties Normal file
View file

@ -0,0 +1,10 @@
name=Zoom_H6_Remote
version=1.0.0-rc
author=Tomer Rubinstein <tomer99r@gmail.com>
maintainer=Tomer Rubinstein <tomer99r@gmail.com>
sentence=Library for contorling Zoom H6 audio recorder with Arduino framework
paragraph=This library enables sending commands and getting status from Zoom H6 audio recorder using Arduino framework.
category=Device Control
url=https://github.com/tomer99r/ZoomH6_Arduino.git
includes=ZoomH6.h
architectures=*

114
src/ZoomH6.cpp Normal file
View file

@ -0,0 +1,114 @@
#include "ZoomH6.h"
static const byte handshakeSeq[] = {0xC2, 0xE1, 0x31, 0x2E, 0x30, 0x30,0xA1,0x80,0x00 };
static const byte handshakeReply[] = {0x82, 0x83, 0x80, 0x81};
ZoomH6Remote::ZoomH6Remote(HardwareSerial* serial, Stream* debug, uint32_t timeout) :
_serial(serial), _debug(debug), _timeout(timeout) {}
/*This will write the data to the serial, and return the expected number of replys
in case of failure the result is negative */
int8_t ZoomH6Remote::writeWithReply(byte* data, size_t dataLength, byte* reply, size_t replyLength) {
int8_t respCount = 0;
for (int i = 0; i < dataLength; ++i) {
_serial->write(data[i]);
}
uint32_t timeout = millis() + _timeout;
do {
if (_serial->available()) {
byte resp = _serial->read();
if (reply != nullptr) {
reply[respCount % replyLength] = resp;
}
timeout = millis() + _timeout;
respCount++;
}
} while (millis() <= timeout);//respCount < replyLength);
return respCount;
}
bool ZoomH6Remote::initialize() {
byte reply[3] = {0};
if(*_serial) _serial->end();
_serial->begin(2400, SERIAL_8N1); // connection to Zoom.
uint32_t timeout = millis() + 10000;
while (!*_serial) {
if(millis() > timeout) goto FAIL_TIME;
}
timeout = millis() + 10000;
do {
if(_serial->available()) {
reply[0] = _serial->read();
} else {
_serial->write(0x00);
delay(200);
}
if(millis() > timeout) return false;
} while(reply[0] != 0x82);
if (!writeWithReply(handshakeSeq, 1, reply, 1)) goto FAIL_TIME;
if (reply[0] != handshakeReply[1]) goto FAIL_RES;
if (!writeWithReply(&handshakeSeq[1], 5, reply, 1)) goto FAIL_TIME;
if (reply[0] != handshakeReply[2]) goto FAIL_RES;
if (!writeWithReply(&handshakeSeq[6], 1, reply, 1)) goto FAIL_TIME;
if (reply[0] != handshakeReply[3]) goto FAIL_RES;
writeWithReply(&handshakeSeq[7], 2, reply, 3); //clear status
printStatus(reply[1], reply[2]);
return true;
FAIL_TIME:
if (_debug) _debug->println("Failed handshake - timeout");
return false;
FAIL_RES:
if (_debug) {
for (int i = 0; i < 3; i++) {
_debug->println(reply[i]);
}
_debug->println("Failed handshake - invalid return value");
}
return false;
}
void ZoomH6Remote::printStatus(byte& high, byte& low) {
if (_debug) {
if (high == 0x00 && low == 0x00) _debug->println("No Channel Record Ready!");
if (high & StatusHigh::Record_on) _debug->println("Start Recording");
if (high & StatusHigh::Channel_L_on) _debug->println("Left Channel Enabled");
if (high & StatusHigh::Channel_R_on) _debug->println("Right Channel Enabled");
if (high & StatusHigh::Channel_1_on) _debug->println("Channel 1 Enabled");
if (low & StatusLow::Channel_2_on) _debug->println("Channel 2 Enabled");
if (low & StatusLow::Channel_3_on) _debug->println("Channel 3 Enabled");
if (low & StatusLow::Channel_4_on) _debug->println("Channel 4 Enabled");
}
}
/* This method is used to transmit commands for the Zoom,
* primary - the primary command
* secondary - the sub command
* gap - the time to set between sending a command to releasing it (getting the status) in millis
* debug - verbose of result status to the debug serial
*/
bool ZoomH6Remote::sendCommand(byte primary, byte secondary, uint32_t gap, byte* reply) {
byte command[2] = {primary, secondary};
byte releaseCom[2] = {Commands::SecFunc, SubCommands::Release };
if (!writeWithReply(command, 2, reply, 3)) return false;
if (reply != nullptr) printStatus(reply[1], reply[2]);
if (gap) delay(gap);
if (!writeWithReply(releaseCom, 2, nullptr, 3)) return false;
return true;
}

55
src/ZoomH6.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef ZOOM_H6_H
#define ZOOM_H6_H
#include "Arduino.h"
enum Commands {
Record = 0x81,
Play = 0x82,
SkipBackward = 0x84,
SkipForward = 0x88,
Stop = 0x90,
SecFunc = 0x80,
};
enum SubCommands {
Release = 0x00,
Channel_L = 0x01,
Channel_R = 0x02,
Channel_1 = 0x04,
Channel_2 = 0x08,
Channel_3 = 0x10,
Channel_4 = 0x20,
VolumeDown = 0x40,
VolumeUp = 0x80,
};
enum StatusHigh {
Record_on = 0x01,
Channel_L_on = 0x20,
Channel_R_on = 0x08,
Channel_1_on = 0x02,
};
enum StatusLow {
Channel_2_on = 0x20,
Channel_3_on = 0x08,
Channel_4_on = 0x02,
};
class ZoomH6Remote {
public:
ZoomH6Remote(HardwareSerial* serial, Stream* debug = nullptr, uint32_t timeout = 40);
~ZoomH6Remote() = default;
bool initialize();
bool sendCommand(byte primary, byte secondary, uint32_t gap, byte* reply = nullptr);
private:
int8_t writeWithReply(byte* data, size_t dataLength, byte* reply, size_t replyLength);
void printStatus(byte& high, byte& low);
Stream* _debug;
uint32_t _timeout;
HardwareSerial* _serial;
};
#endif