-
Notifications
You must be signed in to change notification settings - Fork 787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add functionality for MiniDSP 2x4HD #737
base: master
Are you sure you want to change the base?
Changes from all commits
3a36dfe
69c6db7
8de0ef6
2c9e627
0bccd08
a21295d
fbed4d4
c89520f
6bc3157
2daa15b
db36383
cc9e7a7
8138098
869f083
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -22,21 +22,34 @@ | |||||
#include "MiniDSP.h" | ||||||
|
||||||
void MiniDSP::ParseHIDData(USBHID *hid __attribute__ ((unused)), bool is_rpt_id __attribute__ ((unused)), uint8_t len, uint8_t *buf) { | ||||||
|
||||||
constexpr uint8_t StatusInputCommand[] = {0x05, 0xFF, 0xDA}; | ||||||
|
||||||
// Only care about valid data for the MiniDSP 2x4HD. | ||||||
if(HIDUniversal::VID != MINIDSP_VID || HIDUniversal::PID != MINIDSP_PID || len <= 4 || buf == nullptr) | ||||||
return; | ||||||
|
||||||
// Check if this is a status update. | ||||||
// First byte is the length, we ignore that for now. | ||||||
if(memcmp(buf + 1, StatusInputCommand, sizeof (StatusInputCommand)) == 0) { | ||||||
// Check if this is a requested mute change. | ||||||
if(buf[1] == 0x17){ | ||||||
// Response is of format [ length ] [ 0x17 ] [ muted ] | ||||||
muted = (bool)buf[2]; | ||||||
} | ||||||
|
||||||
// Check if this is a requested volume change. | ||||||
if(buf[1] == 0x42){ | ||||||
// Response is of format [ length ] [ 0x42 ] [ volume ] | ||||||
volume = buf[2]; | ||||||
|
||||||
} | ||||||
|
||||||
constexpr uint8_t InputCommand[] = {0x05, 0xFF}; | ||||||
|
||||||
// Only deal with status updates from now on. | ||||||
if(memcmp(buf + 1, InputCommand, sizeof (InputCommand)) != 0) | ||||||
return; | ||||||
|
||||||
if(buf[3] == 0xDA){ | ||||||
// Parse data. | ||||||
// Response is of format [ length ] [ 0x05 0xFF 0xDA ] [ volume ] [ muted ]. | ||||||
const auto newVolume = buf[sizeof (StatusInputCommand) + 1]; | ||||||
const auto newIsMuted = (bool)buf[sizeof (StatusInputCommand) + 2]; | ||||||
const auto newVolume = buf[4]; | ||||||
const auto newIsMuted = (bool)buf[5]; | ||||||
|
||||||
const auto volumeChanged = newVolume != volume; | ||||||
const auto mutedChanged = newIsMuted != muted; | ||||||
|
@@ -52,15 +65,56 @@ void MiniDSP::ParseHIDData(USBHID *hid __attribute__ ((unused)), bool is_rpt_id | |||||
if(pFuncOnMutedChange != nullptr && mutedChanged) | ||||||
pFuncOnMutedChange(muted); | ||||||
} | ||||||
|
||||||
|
||||||
// Check if this is an input source update. | ||||||
if(buf[3] == 0xA9 || buf[3] == 0xD9){ | ||||||
// Parse data. | ||||||
// Response is of format [ length ] [ 0x05 0xFF 0xA9/0xD9 ] [ source ]. | ||||||
const auto newInputSource = buf[4]; | ||||||
|
||||||
// Ensure we only interpret valid inputs. | ||||||
if(newInputSource >= 0x00 && newInputSource <= 0x02){ | ||||||
const auto inputSourceChanged = newInputSource != (char) inputSource; | ||||||
|
||||||
// Update values. | ||||||
inputSource = (InputSource) newInputSource; | ||||||
|
||||||
// Call callbacks. | ||||||
if(pFuncOnInputSourceChange != nullptr && inputSourceChanged) | ||||||
pFuncOnInputSourceChange(inputSource); | ||||||
} | ||||||
} | ||||||
|
||||||
// Check if this is an Config update. | ||||||
if(buf[3] == 0xD8){ | ||||||
// Parse data. | ||||||
// Response is of format [ length ] [ 0x05 0xFF 0xD8 ] [ config ]. | ||||||
const auto newConfig = buf[4]; | ||||||
|
||||||
// Ensure we only interpret valid inputs. | ||||||
if(newConfig >= 0x00 && newConfig <= 0x03){ | ||||||
const auto configChanged = newConfig != (char) config; | ||||||
|
||||||
// Update values. | ||||||
config = (Config) newConfig; | ||||||
|
||||||
// Call callbacks. | ||||||
if(pFuncOnConfigChange != nullptr && configChanged) | ||||||
pFuncOnConfigChange(config); | ||||||
} | ||||||
} | ||||||
}; | ||||||
|
||||||
uint8_t MiniDSP::OnInitSuccessful() { | ||||||
// Verify we're actually connected to the MiniDSP 2x4HD. | ||||||
if(HIDUniversal::VID != MINIDSP_VID || HIDUniversal::PID != MINIDSP_PID) | ||||||
return 0; | ||||||
|
||||||
// Request current status so we can initialize the values. | ||||||
// Request current information so we can initialize the values. | ||||||
RequestStatus(); | ||||||
RequestInputSource(); | ||||||
RequestConfig(); | ||||||
|
||||||
if(pFuncOnInit != nullptr) | ||||||
pFuncOnInit(); | ||||||
|
@@ -109,3 +163,33 @@ void MiniDSP::RequestStatus() const { | |||||
|
||||||
SendCommand(RequestStatusOutputCommand, sizeof (RequestStatusOutputCommand)); | ||||||
} | ||||||
|
||||||
void MiniDSP::RequestInputSource() const { | ||||||
uint8_t RequestInputSourceCommand[] = {0x05, 0xFF, 0xD9, 0x01}; | ||||||
|
||||||
SendCommand(RequestInputSourceCommand, sizeof(RequestInputSourceCommand)); | ||||||
} | ||||||
|
||||||
void MiniDSP::RequestConfig() const { | ||||||
uint8_t RequestConfigCommand[] = {0x05, 0xFF, 0xD8, 0x01}; | ||||||
|
||||||
SendCommand(RequestConfigCommand, sizeof(RequestConfigCommand)); | ||||||
} | ||||||
|
||||||
void MiniDSP::setVolumeDB(float volumeDB) const { | ||||||
// Only accept values between 0dB and -127.5dB. | ||||||
// Don't do error handling. | ||||||
if(volume > 0 || volume < -127.5){ | ||||||
return; | ||||||
} | ||||||
|
||||||
uint8_t SetVolumeCommand[] = {0x42, (uint8_t)(-2*volumeDB)}; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
SendCommand(SetVolumeCommand, sizeof(SetVolumeCommand)); | ||||||
} | ||||||
|
||||||
void MiniDSP::setMuted(bool muted) const { | ||||||
uint8_t SetMutedommand[] = {0x17, muted ? (uint8_t)0x01 : (uint8_t)0x00}; | ||||||
|
||||||
SendCommand(SetMutedommand, sizeof(SetMutedommand)); | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing new line. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -39,6 +39,21 @@ | |||||
class MiniDSP : public HIDUniversal { | ||||||
public: | ||||||
|
||||||
enum class InputSource : uint8_t { | ||||||
Analog = 0x00, | ||||||
Toslink = 0x01, | ||||||
USB = 0x02, | ||||||
Unknown = 0x03 | ||||||
}; | ||||||
|
||||||
enum class Config : uint8_t { | ||||||
Config_1 = 0x00, | ||||||
Config_2 = 0x01, | ||||||
Config_3 = 0x02, | ||||||
Config_4 = 0x03, | ||||||
Unknown = 0x04 | ||||||
}; | ||||||
|
||||||
/** | ||||||
* Constructor for the MiniDSP class. | ||||||
* @param p Pointer to the USB class instance. | ||||||
|
@@ -83,6 +98,22 @@ class MiniDSP : public HIDUniversal { | |||||
pFuncOnMutedChange = funcOnMutedChange; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Used to call your own function when the input source has changed. | ||||||
* @param funcOnInputSourceChange Function to call. | ||||||
*/ | ||||||
void attachOnInputSourceChange(void (*funcOnInputSourceChange)(InputSource)) { | ||||||
pFuncOnInputSourceChange = funcOnInputSourceChange; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Used to call your own function when the config has changed. | ||||||
* @param funcOnConfigChange Function to call. | ||||||
*/ | ||||||
void attachOnConfigChange(void (*funcOnConfigChange)(Config)) { | ||||||
pFuncOnConfigChange = funcOnConfigChange; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Retrieve the current volume of the MiniDSP. | ||||||
* The volume is passed as an unsigned integer that represents twice the | ||||||
|
@@ -102,13 +133,42 @@ class MiniDSP : public HIDUniversal { | |||||
} | ||||||
|
||||||
/** | ||||||
* Retrieve the current muted status of the MiniDSP | ||||||
* Retrieve the current muted status of the MiniDSP. | ||||||
* @return `true` if the device is muted, `false` otherwise. | ||||||
*/ | ||||||
bool isMuted() const { | ||||||
return muted; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Retrieve the current input source of the MiniDSP. | ||||||
* @return Current input source: `Analog`, `Toslink` or `USB`. | ||||||
*/ | ||||||
InputSource getInputSource() const { | ||||||
return inputSource; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Set volume of the MiniDSP in dB. Values between 0 and -127.5 are | ||||||
* accepted. If any values outside if this range are passed, this | ||||||
* function does nothing. | ||||||
* | ||||||
* Calling this function will not trigger the volume change callback. | ||||||
* | ||||||
* @param volumeDB New volume to set. | ||||||
*/ | ||||||
void setVolumeDB(float volumeDB) const; | ||||||
|
||||||
|
||||||
/** | ||||||
* Mute or unmute the MiniDSP. | ||||||
* | ||||||
* Calling this function will not trigger the mute change callback. | ||||||
* | ||||||
* @param muted Muted status. | ||||||
*/ | ||||||
void setMuted(bool muted) const; | ||||||
|
||||||
protected: | ||||||
/** @name HIDUniversal implementation */ | ||||||
/** | ||||||
|
@@ -159,6 +219,18 @@ class MiniDSP : public HIDUniversal { | |||||
void | ||||||
RequestStatus() const; | ||||||
|
||||||
/** | ||||||
* Send the "Request input source" command to the MiniDSP. | ||||||
*/ | ||||||
void | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
RequestInputSource() const; | ||||||
|
||||||
/** | ||||||
* Send the "Request config" command to the MiniDSP. | ||||||
*/ | ||||||
void | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
RequestConfig() const; | ||||||
|
||||||
/** | ||||||
* Send the given MiniDSP command. This function will create a buffer | ||||||
* with the expected header and checksum and send it to the MiniDSP. | ||||||
|
@@ -179,6 +251,12 @@ class MiniDSP : public HIDUniversal { | |||||
// Pointer to function called when muted status changes. | ||||||
void (*pFuncOnMutedChange)(bool) = nullptr; | ||||||
|
||||||
// Pointer to function called when input source changes. | ||||||
void (*pFuncOnInputSourceChange)(InputSource) = nullptr; | ||||||
|
||||||
// Pointer to function called when config changes. | ||||||
void (*pFuncOnConfigChange)(Config) = nullptr; | ||||||
|
||||||
// ----------------------------------------------------------------------------- | ||||||
|
||||||
// MiniDSP state. Currently only volume and muted status are | ||||||
|
@@ -188,4 +266,6 @@ class MiniDSP : public HIDUniversal { | |||||
// -dB value. Example: 19 represents -9.5dB. | ||||||
uint8_t volume = 0; | ||||||
bool muted = false; | ||||||
InputSource inputSource = InputSource::Unknown; | ||||||
Config config = Config::Unknown; | ||||||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.