├── Audio_Shield.zip ├── README.txt ├── examples ├── AudioPlayRecord │ └── AudioPlayRecord.ino ├── ShieldTest │ └── ShieldTest.ino └── DTMFDemo │ └── DTMFDemo.ino ├── WT2000.h └── WT2000.cpp /Audio_Shield.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SandboxElectronics/Audio_Shield/master/Audio_Shield.zip -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Arduino Library for Sandbox Electronics MP3 Audio Shield [SLD-000022] 2 | ===================================================================== 3 | 4 | This shield is available at http://sandboxelectronics.com/?product=mp3-audio-shield-with-dtmf-support 5 | 6 | Installation Instruction (For Arduino IDE version 1.0.5 and above): 7 | 8 | 1. Download the library as an Arduino IDE compatible zip file at 9 | https://codeload.github.com/SandboxElectronics/UART_Bridge/zip/master (Do not unzip it. leave it as is) 10 | 11 | 2. In the Arduino IDE, select Sketch -> Import Library -> Add Library 12 | 13 | 3. Navigate to the zip file that was just downloaded - Audio_Shield.zip, and Click Open. 14 | 15 | 4. Return to the Sketch -> Import Library menu. You should now see the library at the bottom of the drop-down menu. It is ready to be used in your sketch. 16 | 17 | 5. As this library has a dependency on another Sandbox Electronics Library - UART_Bridge. The same steps 1-4 should be used to install that library if it is not already installed. The library can be downloaded at https://github.com/SandboxElectronics/UART_Bridge/blob/master/UART_Bridge.zip?raw=true. 18 | 19 | The installed library should be under: 20 | - My Documents\Arduino\libraries\ (on Windows) 21 | - Documents/Arduino/libraries/ (on Mac or Linux) 22 | 23 | Note: the above instruction is for automatic installation of 3rd party libraries that is supported starting at Arduino IDE 1.0.5. For users running earlier versions, manual installation is required. For manual installation instruction, please visit http://arduino.cc/en/Guide/Libraries. Please remember to close all opened Arduino IDE windows and restart the Arduino IDE if manual installation was used. Please make sure the new library appears in the Sketch -> Import Library menu item of the software. 24 | -------------------------------------------------------------------------------- /examples/AudioPlayRecord/AudioPlayRecord.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | This is a demo code for Sandbox Electronics' WT2000 audio play/record shield. 4 | You can get one of those products on 5 | http://sandboxelectronics.com 6 | 7 | This code demonstrate that 8 | You can get a sim900 shield on 9 | http://sandboxelectronics.com 10 | 11 | This code demonstrates the playing and recording ability of the shield. 12 | Version: 13 | V0.1 14 | 15 | Release Date: 16 | 2014-02-21 17 | 18 | Author: 19 | Tiequan Shao info@sandboxelectronics.com 20 | 21 | Lisence: 22 | CC BY-NC-SA 3.0 23 | 24 | Please keep the above information when you use this code in your project. 25 | */ 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_BA); 36 | WT2000 myaudioshield = WT2000(&i2cuart); 37 | 38 | 39 | 40 | #define PIN_AUDIO_SWITCH (5) 41 | 42 | 43 | 44 | void setup() 45 | { 46 | Serial.begin(9600); 47 | 48 | // UART to Serial Bridge Initialization 49 | i2cuart.begin(9600); //baudrate setting 50 | i2cuart.pinMode(PIN_AUDIO_SWITCH,OUTPUT); //Audio channel selection output. 0: Earphone R - WT2000 DACR , 51 | // Earphone L -WT2000 DACL 52 | // Microphone - WT2000 MIC in 53 | // WT2000 DACR - SIM900 Audio Input 54 | // 1: Earphone R - SIM900 Audio Ouput 55 | // Earphone L - SIM900 Audio Ouput 56 | // Microphone - SIM900 Audio Input 57 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,0); //Set audio channel selection to 0, so sound played by WT2000 will be fed to earphone 58 | myaudioshield.mode(WT2000_MODE_ALL_CYCLE); //Set play mode to single shot mode 59 | myaudioshield.channel(WT2000_CHANNEL_MIC); //Set MIC input as the recording channel; 60 | 61 | Serial.println("Sandbox Electronics' Audio/DTMF Shield Demo Code"); 62 | Serial.println("================================================"); 63 | Serial.println("PLAY ------------------------------ Play a track"); 64 | Serial.println("STOP ------------------------------ Stop playing"); 65 | Serial.println("PREVIOUS ------------------------- Play previous"); 66 | Serial.println("RECORD ---------------------------- Record track"); 67 | Serial.println("FINISH ------------------------ Finish recording"); 68 | Serial.println("================================================"); 69 | 70 | if (i2cuart.ping() !=1) { 71 | Serial.println("Error1: Can not connnect to SC16IS750"); 72 | Serial.println("Please check the connectivity of SDA-A4, and SCL-A5 if you are a Uno Board."); 73 | Serial.println("You may need to connect A4 to SDA and A5 to SCL with wires if your board does not have SCL and SDA broke out."); 74 | while(1); 75 | } else { 76 | // Serial.println("Connected to SC16IS750"); 77 | 78 | } 79 | 80 | 81 | }; 82 | 83 | void loop() 84 | { 85 | 86 | SerialReadCommand(); 87 | 88 | } 89 | 90 | 91 | void SerialReadCommand() 92 | { 93 | 94 | char command_buffer[100]; 95 | uint8_t index = 0; 96 | 97 | while((Serial.available() > 0) && (index<99)) { 98 | command_buffer[index++] = Serial.read(); 99 | delay(50); 100 | } 101 | 102 | command_buffer[index++] = 0; 103 | 104 | if (!strcmp(command_buffer,"PLAY")) { 105 | Serial.println("Playing tracks..."); 106 | myaudioshield.play("MENU","TRACK"); 107 | } 108 | 109 | if (!strcmp(command_buffer,"NEXT")) { 110 | Serial.println("Playing next track..."); 111 | myaudioshield.next(); 112 | } 113 | 114 | if (!strcmp(command_buffer,"STOP")) { 115 | Serial.println("Stop playing..."); 116 | myaudioshield.stop(); 117 | } 118 | 119 | if (!strcmp(command_buffer,"PREVIOUS")) { 120 | Serial.println("Playing previous track..."); 121 | myaudioshield.previous(); 122 | } 123 | 124 | if (!strcmp(command_buffer,"RECORD")) { 125 | Serial.println("Recording..."); 126 | myaudioshield.remove(0x0001,"REC00"); 127 | myaudioshield.record(0x0001,"REC00"); 128 | 129 | } 130 | 131 | if (!strcmp(command_buffer,"FINISH")) { 132 | Serial.println("Finish recording..."); 133 | myaudioshield.finish(); 134 | 135 | } 136 | 137 | command_buffer[0] = 0; 138 | 139 | 140 | 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /examples/ShieldTest/ShieldTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | This is a demo code to test Sandbox Electronics' WT2000 audio play/record shield. 4 | You can get one of those products on 5 | http://sandboxelectronics.com 6 | 7 | 8 | Please check your SDA and SCL wiring before you run this sketch. 9 | Please confirm that you have connected the lower pink and the lower lime connector with the wire provided with the shield. 10 | Version: 11 | V0.1 12 | 13 | Release Date: 14 | 2014-04-06 15 | 16 | Author: 17 | Tiequan Shao info@sandboxelectronics.com 18 | 19 | Please keep the above information when you use this code in your project. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | 30 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_BA); 31 | WT2000 myaudioshield = WT2000(&i2cuart); 32 | 33 | 34 | #define PIN_Q1 (0) 35 | #define PIN_Q2 (1) 36 | #define PIN_Q3 (2) 37 | #define PIN_Q4 (3) 38 | #define PIN_STD (4) 39 | #define PIN_AUDIO_SWITCH (5) 40 | 41 | 42 | #define DTMF_CONTEXT_IDLE (0) 43 | #define DTMF_CONTEXT_MAIN (1) 44 | #define DTMF_CONTEXT_DECODING_CHECK (2) 45 | #define DTMF_CONTEXT_RECORDING (3) 46 | #define DTMF_CONTEXT_PLAY_BACK (4) 47 | #define DTMF_CONTEXT_REPRESENTATIVE (5) 48 | 49 | #define DTMF_KEY_0 (10) 50 | #define DTMF_KEY_1 (1) 51 | #define DTMF_KEY_2 (2) 52 | #define DTMF_KEY_3 (3) 53 | #define DTMF_KEY_4 (4) 54 | #define DTMF_KEY_5 (5) 55 | #define DTMF_KEY_6 (6) 56 | #define DTMF_KEY_7 (7) 57 | #define DTMF_KEY_8 (8) 58 | #define DTMF_KEY_9 (9) 59 | #define DTMF_KEY_ASTERISK (11) 60 | #define DTMF_KEY_HASH (12) 61 | #define DTMF_KEY_A (13) 62 | #define DTMF_KEY_B (14) 63 | #define DTMF_KEY_C (15) 64 | #define DTMF_KEY_D (0) 65 | #define DTMF_KEY_NULL (16) 66 | 67 | 68 | void setup() 69 | { 70 | Serial.begin(9600); 71 | 72 | // UART to Serial Bridge Initialization 73 | i2cuart.begin(9600); //baudrate setting 74 | 75 | i2cuart.pinMode(PIN_AUDIO_SWITCH,OUTPUT); //Audio channel selection output. 0: Earphone R - WT2000 DACR , 76 | // Earphone L -WT2000 DACL 77 | // Microphone - WT2000 MIC in 78 | // WT2000 DACR - SIM900 Audio Input 79 | // 1: Earphone R - SIM900 Audio Ouput 80 | // Earphone L - SIM900 Audio Ouput 81 | // Microphone - SIM900 Audio Input 82 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,0); //Set audio channel selection to 0, so sound played by WT2000 will be fed to earphone 83 | i2cuart.ModemPin(1); //Set GPIO4-GPIO7 as GPIO pins 84 | i2cuart.InterruptControl(0); // 85 | i2cuart.SetPinInterrupt(0x10); //Set Pin change Interrupt; GPIO0-GPIO3 pin change interrupt enabled; 86 | i2cuart.GPIOLatch(1); 87 | 88 | 89 | myaudioshield.mode(WT2000_MODE_SINGLE); //Set play mode to single shot mode 90 | 91 | }; 92 | 93 | void loop() 94 | { 95 | 96 | SerialReadCommand(); 97 | 98 | } 99 | 100 | 101 | void SerialReadCommand() 102 | { 103 | 104 | char command_buffer[100]; 105 | uint8_t index = 0; 106 | 107 | command_buffer[0] = 0; 108 | while((Serial.available() > 0) && (index<99)) { 109 | command_buffer[index++] = Serial.read(); 110 | delay(50); 111 | } 112 | 113 | command_buffer[index++] = 0; 114 | 115 | if (!strcmp(command_buffer,"TEST")) { 116 | 117 | 118 | if (i2cuart.ping() !=1) { 119 | Serial.println("Error1: Can not connnect to SC16IS750"); 120 | Serial.println("Please check the connectivity of SDA-A4, and SCL-A5 if you are using a Uno Board."); 121 | Serial.println("You may need to connect A4 to SDA and A5 to SCL with wires if your board does not have SCL and SDA broke out."); 122 | return; 123 | //while(1); 124 | } else { 125 | // Serial.println("Connected to SC16IS750"); 126 | 127 | } 128 | 129 | if ( myaudioshield.lookup("1","TONES") != 0) { 130 | Serial.println("Error3: Card read failed!"); 131 | } 132 | 133 | if ( myaudioshield.play("1","TONES") != 0) { 134 | Serial.println("Error4: Can not play TONE 1"); 135 | } 136 | delay(1200); 137 | if (DTMFGetKey() != DTMF_KEY_1) { 138 | Serial.println("Error2: DTMF decoding error!"); 139 | Serial.println("Failed to decode 1"); 140 | Serial.println("Please check the connectivity of the lower pink and lower lime connector"); 141 | return; 142 | 143 | } 144 | 145 | if ( myaudioshield.play("2","TONES") != 0) { 146 | Serial.println("Error4: Can not play TONE 2"); 147 | } 148 | delay(1200); 149 | if (DTMFGetKey() != DTMF_KEY_2) { 150 | Serial.println("Error2: DTMF decoding error!"); 151 | Serial.println("Failed to decode 2"); 152 | Serial.println("Please check the connectivity of the lower pink and lower lime connector"); 153 | return; 154 | 155 | } 156 | 157 | if (myaudioshield.play("4","TONES") != 0) { 158 | Serial.println("Error4: Can not play TONE 4"); 159 | } 160 | delay(1200); 161 | if (DTMFGetKey() != DTMF_KEY_4) { 162 | Serial.println("Error2: DTMF decoding error!"); 163 | Serial.println("Failed to decode 4"); 164 | Serial.println("Please check the connectivity of the lower pink and lower lime connector"); 165 | return; 166 | 167 | } 168 | 169 | if (myaudioshield.play("8","TONES") != 0){ 170 | Serial.println("Error4: Can not play TONE 8"); 171 | } 172 | delay(1200); 173 | if (DTMFGetKey() != DTMF_KEY_8) { 174 | Serial.println("Error2: DTMF decoding error!"); 175 | Serial.println("Failed to decode 8"); 176 | Serial.println("Please check the connectivity of the lower pink and lower lime connector"); 177 | return; 178 | 179 | } 180 | 181 | if (myaudioshield.play("D","TONES") != 0){ 182 | Serial.println("Error4: Can not play TONE D"); 183 | } 184 | delay(1200); 185 | if (DTMFGetKey() != DTMF_KEY_D) { 186 | Serial.println("Error2: DTMF decoding error!"); 187 | Serial.println("Failed to decode D"); 188 | Serial.println("Please check the connectivity of the lower pink and lower lime connector"); 189 | return; 190 | 191 | } 192 | 193 | Serial.println("The shield is OK"); 194 | 195 | } 196 | 197 | command_buffer[0] = 0; 198 | 199 | } 200 | 201 | 202 | 203 | 204 | 205 | uint8_t DTMFGetKey(void) 206 | { 207 | uint8_t key_value; 208 | uint8_t irq_id; 209 | irq_id = i2cuart.InterruptPendingTest(); 210 | if ( (irq_id&0x01) != 0 ) { //no valid data 211 | return DTMF_KEY_NULL; 212 | } else { 213 | key_value = i2cuart.GPIOGetPortState(); 214 | key_value &= 0x0F; 215 | return key_value; 216 | } 217 | 218 | 219 | } 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /WT2000.h: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | This is a example code for Sandbox Electronics' WT2000 audio play/recording module. 4 | You can get one of those products on 5 | http://sandboxelectronics.com 6 | 7 | Version: 8 | V0.1 9 | 10 | Release Date: 11 | 2014-02-16 12 | 13 | Author: 14 | Tiequan Shao info@sandboxelectronics.com 15 | 16 | Lisence: 17 | CC BY-NC-SA 3.0 18 | 19 | Please keep the above information when you use this code in your project. 20 | */ 21 | 22 | 23 | 24 | 25 | #ifndef _WT2000_H_ 26 | #define _WT2000_H_ 27 | 28 | #if ARDUINO >= 100 29 | #include "Arduino.h" 30 | #else 31 | #include "WProgram.h" 32 | #endif 33 | 34 | 35 | #define WT2000_MAXIMUM_COMMAND_LENGTH (10) 36 | #define WT2000_MAXIMUM_REPLY_LENGTH (10) 37 | #define WT2000_MAXIMUM_FILE_NAME_LENGTH (8) 38 | 39 | #define WT2000_COMMAND_PLAY_INDEX (0xA2) 40 | #define WT2000_COMMAND_PLAY_NAME (0xA3) 41 | #define WT2000_COMMAND_PLAY_INDEX_FOLDER (0xA4) 42 | #define WT2000_COMMAND_PLAY_NAME_FOLDER (0xA5) 43 | #define WT2000_COMMAND_PAUSE (0xAA) 44 | #define WT2000_COMMAND_STOP (0xAB) 45 | #define WT2000_COMMAND_NEXT (0xAC) 46 | #define WT2000_COMMAND_PREVIOUS (0xAD) 47 | #define WT2000_COMMAND_SET_VOLUME (0xAE) 48 | #define WT2000_COMMAND_SET_MODE (0xAF) 49 | 50 | 51 | 52 | #define WT2000_COMMAND_FORWARD (0xD0) 53 | #define WT2000_COMMAND_REWIND (0xD1) 54 | #define WT2000_COMMAND_MEDIA_SELECT (0XD2) 55 | #define WT2000_COMMAND_CHANNEL_SELECT (0XD3) 56 | #define WT2000_COMMAND_SAMPLE_RATE_SELECT (0XD4) 57 | #define WT2000_COMMAND_RECORD_INDEX (0xD5) 58 | #define WT2000_COMMAND_RECORD_NAME (0xD6) 59 | #define WT2000_COMMAND_RECORD_INDEX_FOLDER (0xD7) 60 | #define WT2000_COMMAND_RECORD_NAME_FOLDER (0xD8) 61 | #define WT2000_COMMAND_RECORD_STOP (0xD9) 62 | #define WT2000_COMMAND_DELETE_INDEX (0xDA) 63 | #define WT2000_COMMAND_DELETE_NAME (0xDB) 64 | #define WT2000_COMMAND_DELETE_INDEX_FOLDER (0xDC) 65 | #define WT2000_COMMAND_DELETE_NAME_FOLDER (0xDD) 66 | #define WT2000_COMMAND_DELETE_ALL (0xDE) 67 | 68 | 69 | #define WT2000_COMMAND_GET_VOLUME (0xC1) 70 | #define WT2000_COMMAND_GET_MODE (0xC2) 71 | #define WT2000_COMMAND_FILE_COUNT (0xC5) 72 | #define WT2000_COMMAND_FILE_COUNT_FOLDER (0xC6) 73 | #define WT2000_COMMAND_GET_CURRENT_TRACK (0xC9) // 74 | #define WT2000_COMMAND_GET_MEDIA_STATUS (0xCA) 75 | #define WT2000_COMMAND_LOOK_UP_FILE (0xCB) 76 | #define WT2000_COMMAND_LOOK_UP_FILE_FOLDER (0xCC) 77 | #define WT2000_COMMAND_FREE_SPACE_LEFT (0xCE) 78 | 79 | 80 | #define WT2000_MODE_SINGLE (0X00) 81 | #define WT2000_MODE_SINGLE_CYCLE (0X01) 82 | #define WT2000_MODE_ALL_CYCLE (0X02) 83 | #define WT2000_MODE_SHUFFLE (0X03) 84 | #define WT2000_MODE_FOLDER_CYCLE (0X04) 85 | 86 | #define WT2000_MEDIA_SD (0X00) 87 | #define WT2000_MEDIA_USB (0X01) 88 | 89 | #define WT2000_CHANNEL_MIC (0X00) 90 | #define WT2000_CHANNEL_LINE_IN (0X01) 91 | #define WT2000_CHANNEL_AUX (0X02) 92 | 93 | #define WT2000_QUALITY_128K (0X00) 94 | #define WT2000_QUALITY_96K (0X01) 95 | #define WT2000_QUALITY_64K (0X02) 96 | #define WT2000_QUALITY_32K (0X04) 97 | 98 | 99 | 100 | 101 | 102 | class WT2000 { 103 | public: 104 | WT2000(Stream *myserial); 105 | uint8_t play(uint16_t index); //play by index: 16bit 106 | uint8_t play(char *name); //play by file name: 1-8 characters; ALL LETTERS MUST BE CAPITAL 107 | uint8_t play(uint16_t index, char *folder); //play by index in a folder: folder name is fixed to 5 characters wide; ALL LETTERS MUST BE CAPITAL 108 | uint8_t play(char *file, char *folder); //play by name in a folder: folder name is fixed to 5 characters wide;ALL LETTERS MUST BE CAPITAL 109 | uint8_t pause(void); //pause or resume current track 110 | uint8_t stop(void); //stop playing current track 111 | uint8_t volume(void); //get current volume (0-32) 0:mute 32:max 112 | uint8_t volume(uint8_t volume); //set volume to a specific value(0-32 see above) 113 | uint8_t forward(void); //call to speed up the play forward, call again to resume the play 114 | uint8_t rewind(void); //call to speed up the play backward , call again to resume the play 115 | uint8_t record(uint16_t index); //record by index: 16bit 116 | uint8_t record(char *name); //record by file name: 1-8 characters; ALL LETTERS MUST BE CAPITAL 117 | uint8_t record(uint16_t index, char *folder); //record by index in a folder: folder name is fixed to 5 characters wide; ALL LETTERS MUST BE CAPITAL 118 | uint8_t record(char *file, char *folder); //record by name in a folder: folder name is fixed to 5 characters wide; ALL LETTERS MUST BE CAPITAL 119 | uint8_t finish(void); //stop recording 120 | uint8_t next(void); //play next track 121 | uint8_t previous(void); //play preious track 122 | uint8_t mode(uint8_t mode); //set operating mode: cycle, cycle single, cycle all, shuffle, etc. 123 | uint8_t mode(void); //set operating mode: cycle, cycle single, cycle all, shuffle, etc. 124 | uint8_t media(uint8_t media); //select the storage media 125 | uint8_t media(); //get the status of the storage medias(sd card, usb stick) 126 | uint8_t channel(uint8_t channel); //select the recording audio source: mic, line-in, aux(stero) 127 | uint8_t quality(uint8_t quality); //set the quality of the recording, 128Kbps by default 128 | 129 | uint8_t remove(uint16_t index); //remove file by index: 16bit 130 | uint8_t remove(char *name); //remove file by file name: 1-8 characters; ALL LETTERS MUST BE CAPITAL 131 | uint8_t remove(uint16_t index, char *folder); //remove file by index in a folder: folder name is fixed to 5 characters wide; ALL LETTERS MUST BE CAPITAL 132 | uint8_t remove(char *file, char *folder); //remove file by name in a folder: folder name is fixed to 5 characters wide; ALL LETTERS MUST BE CAPITAL 133 | uint8_t erase(); //erase all file on the storage media 134 | 135 | uint16_t count(void); //count the number of tracks in the storage media 136 | uint16_t count(char *folder); //count the number of tracks in a spefic folder of the storage media; ALL LETTERS MUST BE CAPITAL 137 | 138 | uint8_t lookup(char *file); //check if the file is in the root directory, 0:yes, 1:no 139 | uint8_t lookup(char *file, char *folder); //check if the file is in the specific folder, 0:yes, 1:no; ALL LETTERS MUST BE CAPITAL 140 | 141 | uint16_t room(void); //check how many megabytes space left for storage 142 | private: 143 | Stream *_myserial; 144 | void sendcommand(uint8_t opcode, uint8_t data_length, uint8_t *buf); 145 | uint8_t receivereply(uint8_t data_length, char *buf, uint16_t timeout); 146 | }; 147 | #endif 148 | -------------------------------------------------------------------------------- /examples/DTMFDemo/DTMFDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | This is a demo code for Sandbox Electronics' WT2000 audio play/record shield. 4 | You can get one of those products on 5 | http://sandboxelectronics.com 6 | 7 | This demo code requires a sim900 module/shield connect to the Arduino to process 8 | the incoming phone call. 9 | You can get a sim900 shield on 10 | http://sandboxelectronics.com 11 | 12 | This code demonstrates the DTMF decoding and audio playing/recording ability of the shield. 13 | Version: 14 | V0.1 15 | 16 | Release Date: 17 | 2014-02-16 18 | 19 | Author: 20 | Tiequan Shao info@sandboxelectronics.com 21 | 22 | Lisence: 23 | CC BY-NC-SA 3.0 24 | 25 | Please keep the above information when you use this code in your project. 26 | */ 27 | 28 | #include 29 | #include "SIM900.h" 30 | #include 31 | #include "sms.h" 32 | #include "call.h" 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | CallGSM call; 40 | SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_BA); 41 | WT2000 myaudioshield = WT2000(&i2cuart); 42 | 43 | 44 | #define PIN_Q1 (0) 45 | #define PIN_Q2 (1) 46 | #define PIN_Q3 (2) 47 | #define PIN_Q4 (3) 48 | #define PIN_STD (4) 49 | #define PIN_AUDIO_SWITCH (5) 50 | 51 | 52 | #define DTMF_CONTEXT_IDLE (0) 53 | #define DTMF_CONTEXT_MAIN (1) 54 | #define DTMF_CONTEXT_DECODING_CHECK (2) 55 | #define DTMF_CONTEXT_RECORDING (3) 56 | #define DTMF_CONTEXT_PLAY_BACK (4) 57 | #define DTMF_CONTEXT_REPRESENTATIVE (5) 58 | 59 | #define DTMF_KEY_0 (10) 60 | #define DTMF_KEY_1 (1) 61 | #define DTMF_KEY_2 (2) 62 | #define DTMF_KEY_3 (3) 63 | #define DTMF_KEY_4 (4) 64 | #define DTMF_KEY_5 (5) 65 | #define DTMF_KEY_6 (6) 66 | #define DTMF_KEY_7 (7) 67 | #define DTMF_KEY_8 (8) 68 | #define DTMF_KEY_9 (9) 69 | #define DTMF_KEY_ASTERISK (11) 70 | #define DTMF_KEY_HASH (12) 71 | #define DTMF_KEY_A (13) 72 | #define DTMF_KEY_B (14) 73 | #define DTMF_KEY_C (15) 74 | #define DTMF_KEY_D (0) 75 | #define DTMF_KEY_NULL (16) 76 | 77 | 78 | 79 | byte stat=0; 80 | uint8_t DTMFContext = DTMF_CONTEXT_IDLE; 81 | uint8_t idle_flag = 1; 82 | void setup() 83 | { 84 | Serial.begin(9600); 85 | 86 | //SIM900 GSM Initialization 87 | if (gsm.begin(2400)) { 88 | Serial.println("GSM status=READY"); 89 | } else { 90 | Serial.println("GSM status=IDLE"); 91 | } 92 | // UART to Serial Bridge Initialization 93 | i2cuart.begin(9600); //baudrate setting 94 | i2cuart.pinMode(PIN_Q1,INPUT); //DTMF decoding input 1 95 | i2cuart.pinMode(PIN_Q2,INPUT); //DTMF decoding input 2 96 | i2cuart.pinMode(PIN_Q3,INPUT); //DTMF decoding input 3 97 | i2cuart.pinMode(PIN_Q4,INPUT); //DTMF decoding input 4 98 | i2cuart.pinMode(PIN_STD,INPUT); //DTMF data valid input 99 | i2cuart.pinMode(PIN_AUDIO_SWITCH,OUTPUT); //Audio channel selection output. 0: Earphone R - WT2000 DACR , 100 | // Earphone L -WT2000 DACL 101 | // Microphone - WT2000 MIC in 102 | // WT2000 DACR - SIM900 Audio Input 103 | // 1: Earphone R - SIM900 Audio Ouput 104 | // Earphone L - SIM900 Audio Ouput 105 | // Microphone - SIM900 Audio Input 106 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,0); //Set audio channel selection to 0, so sound played by WT2000 will be fed to earphone 107 | i2cuart.ModemPin(1); //Set GPIO4-GPIO7 as GPIO pins 108 | i2cuart.InterruptControl(0); // 109 | i2cuart.SetPinInterrupt(0x10); //Set Pin change Interrupt; GPIO4 pin change interrupt enabled; GPIO4 is connected to STD of the DTMF decoder 110 | i2cuart.GPIOLatch(1); 111 | myaudioshield.mode(WT2000_MODE_SINGLE); //Set play mode to single shot mode 112 | myaudioshield.channel(WT2000_CHANNEL_AUX); //Set Aux input as the recording channel; AUX R - Microphone (if audio channel selection == 1) 113 | // AUX R - 2.5V (if audio channel selection == 0) 114 | // AUX L - SIM900 Audio Output 115 | 116 | if (i2cuart.ping() !=1) { 117 | Serial.println("Error1: Can not connnect to SC16IS750"); 118 | Serial.println("Please check the connectivity of SDA-A4, and SCL-A5 if you are a Uno Board."); 119 | Serial.println("You may need to connect A4 to SDA and A5 to SCL with wires if your board does not have SCL and SDA broke out."); 120 | while(1); 121 | } else { 122 | // Serial.println("Connected to SC16IS750"); 123 | 124 | } 125 | 126 | }; 127 | 128 | void loop() 129 | { 130 | 131 | stat=call.CallStatus(); 132 | 133 | if(stat==CALL_INCOM_VOICE){ 134 | 135 | call.PickUp(); //pick up if there is any incoming call 136 | delay(1500); 137 | 138 | } else if (stat==CALL_ACTIVE_VOICE) { 139 | DTMFParser(); 140 | } else if (stat==CALL_NONE) { 141 | if (idle_flag == 0) { 142 | DTMFContext = DTMF_CONTEXT_IDLE; 143 | myaudioshield.stop(); 144 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,0); 145 | } 146 | idle_flag = 1; 147 | } 148 | 149 | }; 150 | 151 | 152 | 153 | 154 | uint8_t DTMFGetKey(void) 155 | { 156 | uint8_t key_value; 157 | uint8_t irq_id; 158 | irq_id = i2cuart.InterruptPendingTest(); 159 | if ( (irq_id&0x01) != 0 ) { //no valid data 160 | return DTMF_KEY_NULL; 161 | } else { 162 | key_value = i2cuart.GPIOGetPortState(); 163 | key_value &= 0x0F; 164 | return key_value; 165 | } 166 | 167 | 168 | } 169 | 170 | void DTMFParser(void) 171 | { 172 | uint8_t key_value; 173 | switch(DTMFContext) { 174 | case DTMF_CONTEXT_IDLE: 175 | idle_flag = 0; 176 | myaudioshield.play("MENU","TRACK"); 177 | DTMFContext = DTMF_CONTEXT_MAIN; 178 | break; 179 | case DTMF_CONTEXT_MAIN: 180 | key_value = DTMFGetKey(); 181 | switch (key_value) { 182 | case DTMF_KEY_NULL: 183 | 184 | break; 185 | case DTMF_KEY_1: 186 | myaudioshield.play("DTMF","TRACK"); 187 | DTMFContext = DTMF_CONTEXT_DECODING_CHECK; 188 | break; 189 | case DTMF_KEY_2: 190 | 191 | DTMFContext = DTMF_CONTEXT_RECORDING; 192 | break; 193 | case DTMF_KEY_3: 194 | DTMFContext = DTMF_CONTEXT_PLAY_BACK; 195 | break; 196 | case DTMF_KEY_4: 197 | myaudioshield.play("REPR","TRACK"); 198 | delay(3000); 199 | DTMFContext = DTMF_CONTEXT_REPRESENTATIVE; 200 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,1); 201 | break; 202 | case DTMF_KEY_HASH: 203 | call.HangUp(); 204 | default: 205 | break; 206 | } 207 | break; 208 | case DTMF_CONTEXT_DECODING_CHECK: 209 | 210 | key_value = DTMFGetKey(); 211 | switch (key_value) { 212 | case DTMF_KEY_NULL: 213 | Serial.println("No key pressed"); 214 | break; 215 | case DTMF_KEY_1: 216 | Serial.println("Key 1 pressed"); 217 | myaudioshield.play("1","TRACK"); 218 | break; 219 | case DTMF_KEY_2: 220 | Serial.println("Key 2 pressed"); 221 | myaudioshield.play("2","TRACK"); 222 | break; 223 | case DTMF_KEY_3: 224 | Serial.println("Key 3 pressed"); 225 | myaudioshield.play("3","TRACK"); 226 | break; 227 | case DTMF_KEY_4: 228 | Serial.println("Key 4 pressed"); 229 | myaudioshield.play("4","TRACK"); 230 | break; 231 | case DTMF_KEY_5: 232 | Serial.println("Key 5 pressed"); 233 | myaudioshield.play("5","TRACK"); 234 | break; 235 | case DTMF_KEY_6: 236 | Serial.println("Key 6 pressed"); 237 | myaudioshield.play("6","TRACK"); 238 | break; 239 | case DTMF_KEY_7: 240 | Serial.println("Key 7 pressed"); 241 | myaudioshield.play("7","TRACK"); 242 | break; 243 | case DTMF_KEY_8: 244 | Serial.println("Key 8 pressed"); 245 | myaudioshield.play("8","TRACK"); 246 | break; 247 | case DTMF_KEY_9: 248 | Serial.println("Key 9 pressed"); 249 | myaudioshield.play("9","TRACK"); 250 | break; 251 | case DTMF_KEY_0: 252 | Serial.println("Key 0 pressed"); 253 | myaudioshield.play("0","TRACK"); 254 | break; 255 | case DTMF_KEY_ASTERISK: 256 | Serial.println("Key * pressed"); 257 | myaudioshield.play("ASTER","TRACK"); 258 | break; 259 | case DTMF_KEY_HASH: 260 | Serial.println("Key # pressed"); 261 | myaudioshield.play("HASH","TRACK"); 262 | delay(1000); 263 | DTMFContext = DTMF_CONTEXT_IDLE; 264 | break; 265 | default: 266 | break; 267 | }; 268 | break; 269 | case DTMF_CONTEXT_RECORDING: 270 | myaudioshield.remove(0x0001,"REC00"); 271 | myaudioshield.play("RECRD","TRACK"); 272 | delay(2400); 273 | myaudioshield.play("BEEP","TRACK"); 274 | delay(2000); 275 | myaudioshield.record(0x0001,"REC00"); 276 | delay(10000); 277 | myaudioshield.finish(); 278 | myaudioshield.play("BEEP","TRACK"); 279 | delay(2000); 280 | key_value = DTMFGetKey(); //clear any key during the recording. 281 | DTMFContext = DTMF_CONTEXT_IDLE; 282 | break; 283 | case DTMF_CONTEXT_PLAY_BACK: 284 | myaudioshield.play(0X0001,"REC00"); 285 | delay(10000); 286 | myaudioshield.stop(); 287 | DTMFContext = DTMF_CONTEXT_IDLE; 288 | break; 289 | case DTMF_CONTEXT_REPRESENTATIVE: 290 | i2cuart.digitalWrite(PIN_AUDIO_SWITCH,1); 291 | break; 292 | 293 | default: 294 | break; 295 | } 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | } 309 | 310 | -------------------------------------------------------------------------------- /WT2000.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | This is a example code for Sandbox Electronics' WT2000 audio play/recording module. 4 | You can get one of those products on 5 | http://sandboxelectronics.com 6 | 7 | Version: 8 | V0.1 9 | 10 | Release Date: 11 | 2014-02-16 12 | 13 | Author: 14 | Tiequan Shao info@sandboxelectronics.com 15 | 16 | Lisence: 17 | CC BY-NC-SA 3.0 18 | 19 | Please keep the above information when you use this code in your project. 20 | */ 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | #include 30 | #include 31 | 32 | 33 | 34 | 35 | 36 | WT2000::WT2000(Stream *myserial) 37 | { 38 | _myserial = myserial; 39 | 40 | } 41 | 42 | uint8_t WT2000::quality(uint8_t quality) 43 | { 44 | sendcommand(WT2000_COMMAND_SAMPLE_RATE_SELECT,4, &quality); 45 | 46 | return receivereply(1,(char *)0, 1000); 47 | } 48 | 49 | uint8_t WT2000::channel(uint8_t channel) 50 | { 51 | sendcommand(WT2000_COMMAND_CHANNEL_SELECT,4, &channel); 52 | 53 | return receivereply(1,(char *)0, 1000); 54 | } 55 | 56 | uint8_t WT2000::media() 57 | { 58 | uint8_t media=0; 59 | sendcommand(WT2000_COMMAND_GET_MEDIA_STATUS,3, (uint8_t *)0); 60 | receivereply(2,(char*)&media, 10000); 61 | return media; 62 | } 63 | 64 | uint8_t WT2000::erase() 65 | { 66 | 67 | sendcommand(WT2000_COMMAND_DELETE_ALL,3, (uint8_t *)0); 68 | return receivereply(1,(char *)0, 1000); 69 | 70 | } 71 | 72 | uint8_t WT2000::media(uint8_t media) 73 | { 74 | sendcommand(WT2000_COMMAND_MEDIA_SELECT,4, &media); 75 | 76 | return receivereply(1,(char *)0, 1000); 77 | } 78 | 79 | uint8_t WT2000::mode() 80 | { 81 | uint8_t mode=0; 82 | sendcommand(WT2000_COMMAND_GET_MODE,3, (uint8_t *)0); 83 | receivereply(2,(char*)&mode, 10000); 84 | return mode; 85 | } 86 | 87 | uint8_t WT2000::mode(uint8_t mode) 88 | { 89 | sendcommand(WT2000_COMMAND_SET_MODE,4, &mode); 90 | 91 | return receivereply(1,(char *)0, 1000); 92 | } 93 | 94 | uint8_t WT2000::next(void) 95 | { 96 | sendcommand(WT2000_COMMAND_NEXT,3, (uint8_t *)0); 97 | return receivereply(1,(char *)0, 1000); 98 | } 99 | uint8_t WT2000::previous(void) 100 | { 101 | sendcommand(WT2000_COMMAND_PREVIOUS,3, (uint8_t *)0); 102 | return receivereply(1,(char *)0, 1000); 103 | } 104 | 105 | 106 | uint8_t WT2000::play(uint16_t index) 107 | { 108 | uint16_t index_swap; 109 | 110 | index_swap = ((index&0xFF00)>>8); 111 | index_swap |= ((index&0x00FF)<<8); 112 | sendcommand(WT2000_COMMAND_PLAY_INDEX,5, (uint8_t *)&index_swap); 113 | return receivereply(1,(char *)0, 1000); 114 | } 115 | 116 | uint8_t WT2000::play(uint16_t index, char *folder) 117 | { 118 | 119 | uint8_t buffer[7]; 120 | uint8_t i; 121 | 122 | for (i=0;i<5;i++) { 123 | buffer[i] = folder[i]; 124 | } 125 | 126 | buffer[5] = (uint8_t)((index&0xFF00)>>8); 127 | buffer[6] = (uint8_t)(index&0x00FF); 128 | 129 | sendcommand(WT2000_COMMAND_PLAY_INDEX_FOLDER,10, buffer); 130 | return receivereply(1,(char *)0, 1000); 131 | } 132 | 133 | 134 | uint8_t WT2000::lookup(char *file) 135 | { 136 | uint8_t name_length; 137 | name_length = strlen(file); 138 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 139 | 140 | sendcommand(WT2000_COMMAND_LOOK_UP_FILE,name_length+3,(uint8_t*)file); 141 | return receivereply(1,(char *)0, 1000); 142 | } 143 | 144 | uint8_t WT2000::lookup(char *file, char *folder) 145 | { 146 | 147 | uint8_t buffer[9]; 148 | uint8_t i; 149 | uint8_t name_length; 150 | name_length = strlen(file); 151 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 152 | 153 | for (i=0;i<5;i++) { 154 | buffer[i] = folder[i]; 155 | } 156 | 157 | for (i=0;i>8); 249 | count |= ((count_swap&0x00FF)<<8); 250 | 251 | return count; 252 | } 253 | 254 | uint16_t WT2000::count(char *folder) 255 | { 256 | uint16_t count=0; 257 | uint16_t count_swap; 258 | uint8_t buffer[5]; 259 | sendcommand(WT2000_COMMAND_FILE_COUNT_FOLDER,8, (uint8_t *)folder); 260 | receivereply(3,(char *)&count_swap, 1000); 261 | count = ((count_swap&0xFF00)>>8); 262 | count |= ((count_swap&0x00FF)<<8); 263 | 264 | return count; 265 | } 266 | 267 | uint8_t WT2000::volume(void) 268 | { 269 | uint8_t volume=0; 270 | sendcommand(WT2000_COMMAND_GET_VOLUME,3, (uint8_t *)0); 271 | receivereply(2,(char *)&volume, 10000); 272 | return volume; 273 | } 274 | 275 | 276 | 277 | uint8_t WT2000::volume(uint8_t volume) 278 | { 279 | sendcommand(WT2000_COMMAND_SET_VOLUME,4, &volume); 280 | 281 | return receivereply(1,(char *)0, 1000); 282 | } 283 | 284 | uint8_t WT2000::forward(void) 285 | { 286 | uint8_t volume=0; 287 | sendcommand(WT2000_COMMAND_FORWARD,3, (uint8_t *)0); 288 | return receivereply(1,(char *)0, 1000); 289 | } 290 | 291 | uint8_t WT2000::rewind(void) 292 | { 293 | uint8_t volume=0; 294 | sendcommand(WT2000_COMMAND_REWIND,3, (uint8_t *)0); 295 | return receivereply(1,(char *)0, 1000); 296 | 297 | } 298 | 299 | uint8_t WT2000::record(uint16_t index) 300 | { 301 | uint16_t index_swap; 302 | 303 | index_swap = ((index&0xFF00)>>8); 304 | index_swap |= ((index&0x00FF)<<8); 305 | sendcommand(WT2000_COMMAND_RECORD_INDEX,5, (uint8_t *)&index_swap); 306 | return receivereply(1,(char *)0, 1000); 307 | } 308 | 309 | uint8_t WT2000::record(uint16_t index, char *folder) //name of the folder should be 5-characters,otherwise this function will fill the rest of folder name with '0' 310 | { 311 | 312 | uint8_t buffer[7]; 313 | uint8_t i; 314 | uint8_t folder_name_length; 315 | 316 | folder_name_length = strlen(folder); 317 | folder_name_length %= (5+1); 318 | 319 | for (i=0;i<5;i++) { 320 | buffer[i] = folder[i]; 321 | } 322 | 323 | while (folder_name_length<5) { 324 | buffer[folder_name_length++] = '0'; 325 | } 326 | 327 | buffer[5] = (uint8_t)((index&0xFF00)>>8); 328 | buffer[6] = (uint8_t)(index&0x00FF); 329 | 330 | sendcommand(WT2000_COMMAND_RECORD_INDEX_FOLDER,10, buffer); 331 | return receivereply(1,(char *)0, 1000); 332 | } 333 | 334 | uint8_t WT2000::record(char *file) 335 | { 336 | uint8_t name_length; 337 | name_length = strlen(file); 338 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 339 | 340 | sendcommand(WT2000_COMMAND_RECORD_NAME,name_length+3,(uint8_t*)file); 341 | return receivereply(1,(char *)0, 1000); 342 | } 343 | 344 | uint8_t WT2000::record(char *file, char *folder) //name of the folder should be 5-characters,otherwise this function will fill the rest of folder name with '0' 345 | { 346 | 347 | uint8_t buffer[9]; 348 | uint8_t i; 349 | uint8_t name_length; 350 | uint8_t folder_name_length; 351 | 352 | name_length = strlen(file); 353 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 354 | 355 | folder_name_length = strlen(folder); 356 | folder_name_length %= (5+1); 357 | 358 | for (i=0;i<5;i++) { 359 | buffer[i] = folder[i]; 360 | } 361 | 362 | while (folder_name_length<5) { 363 | buffer[folder_name_length++] = '0'; 364 | } 365 | 366 | 367 | for (i=0;i>8); 386 | index_swap |= ((index&0x00FF)<<8); 387 | sendcommand(WT2000_COMMAND_DELETE_INDEX,5, (uint8_t *)&index_swap); 388 | return receivereply(1,(char *)0, 1000); 389 | } 390 | 391 | uint8_t WT2000::remove(uint16_t index, char *folder) 392 | { 393 | 394 | uint8_t buffer[7]; 395 | uint8_t i; 396 | 397 | for (i=0;i<5;i++) { 398 | buffer[i] = folder[i]; 399 | } 400 | 401 | buffer[5] = (uint8_t)((index&0xFF00)>>8); 402 | buffer[6] = (uint8_t)(index&0x00FF); 403 | 404 | sendcommand(WT2000_COMMAND_DELETE_INDEX_FOLDER,10, buffer); 405 | return receivereply(1,(char *)0, 1000); 406 | } 407 | 408 | uint8_t WT2000::remove(char *file) 409 | { 410 | uint8_t name_length; 411 | name_length = strlen(file); 412 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 413 | 414 | sendcommand(WT2000_COMMAND_DELETE_NAME,name_length+3,(uint8_t*)file); 415 | return receivereply(1,(char *)0, 1000); 416 | 417 | } 418 | 419 | uint8_t WT2000::remove(char *file, char *folder) 420 | { 421 | 422 | uint8_t buffer[9]; 423 | uint8_t i; 424 | uint8_t name_length; 425 | uint8_t result; 426 | name_length = strlen(file); 427 | name_length %= (WT2000_MAXIMUM_FILE_NAME_LENGTH+1); 428 | 429 | for (i=0;i<5;i++) { 430 | buffer[i] = folder[i]; 431 | } 432 | 433 | for (i=0;iwrite(0x7E); //Send start code; 450 | delay(2); 451 | _myserial->write(data_length);//Send length; 452 | delay(2); 453 | _myserial->write(opcode);//Send operation code; 454 | delay(2); 455 | for(i=0;iwrite(buf[i]); 459 | checksum += buf[i]; 460 | }; 461 | _myserial->write(checksum); 462 | _myserial->write(0xEF); 463 | 464 | return; 465 | } 466 | 467 | uint8_t WT2000::receivereply(uint8_t data_length, char *buf,uint16_t timeout) 468 | { 469 | char op_code; 470 | uint8_t count = 0; 471 | 472 | _myserial->setTimeout(timeout); 473 | if ( _myserial->readBytes(&op_code,1) == 0) { 474 | return 0xff; 475 | } else { 476 | count++; 477 | } 478 | if ( count < data_length ) { 479 | count = _myserial->readBytes(buf,data_length-1) + count; 480 | }; 481 | return op_code; 482 | } 483 | 484 | --------------------------------------------------------------------------------