Skip to content

Commit bae9a06

Browse files
author
Qinghao Shi
authored
Merge pull request #62 from mprse/usb_examples
Add USB examples
2 parents c36d9fe + 9573498 commit bae9a06

File tree

37 files changed

+10140
-23
lines changed

37 files changed

+10140
-23
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ jobs:
1717
cd work
1818
mbed config root .
1919
mbed update
20+
mbed add https://github.com/c1728p9/AudioPlayer
2021
mbed test --compile -m K64F -t GCC_ARM -n sinppet-* --app-config=sinppet/TESTS/test.json -v
21-
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## USBAudio loopback example
2+
3+
The example loops input audio to the Mbed board back to the host PC, so that you may record the audio or listen to it through headphones or speakers.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Select "Mbed Audio" as your PC's default speaker and microphone devices.
7+
3. Play some sound (YouTube, audio file, etc.) on your PC.
8+
4. The audio that is playing on your PC will be recorded by Audacity via USB loopback.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "mbed.h"
2+
#include "USBAudio.h"
3+
4+
int main()
5+
{
6+
USBAudio audio(true, 44100, 2, 44100, 2);
7+
8+
printf("Looping audio\r\n");
9+
static uint8_t buf[128];
10+
while (true) {
11+
if (!audio.read(buf, sizeof(buf))) {
12+
memset(buf, 0, sizeof(buf));
13+
}
14+
audio.write(buf, sizeof(buf));
15+
}
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## USBAudio play sound example
2+
3+
The example loads raw audio data to your board's flash and then plays on the host PC over USB.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open a program like Audacity, select microphone(Mbed audio) as an audio source and record sample.
7+
3. Play the the recorded sound.
8+
9+
**Note:** This example should work whitout any modifications on the `NXP FRDM-K64F`, which has `1 MB` of flash memory.
10+
**Note:** If you are using a board that has less than `1 MB` of flash memory, delete data from the end of the `data` array, and set `NUM_ELEMENTS` accordingly until the program size is small enough to flash without exceeding storage.

APIs_USB/USBAudio_play_sound/main.cpp

Lines changed: 9390 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## USBAudio square wave example
2+
3+
The example outputs an audio square wave over USB.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open a program like Audacity, select microphone(Mbed audio) as an audio source and record sample.
7+
3. Zoom in the recorded sound and you should see a square wave.
8+
9+
**Note:** You can also route microphone(Mbed audio) to the output device and you should hear a buzz.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "mbed.h"
2+
#include "USBAudio.h"
3+
#include <math.h>
4+
5+
int16_t square_wave(uint32_t freq_hz, uint16_t amplitude, float time_s)
6+
{
7+
float period = (float)1 / freq_hz;
8+
if (fmod(time_s, period) > period / 2) {
9+
return amplitude / 2;
10+
} else {
11+
return -(amplitude / 2);
12+
}
13+
}
14+
15+
int main()
16+
{
17+
uint32_t tx_freq = 16000;
18+
USBAudio audio(true, 8000, 2, tx_freq, 1, 10, 0x7bb8, 0x1112, 0x0100);
19+
float cur_time = 0;
20+
while (true) {
21+
uint16_t samples[64];
22+
for (int i = 0; i < 64; i++) {
23+
samples[i] = square_wave(100, 5000, cur_time);
24+
cur_time += 1.0 / tx_freq;
25+
}
26+
if (!audio.write((uint8_t *)&samples, sizeof(samples))) {
27+
audio.write_wait_ready();
28+
}
29+
}
30+
}
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## USBAudio wav audio player example
2+
3+
The example plays the wav audio file from the target's SD card on the host PC over USB.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Store example audio file on the SD card in the following location: `songs/Bach-minuet-in-g.wav`.
7+
3. Insert SD-card to the targte's SD-card slot.
8+
4. Open a program like Audacity, select microphone(Mbed audio) as an audio source and record sample.
9+
5. Play the recorded sound.
10+
11+
**Note:** This example should work whitout any modifications on the `NXP FRDM-K64F` with SD card connected.
12+
**Note:** You can also route microphone(Mbed audio) to the output device and you should hear the music.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "mbed.h"
2+
#include "USBAudio.h"
3+
#include "SDBlockDevice.h"
4+
#include "FATFileSystem.h"
5+
#include "AudioPlayer.h"
6+
#include "WaveAudioStream.h"
7+
8+
#define BUFFER_SIZE 512
9+
#define FREQ_25_MHZ 25000000
10+
11+
// Connection for SD card
12+
SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);//MOSI, MISO, SCLK, CS
13+
FATFileSystem fs("sd", &sd);
14+
15+
int main()
16+
{
17+
// Set the maximum speed so it can keep up with audio
18+
sd.frequency(FREQ_25_MHZ);
19+
// Load WAV file from SD card
20+
// WAV file must be PCM signed 16-bit little endian
21+
File file;
22+
if (file.open(&fs, "songs/Bach-minuet-in-g.wav") != 0) {
23+
error("Could not open 'songs/Bach-minuet-in-g.wav'\r\n");
24+
}
25+
WaveAudioStream song(&file);//"song" is the audio data object
26+
// Check to see if file is a valid WAV file
27+
if (song.get_valid() == 0) {
28+
error("ERROR: not valid WAV file\r\n");
29+
}
30+
// WAV file must be 16-bit
31+
if (song.get_bytes_per_sample() != 2) {
32+
error("ERROR: WAV file not 2 bytes per sample (16-bit)\r\n");
33+
}
34+
USBAudio audio(true, 8000, song.get_channels(), song.get_sample_rate(), song.get_channels());
35+
uint8_t buffer[BUFFER_SIZE];
36+
int num_bytes_read;
37+
printf("Playing Audio\r\n");
38+
// Reads and plays data from WAV file over USB until song is over
39+
while (1) {
40+
num_bytes_read = song.read(buffer, BUFFER_SIZE);
41+
if (num_bytes_read == -1) {
42+
printf("Song Over\r\n");
43+
break;
44+
}
45+
audio.write(buffer, num_bytes_read);
46+
}
47+
song.close();//Close the WAV file
48+
}

