Files
2024-07-20 22:09:06 +08:00

258 lines
6.4 KiB
C++

/**
*/
#include "GD5800_Serial.h"
void GD5800_Serial::play()
{
this->sendCommand(0x01);
}
void GD5800_Serial::restart()
{
byte oldVolume = this->getVolume();
this->setVolume(0);
this->next();
this->pause();
this->setVolume(oldVolume);
this->prev();
}
void GD5800_Serial::pause()
{
this->sendCommand(0x02);
}
void GD5800_Serial::next()
{
this->sendCommand(0x03);
}
void GD5800_Serial::prev()
{
this->sendCommand(0x04);
}
void GD5800_Serial::fastReverse()
{
this->sendCommand(0x0B);
}
void GD5800_Serial::fastForward()
{
this->sendCommand(0x0A);
}
void GD5800_Serial::playFileByIndexNumber(unsigned int fileNumber)
{
this->sendCommand(0x41, (fileNumber>>8) & 0xFF, fileNumber & (byte)0xFF);
}
void GD5800_Serial::volumeUp()
{
this->sendCommand(0x05);
}
void GD5800_Serial::volumeDn()
{
this->sendCommand(0x06);
}
void GD5800_Serial::setVolume(byte volumeFrom0To30)
{
this->sendCommand(0x31, volumeFrom0To30);
}
void GD5800_Serial::setEqualizer(byte equalizerMode)
{
this->sendCommand(0x32, equalizerMode);
}
void GD5800_Serial::setLoopMode(byte loopMode)
{
this->sendCommand(0x33, loopMode);
}
byte GD5800_Serial::getStatus()
{
byte statTotal = 0;
byte stat = 0;
do
{
statTotal = 0;
for(byte x = 0; x < MP3_STATUS_CHECKS_IN_AGREEMENT; x++)
{
stat = this->sendCommandWithUnsignedIntResponse(0x42);
if(stat == 0) return 0; // STOP is fairly reliable
statTotal += stat;
}
} while (statTotal != 1 * MP3_STATUS_CHECKS_IN_AGREEMENT && statTotal != 2 * MP3_STATUS_CHECKS_IN_AGREEMENT);
return statTotal / MP3_STATUS_CHECKS_IN_AGREEMENT;
}
byte GD5800_Serial::getVolume() { return this->sendCommandWithUnsignedIntResponse(0x11); }
byte GD5800_Serial::getEqualizer() { return this->sendCommandWithUnsignedIntResponse(0x44); }
byte GD5800_Serial::getLoopMode() { return this->sendCommandWithUnsignedIntResponse(0x13); }
unsigned int GD5800_Serial::countFiles()
{
return this->sendCommandWithUnsignedIntResponse(0x16);
}
unsigned int GD5800_Serial::currentFileIndexNumber()
{
return this->sendCommandWithUnsignedIntResponse(0x1A);
}
// Used for the status commands, they mostly return an 8 to 16 bit integer
// and take no arguments
unsigned int GD5800_Serial::sendCommandWithUnsignedIntResponse(byte command)
{
char buffer[5];
this->sendCommand(command, 0, 0, buffer, sizeof(buffer));
return (unsigned int) strtoul(buffer, NULL, 16);
}
void GD5800_Serial::sendCommand(byte command)
{
this->sendCommand(command, 0, 0, 0, 0);
}
void GD5800_Serial::sendCommand(byte command, byte arg1)
{
this->sendCommand(command, arg1, 0, 0, 0);
}
void GD5800_Serial::sendCommand(byte command, byte arg1, byte arg2)
{
this->sendCommand(command, arg1, arg2, 0, 0);
}
void GD5800_Serial::sendCommand(byte command, byte arg1, byte arg2, char *responseBuffer, unsigned int bufferLength)
{
// Command structure
// [7E][number bytes following including command and terminator][command byte][?arg1][?arg2][EF]
// Most commands do not have arguments
byte args = 0;
// These ones do
switch(command)
{
case 0x41: args = 2; break;//指定曲目
case 0x31: args = 1; break;//指定音量
case 0x32: args = 1; break;//指定EQ
case 0x09: args = 1; break;//指定设备
case 0x33: args = 1; break;//循环播放
default :args=1;break;
}
#if MP3_DEBUG
char buf[4];
Serial.println();
Serial.print("7E ");
itoa(2+args, buf, 16); Serial.print(buf); Serial.print(" "); memset(buf, 0, sizeof(buf));
itoa(command, buf, 16); Serial.print(buf); Serial.print(" "); memset(buf, 0, sizeof(buf));
if(args>=1) itoa(arg1, buf, 16); Serial.print(buf); Serial.print(" "); memset(buf, 0, sizeof(buf));
if(args>=2) itoa(arg2, buf, 16); Serial.print(buf); Serial.print(" "); memset(buf, 0, sizeof(buf));
Serial.print("EF");
#endif
// The device appears to send some sort of status information (namely "STOP" when it stops playing)
// just discard this right before we send the command
while(this->waitUntilAvailable(10)) this->read();
this->write((byte)0x7E);
this->write(2+args);
this->write(command);
if(args>=1) this->write(arg1);
if(args==2) this->write(arg2);
this->write((byte)0xEF);
unsigned int i = 0;
char j = 0;
if(responseBuffer && bufferLength)
{
memset(responseBuffer, 0, bufferLength);
}
// Allow some time for the device to process what we did and
// respond, up to 1 second, but typically only a few ms.
this->waitUntilAvailable(1000);
#if MP3_DEBUG
Serial.print(" ==> [");
#endif
while(this->waitUntilAvailable(150))
{
j = (char)this->read();
#if MP3_DEBUG
Serial.print(j);
#endif
if(responseBuffer && (i<(bufferLength-1)))
{
responseBuffer[i++] = j;
}
}
#if MP3_DEBUG
Serial.print("]");
Serial.println();
#endif
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t GD5800_Serial::readBytesUntilAndIncluding(char terminator, char *buffer, size_t length, byte maxOneLineOnly)
{
if (length < 1) return 0;
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0) break;
*buffer++ = (char)c;
index++;
if(c == terminator) break;
if(maxOneLineOnly && ( c == '\n') ) break;
}
return index; // return number of characters, not including null terminator
}
// Waits until data becomes available, or a timeout occurs
int GD5800_Serial::waitUntilAvailable(unsigned long maxWaitTime)
{
unsigned long startTime;
int c = 0;
startTime = millis();
do {
c = this->available();
if (c) break;
} while(millis() - startTime < maxWaitTime);
return c;
}