UART MP3 Voice Module with 8MB Flash Memory / DFR0534

Dependents:   DFR0534_MP3_Test_os5 TYBLE16_MP3_Air

see /users/kenjiArai/notebook/mp3--voice-module-dfr0534/

Files at this revision

API Documentation at this revision

Comitter:
kenjiArai
Date:
Sun Dec 29 02:55:07 2019 +0000
Commit message:
1st working sample (need to update)

Changed in this revision

DRF0534_command.txt Show annotated file Show diff for this revision Revisions of this file
drf0534.cpp Show annotated file Show diff for this revision Revisions of this file
drf0534.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 466200f304c9 DRF0534_command.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRF0534_command.txt	Sun Dec 29 02:55:07 2019 +0000
@@ -0,0 +1,249 @@
+/*
+    Original information:
+    https://wiki.dfrobot.com/Voice_Module_SKU__DFR0534
+ */
+
+Three types
+    SIMPLE
+    PARAMETER
+    ANSWER
+
+---------- COMMREQ -------------------------------------------------------------
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check Playback Status(0x01)
+    Command: AA 01 00 AB
+    Return: AA 01 01 Playback status SM
+    Explanation: You can check the play status at any time.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Play(0x02)
+    Command: AA 02 00 AC
+    Return: None
+    Explanation: Play the current track from the beginning at any time.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Pause(0x03)
+    Command: AA 03 00 AD
+    Return: None
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Playstop(0x04)
+    Command: AA 04 00 AE
+    Return: None
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Prev Audio(0x05)
+    Command: AA 05 00 AF
+    Return: None
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Next Audio(0x06)
+    Command: AA 06 00 B0
+    Return: None
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Specified Audio:(0x07)
+    Command: AA 07 02 Upper-Byte Lower-Byte SM
+    Return: None
+    E.g. AA 07 02 00 08 BB
+        will specify to play the eighth audio in the current drive,
+        and the audio number is from 1 to 65535.
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Play the audio in specified drive of specified path.(0x08)
+    Command: AA 08 length drive path SM
+    Return: None
+    Explanation: length= drive length + path length=1+ path length
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the current online drive.(0x09)
+    Command: AA 09 00 B3
+    Return: AA 09 01 Drive SM
+    Explanation: The online drive is differentiated
+        by bitwise usb:bit (0) sd:bit (1) flash:bit (2)
+        It can check the current online drive.
+        It is recommended that you check the current online drive
+         before switching the drive.
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the current drive(0x0A) to play
+    Command: AA 0A 00 84
+    Return: AA 0A 01 Drive SM
+--------------------------------------------------------------------------------
+<<PARAMETER>>    
+Switch to the specified drive(0x0B)
+    Command: AA 0B 01 drive SM
+    Return: None
+    Explanation: It is drive switching command. If the current drive is online,
+        you can switch it to the corresponding drive and wait to play.
+        After switching, the module plays the first audio of this drive.
+        It is recommended to check whether the drive is online before you switch.
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the total audios(0x0C)
+    Command: AA 0C 00 B6
+    Return: AA 0C 02 Upper-byte Lower-byte SM
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the current audio(0x0D)
+    Command: AA 0D 00 B7
+    Return: AA 0D 02 upper-byte lower-byte SM
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+The Directory of the previous folder(0x0E)
+    Command: AA 0E 00 B8
+    Return: None
+    Explanation: The first audio in the folder will be played after switching.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+The directory of the next folder(0x0F)
+    Command: AA 0F 00 B9
+    Return: None
+    Explanation: The first audio in the folder will be played after switching.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+End to play(0x10)
+    Command: AA 10 00 BA
+    Explanation: This command can end the current operations in advance.
+        If the command end a cut-in,
+        it will end in advance and return to the original status.
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the first audio in the folder(0x11)
+    Command: AA 11 00 BB
+    Return: AA 11 02 Upper-byte Lower-byte SM
+    Explanation: It is the sequence number of the first audio.
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Check the total numbers of audio in all folders(0x12)
+    Command: AA 12 00 BC
+    Return: AA 12 02 Upper-byte Lower-byte SM
+    Explanation:
+        This number does not contain the number of files in subdirectories.
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Volume settings(0x13)
+    Command: AA 13 01 VOL SM
+    Return: None
+    Explanation: AA 13 01 14 D2 Set volume to level 20.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+Increase the volume(0x14)
+    Command: AA 14 00 BE
+    Return: None
+--------------------------------------------------------------------------------
+<<SIMPLE>>   
+Reduce the volume(0x15)
+    Command: AA 15 00 BF
+    Return: None
+--------------------------------------------------------------------------------
+<<PARAMETER>>    
+Cut-in a specific audio(0x16)
+    Command: AA 16 03 drive Upper-byte Lower-byte SM
+    Return: None
+    E.g. AA 16 03 00 00 09 CC Cut-in the 9th audio in the USB flash drive.
+    Explanation:
+        Continue to play the original audio when cut-in audio is played.
+--------------------------------------------------------------------------------
+<<PARAMETER>> 
+Cut-in the audio on the specified path(0x17)
+    Command: AA 17 Length Drive Path SM
+    Return: None
+    Explanation: length= drive length + path length=1+ path length
+--------------------------------------------------------------------------------
+<<PARAMETER>> 
+Set the loop mode(0x18)
+    Command: AA 18 01 loop mode
+    Return: None
+    E.g. Set to end single play AA 18 01 03 C6
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Set the number of loop times(0x19)
+    Command: AA 19 02 Upper-byte Lower-byte SM
+    Return: None
+    Explain: This command is only valid when the loop mode is Full Loop,
+         Single Loop, Catalog Loop.
+    E.g. AA 19 02 00 06 CB Repeat 6 times.
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+EQ Setting (0x1A)
+    Command: AA 1A 01 EQ SM
+    Return: None
+    E.g. AA 1A 01 02 C7 Set EQ to ROCK
+--------------------------------------------------------------------------------
+<<PARAMETER>>  
+Combination Play(0x1B)
+    Command: AA 1B Upper-byte of the audio 1,
+         Lower-byte of the audio 1...Upper-byte of the audio n,
+         Lower byte of the audio n.
+    Return: None
+    E.g. AA1B04303130328C,
+        audios with file names of 01 and 02 are grouped together to play
+    Explanation: The combination of file names is very convenient, 
+        more accurate than combined file numbers,
+        and is not restricted by the copy order limitation.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+End Combination Play(0x1C)
+    Command: AA 1C 00 C6
+    Return: None
+    Explanation: End combination playback,
+         and return the play state before the combination.
+--------------------------------------------------------------------------------
+<<PARAMETER>>  
+Set channels(0x1D)
+    Command: AA 1D 01 channels SM
+    Return: None
+--------------------------------------------------------------------------------
+<<ANSWER>>    
+Check the short-file name(0x1E)
+    Command: AA 1E 00 C8
+    Return: AA 1E The length of short-file name Short-file name SM
+--------------------------------------------------------------------------------
+<<PARAMETER>>  
+Select audio but do not play(0x1F)
+    Command: AA 1F 02 Upper-byte Lower-byte SM
+    Return: None
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Control of Repetition(0x20)
+    Command: AA 20 04 beginning-minute beginning-second
+         ending-minute ending-second SM
+    Return: None
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+End repetition(0x21)
+    Command: AA 21 00 CB
+    Return: None
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Specify the time to rewind(0x22)
+    Command: AA 22 02 Upper-byte Lower-byte SM
+    Return: None
+    Explanation: The unit is seconds
+--------------------------------------------------------------------------------
+<<PARAMETER>>
+Specify the time to wind(0x23)
+    Command: AA 23 02 Upper-byte Lower-byte SM
+    Return: None
+    Explanation: The unit is seconds
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Get the total time of the current audio(0x24)
+    Command: AA 24 00 CE
+    Return: AA 24 03 hour minute second SM
+--------------------------------------------------------------------------------
+<<ANSWER>>
+Start the playback time sending(0x25)
+    Command: AA 25 00 CF
+    Return: AA 25 03 hour minute second SM
+    Explanation: Start to send playing time,
+         Return automatically when the time is updated.
+--------------------------------------------------------------------------------
+<<SIMPLE>>
+End to send the playing time(0x26)
+    Command: AA 26 00 D0
+    Return: None
+    Explanation: End the playback time sending.
+--------------------------------------------------------------------------------
\ No newline at end of file
diff -r 000000000000 -r 466200f304c9 drf0534.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drf0534.cpp	Sun Dec 29 02:55:07 2019 +0000
@@ -0,0 +1,333 @@
+/*
+ * Mbed Library program
+ *  UART MP3 Voice Module with 8MB Flash Memory / DFR0534
+ *
+ * Copyright (c) 2019 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    December  28th, 2019
+ *      Revised:    December  29th, 2019
+ */
+
+/*
+    Reference information:
+        http://akizukidenshi.com/catalog/g/gM-13708/
+        https://wiki.dfrobot.com/Voice_Module_SKU__DFR0534
+ */
+
+#include "drf0534.h"
+    
+#if MBED_MAJOR_VERSION == 2
+#define WAIT_MS(x)       wait_ms(x)
+#elif  MBED_MAJOR_VERSION == 5
+#define WAIT_MS(x)       ThisThread::sleep_for(x)
+#else
+#error "Running on Unknown OS"
+#endif
+
+//#define DEBUG
+
+DFR0534::DFR0534(PinName tx, PinName rx, PinName busy)
+    :_mp3(tx, rx), _bsy(busy)
+{
+    _mp3.baud(9600);
+    _mp3.attach(callback(this,&DFR0534::_rx_handler), Serial::RxIrq);
+    volume_setting(0);
+}
+
+void DFR0534::play_one(uint16_t track_num)
+{
+    _wait_busy();
+    _sum = 0xaa;
+    _mp3.putc(_sum);
+    WAIT_MS(2);
+    _sum += 0x07;
+    _mp3.putc(0x07);
+    WAIT_MS(2);
+    _sum += 0x02;
+    _mp3.putc(0x02);
+    WAIT_MS(2);
+    uint8_t dt = track_num >> 8;
+    _sum += dt;
+    _mp3.putc(dt);
+    WAIT_MS(2);
+    dt = (uint8_t)track_num;
+    _sum += dt;
+    _mp3.putc(dt);
+    WAIT_MS(2);
+    _mp3.putc(_sum);
+}
+
+void DFR0534::volume_setting(uint8_t vol)
+{
+    _sum = 0xaa;
+    _mp3.putc(_sum);
+    WAIT_MS(2);
+    _sum += 0x13;
+    _mp3.putc(0x13);
+    WAIT_MS(2);
+    _sum += 0x01;
+    _mp3.putc(0x01);
+    WAIT_MS(2);
+    uint8_t dt = vol;
+    if (dt > VOL_MAX) {
+        dt = VOL_MAX;
+    }
+    _sum += dt;
+    _mp3.putc(dt);
+    WAIT_MS(2);
+    _mp3.putc(_sum);
+}
+
+void DFR0534::volume_increase()
+{
+    _command(0x14);
+}
+
+void DFR0534::volume_decrease()
+{
+    _command(0x15);
+}
+
+void DFR0534::command(enum simple_commands cmds)
+{
+    _command(cmds);
+}
+
+uint16_t DFR0534::total_num_of_audio()
+{
+    uint16_t dt = 0;
+    char c;
+
+    _rxbuf.reset();     // clear buffer
+    _command(0x0c);
+    WAIT_MS(50);
+    for (uint32_t i = 0; i < 6; i++) {
+        while(_rxbuf.empty() == true) {;}
+        _rxbuf.pop(c);
+        _buf[i] = c;
+    }
+#if defined(DEBUG)
+    for (uint32_t i = 0; i < 6; i++) {
+        printf("0x%02x, ",_buf[i]);
+    }
+    printf("\r\n");
+#endif
+    if (_buf[0] == 0xaa) {
+        _sum = 0xaa;
+        _sum += _buf[1];
+        _sum += _buf[2];
+        dt = _buf[3] << 8;
+        _sum += _buf[3];
+        dt += _buf[4];
+        _sum += _buf[4];
+        if (_sum == _buf[5]) {
+            return dt;  // success
+        }
+    }
+    return 0;   // error
+}
+
+uint16_t DFR0534::current_num_of_audio()
+{
+    uint16_t dt = 0;
+    char c;
+
+    _rxbuf.reset();     // clear buffer
+    _command(0x0d);
+    WAIT_MS(50);
+    for (uint32_t i = 0; i < 6; i++) {
+        while(_rxbuf.empty() == true) {;}
+        _rxbuf.pop(c);
+        _buf[i] = c;
+    }
+#if defined(DEBUG)
+    for (uint32_t i = 0; i < 6; i++) {
+        printf("0x%02x, ",_buf[i]);
+    }
+    printf("\r\n");
+#endif
+    if (_buf[0] == 0xaa) {
+        _sum = 0xaa;
+        _sum += _buf[1];
+        _sum += _buf[2];
+        dt = _buf[3] << 8;
+        _sum += _buf[3];
+        dt += _buf[4];
+        _sum += _buf[4];
+        if (_sum == _buf[5]) {
+            return dt;  // success
+        }
+    }
+    return 0;   // error
+}
+
+void DFR0534::get_file_name(char *buf)
+{
+    uint16_t dt = 0;
+    char c, num;
+    char *p;
+
+    _rxbuf.reset();     // clear buffer
+    _command(0x1e);
+    WAIT_MS(50);
+    for (uint32_t i = 0; i < 3; i++) {
+        while(_rxbuf.empty() == true) {;}
+        _rxbuf.pop(c);
+        _buf[i] = c;
+    }
+#if defined(DEBUG)
+    for (uint32_t i = 0; i < 3; i++) {
+        printf("H: 0x%02x, ",_buf[i]);
+    }
+    printf("\r\n");
+#endif
+    if (_buf[0] == 0xaa) {
+        _sum = 0xaa;
+        _sum += _buf[1];
+        _sum += _buf[2];
+    } else {    // error
+        *buf = 0;
+        return;
+    }
+    num = _buf[2] + 1;
+#if defined(DEBUG)
+    printf("number = %d\r\n", num);
+#endif
+    for (uint32_t i = 0; i < num; i++) {
+        while(_rxbuf.empty() == true) {;}
+        _rxbuf.pop(c);
+        _buf[i] = c;
+    }
+#if defined(DEBUG)
+    for (uint32_t i = 0; i < num; i++) {
+        printf("T: 0x%02x, ",_buf[i]);
+    }
+#endif
+    num -= 1;
+    for (uint32_t i = 0; i < num; i++) {
+        _sum += _buf[i];
+    }
+    if (_sum == _buf[num]) {
+#if defined(DEBUG)
+        printf("Sum is okay! sum = %d, buf = %d\r\n", _sum, _buf[num]);
+#endif
+        p = buf;
+        for (uint32_t i = 0; i < num; i++) {
+            *p++ = _buf[i];
+        }
+        *p = 0;
+#if defined(DEBUG)
+        printf("%s\r\n", buf);
+    } else {
+        printf("Sum is NG! sum = %d, buf = %d\r\n", _sum, _buf[num]);
+    }
+#else
+    }
+#endif
+}
+
+uint32_t DFR0534::get_play_time()
+{
+    _rxbuf.reset();     // clear buffer
+    _command(0x24);
+    return get_time();
+}
+
+uint32_t DFR0534::get_play_back_time()
+{
+    _rxbuf.reset();     // clear buffer
+    _command(0x25);
+    return get_time();
+}
+
+uint32_t DFR0534::get_time()
+{
+    uint16_t dt = 0;
+    char c, h, m, s;
+
+    WAIT_MS(50);
+    for (uint32_t i = 0; i < 7; i++) {
+        while(_rxbuf.empty() == true) {;}
+        _rxbuf.pop(c);
+        _buf[i] = c;
+    }
+#if defined(DEBUG)
+    for (uint32_t i = 0; i < 7; i++) {
+        printf("0x%02x, ",_buf[i]);
+    }
+    printf("\r\n");
+#endif
+    if (_buf[0] == 0xaa) {
+        _sum = 0xaa;
+        _sum += _buf[1];
+        _sum += _buf[2];
+        h = _buf[3];
+        _sum += _buf[3];
+        m = _buf[4];
+        _sum += _buf[4];
+        s = _buf[5];
+        _sum += _buf[5];
+        if (_sum == _buf[6]) {
+#if defined(DEBUG)
+            printf("Sum is okay! sum = %d, buf = %d\r\n", _sum, _buf[6]);
+#endif
+            // success
+            return ((uint32_t)h * 3600 + (uint32_t)m * 60 + (uint32_t)s);
+#if defined(DEBUG)
+        } else {
+            printf("Sum is NG! sum = %d, buf = %d\r\n", _sum, _buf[6]);
+        }
+#else
+        }
+#endif
+    }
+    return 0;   // error
+}
+
+// Interrupt Hander
+void DFR0534::_rx_handler(void)
+{
+    while(_mp3.readable()) {
+        _rxbuf.push(_mp3.getc());
+    }
+}
+
+void DFR0534::_command(uint8_t cmd_no)
+{
+    _sum = 0xaa;
+    _mp3.putc(_sum);
+    _sum += cmd_no;
+    WAIT_MS(2);
+    _mp3.putc(cmd_no);
+    WAIT_MS(2);
+    _mp3.putc(0x00);
+    WAIT_MS(2);
+    _mp3.putc(_sum);
+}
+
+void DFR0534::_command_w_para(uint8_t cmd_no, uint8_t *parameter, uint8_t len)
+{
+    _sum = 0xaa;
+    _mp3.putc(_sum);
+    _sum += cmd_no;
+    WAIT_MS(2);
+    _mp3.putc(cmd_no);
+    WAIT_MS(2);
+    _mp3.putc(0x00);
+    WAIT_MS(2);
+    for (uint32_t i = 0; i < len; i++) {
+        uint8_t dt = *parameter++;
+        _sum += dt;
+        _mp3.putc(dt);
+        WAIT_MS(2);
+    }
+    _mp3.putc(_sum);
+}
+
+void DFR0534::_wait_busy(void)
+{
+    while (_bsy.read() == 1) {
+        WAIT_MS(20);
+    }
+}
diff -r 000000000000 -r 466200f304c9 drf0534.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drf0534.h	Sun Dec 29 02:55:07 2019 +0000
@@ -0,0 +1,142 @@
+/*
+ * Mbed Library program
+ *  UART MP3 Voice Module with 8MB Flash Memory / DFR0534
+ *
+ * Copyright (c) 2019 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    December  28th, 2019
+ *      Revised:    December  29th, 2019
+ */
+
+/*
+    Reference information:
+        http://akizukidenshi.com/catalog/g/gM-13708/
+        https://wiki.dfrobot.com/Voice_Module_SKU__DFR0534
+ */
+
+#ifndef DFR0534_H
+#define DFR0534_H
+
+#include "mbed.h"
+
+#define VOL_MIN     0
+#define VOL_MAX     30
+
+enum simple_commands{
+    Play = 0x02,
+    Pause,
+    Playstop,
+    Prev_Audio,
+    Next_Audio,
+    The_Directory_of_the_previous_folder = 0x0e,
+    The_directory_of_the_next_folder,
+    End_to_play,
+    Increase_the_volume = 0x14,
+    Reduce_the_volume,
+    End_Combination_Play = 0x1c,
+    End_repetition = 0x21,
+    End_to_send_the_playing_time = 0x26
+};
+
+/** UART MP3 Voice Module with 8MB Flash Memory / DFR0534
+ * @code
+ * #include    "mbed.h"
+ * #include    "drf0534.h"
+ *
+ * DFR0534 mp3(PA_0, PA_1, PA_4);  // tx, rx, busy
+ *
+ * int main() {
+ *     mp3.volume_setting(VOL_MAX / 2);
+ *     uint32_t num = mp3.total_num_of_audio();
+ *     while(true) {
+ *         for (uint32_t i = 1; i < num + 1; i++) {
+ *             mp3.play_one(i);
+ *             mp3.get_file_name(name_buf);
+ *             printf("File name = %s\r\n", name_buf);
+ *         }
+ *     }
+ * }
+ * @endcode
+ */
+ 
+class DFR0534
+{
+public:
+    /** Create the DFR0534 object
+     *  @param PinName communication line TX & RX & Busy signal input
+     */
+    DFR0534(PinName tx, PinName rx, PinName busy);
+
+    /** Play specific truck 
+     * @param truck number
+     */
+    void play_one(uint16_t track_num);
+
+    /** set volume
+     * @param volume value(VOL_MIN to VOL_MAX, 0 to 30)
+     */
+    void volume_setting(uint8_t vol);
+
+    /** increase volume
+     * @param none
+     */
+    void volume_increase();
+
+    /** decrease volume
+     * @param none
+     */
+    void volume_decrease();
+
+    /** direct command (simple type -> No parameter & no return value)
+     * @param command
+     */
+    void command(enum simple_commands cmds);
+
+    /** Check the total number of audio track
+     * @param none
+     * @return total number of audio
+     */
+    uint16_t total_num_of_audio();
+
+    /** Check the current audio track number
+     * @param none
+     * @return number
+     */
+    uint16_t current_num_of_audio();
+
+    /** get file name
+     * @param buffer pointer (buffer size > 32)
+     * @return name into buffer
+     */
+    void get_file_name(char *buf);
+
+    /** get play time
+     * @param none
+     * @return time[seconds]
+     */
+    uint32_t get_play_time();
+
+    /** get play back time
+     * @param none
+     * @return time[seconds]
+     */
+    uint32_t get_play_back_time();
+
+private:
+    RawSerial  _mp3;
+    DigitalIn  _bsy;
+
+    void _rx_handler(void);
+    void _command(uint8_t cmd_no);
+    void _command_w_para(uint8_t cmd_no, uint8_t *parameter, uint8_t len);
+    void _wait_busy(void);
+    uint32_t get_time(void);
+
+    CircularBuffer<char, 32> _rxbuf; // small ring buffer
+    uint8_t _sum;
+    char _buf[32];
+
+};
+
+#endif // DFR0534_H
\ No newline at end of file