APIs_USB/USBCDC/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## USBCDC example
2+
3+
The example sends string in the loop using an emulated serial port over USB.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open serial console (select associated COM port, transmission speed: 9600 bps).
7+
3. Reset the target.
8+
4. "Hello world" string should appear in the loop on the serial console in the 1-second delays.
9+
10+
**Note:** On Windows you can check the associated COM port in the Device Manager (USB Serial Device).
11+
**Note:** If you want printf functionality, please see the USBSerial class.

APIs_USB/USBCDC/main.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "mbed.h"
2+
#include "USBCDC.h"
3+
4+
USBCDC cdc;
5+
6+
int main(void)
7+
{
8+
9+
while (1) {
10+
char msg[] = "Hello world\r\n";
11+
cdc.send((uint8_t *)msg, strlen(msg));
12+
ThisThread::sleep_for(1000);
13+
}
14+
}

APIs_USB/USBCDC_ECM/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
The example sends an Ethernet frame that carries "Hello world" payload with a custom EtherType to the host PC. You can capture the frame by using a program called "Wireshark":
44

55
1. Flash the board, and ensure the target's USB is plugged into the PC.
6-
2. Open Wireshark.
7-
3. Click **Capture > Options** to select the correct capture interface.
8-
4. Click **Capture > Start**.
9-
5. Click captured packet from source address 12:34:56:78:9a:bc to see the "Hello world" payload.
6+
2. Use `dmesg -w` linux command to determine address of the USB CDC Ethernet device.
7+
3. Use `ifconfig` linux command to determine interface related to the the USB CDC Ethernet device.
8+
4. Open Wireshark.
9+
5. Click **Capture > Options** to select the correct capture interface.
10+
6. Click **Capture > Start**.
11+
7. Click captured packet from source address 12:34:56:78:9a:bc to see the "Hello world" payload.
1012

11-
**Note:** Because Windows doesn't provide native support for the USB CDC-ECM model, you must use third party drivers to use this class on Windows.
13+
**Note:** Because Windows doesn't provide native support for the USB CDC-ECM model, you must use third party drivers to use this class on Windows. It is suggested to run this example on Linux.

