Skip to content

Commit 8f456bd

Browse files
committed
Add CHANGELOG
1 parent 7ef5309 commit 8f456bd

File tree

3 files changed

+376
-0
lines changed

3 files changed

+376
-0
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# ChirpSDK for Arduino Changelog
2+
3+
Recent changes to the [Chirp Arduino SDK](https://developers.chirp.io/docs).
4+
5+
## v3.0.0 (beta)
6+
7+
- Build v3.2.5
8+
- cortex-m4 architectures for MXChip

examples/credentials.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*------------------------------------------------------------------------------
2+
*
3+
* Credentials.h
4+
*
5+
* For full information on usage and licensing, see https://chirp.io/
6+
*
7+
* Copyright © 2011-2019, Asio Ltd.
8+
* All rights reserved.
9+
*
10+
*----------------------------------------------------------------------------*/
11+
12+
#ifndef Credentials_h
13+
#define Credentials_h
14+
15+
#error("Add your credentials below (from https://developers.chirp.io) and delete this line.")
16+
17+
#define APP_KEY "YOUR_APP_KEY"
18+
#define APP_SECRET "YOUR_APP_SECRET"
19+
#define APP_CONFIG "YOUR_APP_CONFIG"
20+
21+
#endif /* Credentials_h */

examples/mxchip.ino

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
/**------------------------------------------------------------------------------
2+
*
3+
* Simple example of the Chirp C SDK on the Microsoft MXChip IoT DevKit.
4+
*
5+
* @file mxchip.ino
6+
*
7+
* @brief After creating a developer account on https://developers.chirp.io, get
8+
* your key, secret and config string from your account using the "16kHz"
9+
* protocol, and set them in this file (in APP_KEY, APP_SECRET, APP_CONFIG).
10+
*
11+
* This example will start in listening mode. The listening and playing modes
12+
* can alternate by pressing the button A (on the left).
13+
*
14+
* Each time the SDK starts receiving some data, the LED will turn blue.
15+
* If the data has been successfully decoded then the LED will turn green and the
16+
* hexadecimal representation of the data as well as the length of the message,
17+
* in bytes, will be displayed. If the decode fails, the LED will turn red.
18+
*
19+
* In playing mode, each press on button B (on the right) will start sending a
20+
* random payload of random length, and turn the LED yellow. Once the payload
21+
* has been sent, the LED will turn cyan and the hexadecimal representation of the
22+
* data sent as well as the length of the payload, in bytes, will be displayed.
23+
* The audio data is sent via the 3.5mm jack output.
24+
*
25+
* See README.md for further information and known issues.
26+
*
27+
* Copyright © 2011-2018, Asio Ltd.
28+
* All rights reserved.
29+
*
30+
*----------------------------------------------------------------------------*/
31+
32+
/*
33+
* MXChip and Arduino native headers.
34+
*/
35+
#include "Arduino.h"
36+
#include "AudioClassV2.h"
37+
#include "OledDisplay.h"
38+
#include "RGB_LED.h"
39+
40+
/*
41+
* Main Chirp Connect header. This header and the ones it depends on must be in
42+
* the same folder.
43+
*/
44+
#include "chirp_connect.h"
45+
#include "credentials.h"
46+
47+
/*
48+
* The audio sample rate used by the microphone. At present, only 16kHz is
49+
* supported by the SDK on the MXChip board.
50+
*/
51+
#define SAMPLE_RATE 16000
52+
#define AUDIO_SAMPLE_SIZE 16
53+
#define SHORT_BUFFER_SIZE (AUDIO_CHUNK_SIZE / 2)
54+
#define FLOAT_BUFFER_SIZE (SHORT_BUFFER_SIZE / 2)
55+
56+
/*
57+
* To keep track of audio buffer states.
58+
*/
59+
typedef enum {
60+
BUFFER_STATE_NONE,
61+
BUFFER_STATE_EMPTY,
62+
BUFFER_STATE_FULL,
63+
} bufferState;
64+
65+
/*
66+
* Class handling the audio on the board. The state is recording by default.
67+
*/
68+
static AudioClass& Audio = AudioClass::getInstance();
69+
AUDIO_STATE_TypeDef audioState = AUDIO_STATE_RECORDING;
70+
71+
/*
72+
* Buffers containnig the audio to play and record data.
73+
*/
74+
static int16_t shortRecordBuffer[SHORT_BUFFER_SIZE] = {0};
75+
static float floatRecordBuffer[FLOAT_BUFFER_SIZE] = {0};
76+
bufferState recordBufferState = BUFFER_STATE_EMPTY;
77+
78+
static int16_t shortPlayBuffer[SHORT_BUFFER_SIZE] = {0};
79+
bufferState playBufferState = BUFFER_STATE_EMPTY;
80+
81+
int lastButtonAState;
82+
int buttonAState;
83+
84+
int buttonBState;
85+
int lastButtonBState;
86+
87+
RGB_LED rgbLed;
88+
89+
/*
90+
* Global pointer to the SDK structure. This is global as this pointer is
91+
* needed when processing the audio in the loop() function.
92+
*/
93+
chirp_connect_t *chirpConnect = NULL;
94+
95+
/*
96+
* Simple error handler which display an error message and loop indefinitely.
97+
*/
98+
void errorHandler(chirp_connect_error_code_t errorCode)
99+
{
100+
if (errorCode != CHIRP_CONNECT_OK)
101+
{
102+
Serial.printf("Error handler : %s\n", chirp_connect_error_code_to_string(errorCode));
103+
while(true);
104+
}
105+
}
106+
107+
/*
108+
* Audio recording callback called by the Audio Class instance when a new
109+
* buffer of samples is available with new recorded samples.
110+
*/
111+
void recordCallback(void)
112+
{
113+
Audio.readFromRecordBuffer((char *) shortRecordBuffer, SHORT_BUFFER_SIZE * 2);
114+
recordBufferState = BUFFER_STATE_FULL;
115+
}
116+
117+
/*
118+
* Audio playing callback called by the Audio Class instance when a new
119+
* buffer of samples is available with new samples to be played.
120+
*/
121+
void playCallback(void)
122+
{
123+
if(playBufferState == BUFFER_STATE_FULL)
124+
{
125+
Audio.writeToPlayBuffer((char *) shortPlayBuffer, SHORT_BUFFER_SIZE * 2);
126+
playBufferState = BUFFER_STATE_EMPTY;
127+
}
128+
}
129+
130+
/*
131+
* Callback reached when the SDK starts sending data.
132+
*/
133+
void on_sending_callback(void *data, uint8_t *payload, size_t length, uint8_t channel)
134+
{
135+
Screen.clean();
136+
rgbLed.setColor(255, 255, 0);
137+
}
138+
139+
/*
140+
* Callback reached when the SDK has sent the data.
141+
*/
142+
void on_sent_callback(void *data, uint8_t *payload, size_t length, uint8_t channel)
143+
{
144+
char *identifier = chirp_connect_as_string(chirpConnect, payload, length);
145+
char strLength[8] = {0};
146+
itoa(length, strLength, 10);
147+
148+
Screen.clean();
149+
Screen.print(0, "Sent !");
150+
Screen.print(1, (const char *) identifier, true);
151+
Screen.print(3, strLength);
152+
rgbLed.setColor(0, 255, 255);
153+
154+
free(payload);
155+
free(identifier);
156+
}
157+
158+
/*
159+
* Callback reached when the SDK starts receiving some data.
160+
*/
161+
void on_receiving_callback(void *data, uint8_t *payload, size_t length, uint8_t channel)
162+
{
163+
rgbLed.setColor(0, 0, 255);
164+
}
165+
166+
/*
167+
* Callback reached when the SDK has received some data.
168+
*/
169+
void on_received_callback(void *data, uint8_t *payload, size_t length, uint8_t channel)
170+
{
171+
// A pointer not null with a length different than 0 means the decode has succedeed.
172+
if (payload && length != 0)
173+
{
174+
char *identifier = chirp_connect_as_string(chirpConnect, payload, length);
175+
char strLength[8] = {0};
176+
itoa(length, strLength, 10);
177+
178+
Screen.clean();
179+
Screen.print(0, "Received !");
180+
Screen.print(1, (const char *) identifier, true);
181+
Screen.print(3, strLength);
182+
rgbLed.setColor(0, 255, 0);
183+
184+
free(payload);
185+
free(identifier);
186+
}
187+
// A null pointer with a length of 0 means the decode has failed.
188+
else
189+
{
190+
Screen.clean();
191+
Screen.print(0, "Decode failed =(");
192+
rgbLed.setColor(255, 0, 0);
193+
}
194+
}
195+
196+
/*
197+
* Setup function where the SDK is initialised.
198+
*/
199+
void setup()
200+
{
201+
Serial.begin(115200);
202+
delay(1000);
203+
204+
pinMode(USER_BUTTON_A, INPUT);
205+
lastButtonAState = digitalRead(USER_BUTTON_A);
206+
207+
chirpConnect = new_chirp_connect(APP_KEY, APP_SECRET);
208+
if (chirpConnect)
209+
{
210+
printf("Initialisation is OK\n");
211+
}
212+
else
213+
{
214+
printf("Initialisation failed\nAre your key and secret correct ?\n");
215+
exit(1);
216+
}
217+
218+
chirp_connect_error_code_t errorCode = chirp_connect_set_config(chirpConnect, APP_CONFIG);
219+
errorHandler(errorCode);
220+
221+
printf("Licence set correctly\n");
222+
223+
char *info = chirp_connect_get_info(chirpConnect);
224+
printf("%s - V%s\n", info, chirp_connect_get_version());
225+
free(info);
226+
227+
errorCode = chirp_connect_set_input_sample_rate(chirpConnect, SAMPLE_RATE);
228+
errorHandler(errorCode);
229+
printf("Input sample rate is : %u\n", chirp_connect_get_input_sample_rate(chirpConnect));
230+
231+
errorCode = chirp_connect_set_output_sample_rate(chirpConnect, SAMPLE_RATE);
232+
errorHandler(errorCode);
233+
printf("Output sample rate is : %u\n", chirp_connect_get_output_sample_rate(chirpConnect));
234+
235+
// The static structure is set to 0. This is needed because we are not setting
236+
// the `on_state_changed` callback.
237+
chirp_connect_callback_set_t callbacks = {0};
238+
callbacks.on_sending = on_sending_callback;
239+
callbacks.on_sent = on_sent_callback;
240+
callbacks.on_received = on_received_callback;
241+
callbacks.on_receiving = on_receiving_callback;
242+
243+
errorCode = chirp_connect_set_callbacks(chirpConnect, callbacks);
244+
errorHandler(errorCode);
245+
246+
printf("Callbacks set\n");
247+
248+
// MXChip specific : A software adjustment of the sample rate is needed.
249+
errorCode = chirp_connect_set_frequency_correction(chirpConnect, 0.9950933459f);
250+
errorHandler(errorCode);
251+
252+
errorCode = chirp_connect_start(chirpConnect);
253+
errorHandler(errorCode);
254+
255+
printf("SDK started\n");
256+
257+
Screen.clean();
258+
Screen.print(0, "Chirp C SDK");
259+
Screen.print(1, "Listening ...");
260+
261+
// Setup the audio class and start recording.
262+
Audio.format(SAMPLE_RATE, AUDIO_SAMPLE_SIZE);
263+
int res = Audio.startRecord(recordCallback);
264+
if (res != 0)
265+
{
266+
Serial.printf("Error when starting audio\n");
267+
while(true);
268+
}
269+
}
270+
271+
void loop()
272+
{
273+
buttonAState = digitalRead(USER_BUTTON_A);
274+
buttonBState = digitalRead(USER_BUTTON_B);
275+
chirp_connect_error_code_t errorCode;
276+
277+
// If we've pressed the button A, alternate the audio state between Recording and Playing.
278+
if (buttonAState == LOW && lastButtonAState == HIGH)
279+
{
280+
if (audioState == AUDIO_STATE_RECORDING)
281+
{
282+
audioState = AUDIO_STATE_PLAYING;
283+
Audio.stop();
284+
Audio.startPlay(playCallback);
285+
Screen.clean();
286+
Screen.print(0, "Playing");
287+
}
288+
else if (audioState == AUDIO_STATE_PLAYING)
289+
{
290+
audioState = AUDIO_STATE_RECORDING;
291+
Audio.stop();
292+
Audio.startRecord(recordCallback);
293+
Screen.clean();
294+
Screen.print(0, "Recording");
295+
}
296+
297+
rgbLed.turnOff();
298+
}
299+
300+
if (audioState == AUDIO_STATE_RECORDING)
301+
{
302+
// Once the recording buffer is full, we process it.
303+
if (recordBufferState == BUFFER_STATE_FULL)
304+
{
305+
// Convert the stereo audio samples into mono by taking every other sample and convert them
306+
// from int16_t to float.
307+
for (int i = 0; i < FLOAT_BUFFER_SIZE; i++)
308+
{
309+
floatRecordBuffer[i] = (float) shortRecordBuffer[i * 2] / 32767.0f;
310+
}
311+
errorCode = chirp_connect_process_input(chirpConnect, floatRecordBuffer, FLOAT_BUFFER_SIZE);
312+
errorHandler(errorCode);
313+
recordBufferState = BUFFER_STATE_EMPTY;
314+
}
315+
}
316+
else if (audioState == AUDIO_STATE_PLAYING)
317+
{
318+
// If the button B is pressed a chirp is sent.
319+
if (buttonBState == LOW && lastButtonBState == HIGH)
320+
{
321+
size_t randomPayloadLength = 0;
322+
uint8_t *randomPayload = chirp_connect_random_payload(chirpConnect, &randomPayloadLength);
323+
errorCode = chirp_connect_send(chirpConnect, randomPayload, randomPayloadLength);
324+
errorHandler(errorCode);
325+
free(randomPayload);
326+
}
327+
328+
chirp_connect_state_t state = chirp_connect_get_state(chirpConnect);
329+
if (state == CHIRP_CONNECT_STATE_SENDING && playBufferState == BUFFER_STATE_EMPTY)
330+
{
331+
float tmpBuffer[SHORT_BUFFER_SIZE / 2] = {0};
332+
errorCode = chirp_connect_process_output(chirpConnect, tmpBuffer, SHORT_BUFFER_SIZE / 2);
333+
errorHandler(errorCode);
334+
// On the contrary of the recording part, we duplicate the data produced by the SDK
335+
// to create a stereo audio stream that is converted from float to int16_t samples.
336+
for (uint16_t i = 0; i < SHORT_BUFFER_SIZE / 2; i++)
337+
{
338+
shortPlayBuffer[i * 2] = tmpBuffer[i] * 32767.0f;
339+
shortPlayBuffer[i * 2 + 1] = tmpBuffer[i] * 32767.0f;
340+
}
341+
playBufferState = BUFFER_STATE_FULL;
342+
}
343+
}
344+
345+
lastButtonAState = buttonAState;
346+
lastButtonBState = buttonBState;
347+
}

0 commit comments

Comments
 (0)