APIs_USB/USBCDC_ECM/main.cpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
/*
2-
* Copyright (c) 2019 ARM Limited. All rights reserved.
3-
* SPDX-License-Identifier: Apache-2.0
4-
* Licensed under the Apache License, Version 2.0 (the License); you may
5-
* not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
171
#include "mbed.h"
182
#include "USBCDC_ECM.h"
193

@@ -36,8 +20,12 @@ USBCDC_ECM ecm;
3620

3721
int main()
3822
{
23+
// Let the USB device to setup
24+
ThisThread::sleep_for(10);
25+
26+
// Send "Hello world" packets in loop
3927
while (true) {
4028
ecm.send((uint8_t *)&packet, sizeof(packet));
41-
wait(1.0);
29+
ThisThread::sleep_for(1000);
4230
}
4331
}

APIs_USB/USBHID/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## USBHID example
2+
3+
This example turns the Mbed board into the HID (Human Interface Device) that can send and receive messages over USB.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open serial console (select Mbed COM port, transmission speed: 9600 bps).
7+
3. Reset the target.
8+
4. Run the attached Python script.
9+
5. The script will send 8 bytes of data (1 2 3 4 5 6 7 8) to the Mbed board and will read and print the data sent to the host computer by the Mbed board.
10+
6. You should see "1 2 3 4 5 6 7 8" on the console and LED1 on the target device should change its state to the opposite.
11+
12+
**Note:** You can check the Mbed COM port using "mbedls" command.

APIs_USB/USBHID/USBHID.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from pywinusb import hid
2+
3+
# Whenever the host computer receives data from the
4+
# Mbed board, the received data is printed
5+
def on_data(data):
6+
print(f"Got message {data}")
7+
8+
'''
9+
Gets all HIDs currently connected to host computer,
10+
and sets the first device with string "mbed" in its
11+
vendor name equal to variable mbed. This variable
12+
will be used to send data to the Mbed board.
13+
'''
14+
all_hid_devices = hid.find_all_hid_devices()
15+
mbed_devices = [d for d in all_hid_devices if "mbed" in d.vendor_name]
16+
17+
if mbed_devices is None:
18+
raise ValueError("No HID devices found")
19+
20+
# A buffer of bytes representing the values 1-8
21+
# The first byte is the report ID which must be 0
22+
buffer = [0, 1, 2, 3, 4, 5, 6, 7, 8]
23+
24+
mbed_devices[0].open()
25+
# Set custom raw data handler
26+
mbed_devices[0].set_raw_data_handler(on_data)
27+
28+
# Send the message to the Mbed board
29+
out_report = mbed_devices[0].find_output_reports()
30+
out_report[0].set_raw_data(buffer)
31+
out_report[0].send()

APIs_USB/USBHID/main.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include <stdio.h>
2+
#include "mbed.h"
3+
#include "drivers/USBHID.h"
4+
5+
// Declare a USBHID device
6+
USBHID HID(8, 8, 0x1234, 0x0006, 0x0001, true);
7+
8+
HID_REPORT output_report = {
9+
.length = 8,
10+
.data = {0}
11+
};
12+
HID_REPORT input_report = {
13+
.length = 0,
14+
.data = {0}
15+
};
16+
17+
DigitalOut led_out(LED1);
18+
19+
int main(void)
20+
{
21+
while (1) {
22+
23+
// Fill the report
24+
for (int i = 0; i < output_report.length; i++) {
25+
output_report.data[i] = rand() & UINT8_MAX;
26+
}
27+
28+
// Send the report
29+
HID.send(&output_report);
30+
31+
// Try to read a msg
32+
if (HID.read_nb(&input_report)) {
33+
led_out = !led_out;
34+
for (int i = 0; i < input_report.length; i++) {
35+
printf("%d ", input_report.data[i]);
36+
}
37+
printf("\r\n");
38+
}
39+
}
40+
}

APIs_USB/USBKeyboard/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## USBKeyboard example
2+
3+
The example emulates keyboard over USB port.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Reset the target.
7+
3. "Hello World" sequence should be typed by the virtual keyboard in loop with 1 sec delays.

APIs_USB/USBKeyboard/main.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "mbed.h"
2+
#include "USBKeyboard.h"
3+
4+
USBKeyboard key;
5+
6+
int main(void)
7+
{
8+
while (1) {
9+
key.printf("Hello World\r\n");
10+
ThisThread::sleep_for(1000);
11+
}
12+
}

APIs_USB/USBMIDI/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## USBMIDI example
2+
3+
The example sends a series of MIDI notes to the host PC
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open Anvil Studio.
7+
3. Click View > Synthesizers, MIDI + Audio Devices.
8+
4. Uncheck Synth is too slow to echo incoming events.
9+
5. Click View > Composer (Staff Editor) to see notes from the board being mapped to the sheet music.

APIs_USB/USBMIDI/main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "mbed.h"
2+
#include "USBMIDI.h"
3+
4+
USBMIDI midi;
5+
6+
int main()
7+
{
8+
while (1) {
9+
for (int i = 48; i < 83; i++) { // send some messages!
10+
midi.write(MIDIMessage::NoteOn(i));
11+
ThisThread::sleep_for(250);
12+
midi.write(MIDIMessage::NoteOff(i));
13+
ThisThread::sleep_for(500);
14+
}
15+
}
16+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## USBMIDI "Take Me Out to the Ball Game" example
2+
3+
The example plays an entire song, not just a series of notes. "Take Me Out to the Ball Game" is a popular song in the public domain.
4+
5+
1. Flash the board, and ensure the target's auxiliary USB is plugged into the PC.
6+
2. Open Anvil Studio.
7+
3. Click View > Synthesizers, MIDI + Audio Devices.
8+
4. Uncheck Synth is too slow to echo incoming events.
9+
5. Click View > Composer (Staff Editor) to see notes from the board being mapped to the sheet music.

0 commit comments

Comments
 (0)