Skip to content

Commit 5f302f1

Browse files
mprseithinuel
authored andcommitted
Add SAI/SAITransmitter/SAIReceiver class test.
Since currently we have only "placeholder" implementation and real "real" C++ implementation is under development current test provides only loop-back communication test using one format. Test needs to be updated when real implementation is ready.
1 parent 01f493f commit 5f302f1

File tree

1 file changed

+294
-0
lines changed

1 file changed

+294
-0
lines changed

TESTS/mbed_drivers/sai/main.cpp

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may 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,
12+
* WITHOUT 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+
#include "utest/utest.h"
17+
#include "unity/unity.h"
18+
#include "greentea-client/test_env.h"
19+
#include "mbed.h"
20+
#include "math.h"
21+
22+
#define THREAD_STACK_SIZE 1024
23+
24+
#if !DEVICE_SAI
25+
#error [NOT_SUPPORTED] SAI not supported for this target
26+
#endif
27+
28+
using namespace utest::v1;
29+
30+
/* Since boards on CI do not have wire SAI loop-back connection, some of the functional
31+
* tests can not be executed.
32+
* If you want to fully test SAI support please connect pins as follows:
33+
* - SAI_A_SD <--> SAI_B_SD
34+
* - SAI_A_BCLK <--> SAI_B_BCLK
35+
* - SAI_A_WCLK <--> SAI_B_WCLK
36+
* and enable loop-back tests by setting LOOPBACK_CONNECTION to true.
37+
*/
38+
#define LOOPBACK_CONNECTION (false)
39+
40+
#define BUFFER_SIZE 100
41+
42+
typedef enum
43+
{
44+
LOOPBACK_TEST_OK, LOOPBACK_TEST_SKIP, LOOPBACK_TEST_FAILURE
45+
} loopback_test_tatus_t;
46+
47+
static uint32_t transmit_buffer[BUFFER_SIZE];
48+
static uint32_t receive_buffer[BUFFER_SIZE];
49+
50+
/* Auxiliary function which sets the specified buffer using specified pattern. */
51+
static void set_buffer(void * buffer, uint32_t size, char pattern)
52+
{
53+
char* p_byte = (char*) buffer;
54+
55+
while (size--) {
56+
*p_byte = pattern;
57+
p_byte++;
58+
}
59+
}
60+
61+
/* Auxiliary function which compares two buffers and returns true if both are the same. */
62+
static bool compare_buffers(const void *buffer1, const void *buffer2, uint32_t size)
63+
{
64+
const unsigned char *p1 = (const unsigned char *) buffer1;
65+
const unsigned char *p2 = (const unsigned char *) buffer2;
66+
while (size--) {
67+
if (*p1 != *p2) {
68+
return false;
69+
} else {
70+
p1++;
71+
p2++;
72+
}
73+
}
74+
75+
return true;
76+
}
77+
78+
/* Number of formats which must be supported by SAI device.
79+
* This variable defines number of obligate formats in test_sai_formats array. */
80+
const uint32_t required_formats_count = 5;
81+
82+
/* Array of tested formats. */
83+
static sai_format_t test_sai_formats[] = {
84+
// Formats which are requested for all SAI devices
85+
sai_mode_i2s16,
86+
sai_mode_i2s16w32,
87+
sai_mode_i2s32,
88+
sai_mode_pcm16l,
89+
sai_mode_pcm16s,
90+
// Other formats
91+
92+
};
93+
94+
/* Test that SAI class is able to communicate in loop-back mode.
95+
*
96+
* Given is SAI Class and SAI loop-back connection.
97+
* When SAI object is configured as transmitter with the specified format and
98+
* another SAI object is configured as receiver with the same format used.
99+
* Then transmitter can successfully transmit samples to the receiver.
100+
*/
101+
void SAI_transmission_test()
102+
{
103+
loopback_test_tatus_t status;
104+
105+
if (!LOOPBACK_CONNECTION) {
106+
TEST_IGNORE_MESSAGE("NO LOOPBACK CONNECTION - TEST SKIPPED!");
107+
return;
108+
}
109+
110+
char message[50];
111+
112+
for (uint32_t f_idx = 0; f_idx < (sizeof(test_sai_formats) / sizeof(sai_format_t)); f_idx++) {
113+
114+
SAI sai_transmitter(SAI_A_MCLK, // mclk
115+
SAI_A_BCLK, // bclk
116+
SAI_A_WCLK, // wclk
117+
SAI_A_SD, // SD
118+
&test_sai_formats[f_idx], // format
119+
false, // is input
120+
0, // master clock
121+
false // internal mclk
122+
);
123+
124+
SAI sai_receiver(SAI_B_MCLK, // mclk
125+
SAI_B_BCLK, // bclk
126+
SAI_B_WCLK, // wclk
127+
SAI_B_SD, // SD
128+
&test_sai_formats[f_idx], // format
129+
true, // is input
130+
0, // master clock
131+
false // internal mclk
132+
);
133+
134+
// we should check init status before the actual test - for now there is no such option
135+
sai_result_t transmitter_init_status = SAI_RESULT_OK;
136+
sai_result_t receiver_init_status = SAI_RESULT_OK;
137+
138+
/* Continue test only if SAI device has been successfully configured. */
139+
if (transmitter_init_status == SAI_RESULT_OK && receiver_init_status == SAI_RESULT_OK) {
140+
141+
const uint32_t data_mask = ((1 << test_sai_formats[f_idx].data_length) - 1);
142+
143+
/* Set to unexpected. */
144+
set_buffer(receive_buffer, sizeof(receive_buffer), 0xFF);
145+
146+
for (int i = 0; i < BUFFER_SIZE; i++) {
147+
transmit_buffer[i] = data_mask / 100 * i;
148+
}
149+
150+
uint32_t write_cnt = 0;
151+
uint32_t read_cnt = 0;
152+
uint32_t sample;
153+
154+
/* Send samples and read them back. */
155+
while (1) {
156+
if (write_cnt < BUFFER_SIZE) {
157+
sample = transmit_buffer[write_cnt];
158+
if (sai_transmitter.xfer(&sample) == true) {
159+
write_cnt++;
160+
}
161+
}
162+
163+
if (sai_receiver.xfer(&sample) == true) {
164+
receive_buffer[read_cnt] = sample;
165+
read_cnt++;
166+
}
167+
168+
if (read_cnt == BUFFER_SIZE) {
169+
break;
170+
}
171+
}
172+
173+
if (compare_buffers(transmit_buffer, receive_buffer, BUFFER_SIZE) == true) {
174+
status = LOOPBACK_TEST_OK;
175+
} else {
176+
status = LOOPBACK_TEST_FAILURE;
177+
}
178+
} else {
179+
status = LOOPBACK_TEST_SKIP;
180+
}
181+
182+
/* First `required_formats_count` formats are obligate, so we expect that
183+
* communication tests passes. Others formats may be supported, so test can pass or be skipped.
184+
*/
185+
sprintf(message, "format idx: %lu", f_idx);
186+
if (f_idx < required_formats_count) {
187+
TEST_ASSERT_EQUAL_MESSAGE(LOOPBACK_TEST_OK, status, message);
188+
} else {
189+
TEST_ASSERT_NOT_EQUAL_MESSAGE(LOOPBACK_TEST_FAILURE, status, message);
190+
}
191+
}
192+
}
193+
194+
/* Test that SAITransmitter class is able to send samples in loop-back mode.
195+
* Test that SAIReceiver class is able to receive samples in loop-back mode.
196+
*
197+
* Given are SAITransmitter and SAIReceiver Classes and SAI loop-back connection.
198+
* When SAI object is configured as transmitter with the specified format and
199+
* another SAI object is configured as receiver with the same format used.
200+
* Then transmitter can successfully transmit samples to the receiver.
201+
*/
202+
void SAITransmitter_SAIReceiver_transmission_test()
203+
{
204+
loopback_test_tatus_t status;
205+
206+
if (!LOOPBACK_CONNECTION) {
207+
TEST_IGNORE_MESSAGE("NO LOOPBACK CONNECTION - TEST SKIPPED!");
208+
return;
209+
}
210+
211+
char message[50];
212+
213+
for (uint32_t f_idx = 0; f_idx < (sizeof(test_sai_formats) / sizeof(sai_format_t)); f_idx++) {
214+
215+
SAITransmitter sai_transmitter(SAI_A_MCLK, SAI_A_BCLK, SAI_A_WCLK, SAI_A_SD, &test_sai_formats[f_idx]);
216+
SAIReceiver sai_receiver(SAI_B_MCLK, SAI_B_BCLK, SAI_B_WCLK, SAI_B_SD, &test_sai_formats[f_idx]);
217+
218+
// we should check init status before the actual test - for now there is no such option
219+
sai_result_t transmitter_init_status = SAI_RESULT_OK;
220+
sai_result_t receiver_init_status = SAI_RESULT_OK;
221+
222+
/* Continue test only if SAI device has been successfully configured. */
223+
if (transmitter_init_status == SAI_RESULT_OK && receiver_init_status == SAI_RESULT_OK) {
224+
225+
const uint32_t data_mask = ((1 << test_sai_formats[f_idx].data_length) - 1);
226+
227+
/* Set to unexpected. */
228+
set_buffer(receive_buffer, sizeof(receive_buffer), 0xFF);
229+
230+
for (int i = 0; i < BUFFER_SIZE; i++) {
231+
transmit_buffer[i] = data_mask / 100 * i;
232+
}
233+
234+
uint32_t write_cnt = 0;
235+
uint32_t read_cnt = 0;
236+
uint32_t sample;
237+
238+
/* Send samples and read them back. */
239+
while (1) {
240+
if (write_cnt < BUFFER_SIZE) {
241+
sample = transmit_buffer[write_cnt];
242+
if (sai_transmitter.send(sample) == true) {
243+
write_cnt++;
244+
}
245+
}
246+
247+
if (sai_receiver.receive(&sample) == true) {
248+
receive_buffer[read_cnt] = sample;
249+
read_cnt++;
250+
}
251+
252+
if (read_cnt == BUFFER_SIZE) {
253+
break;
254+
}
255+
}
256+
257+
if (compare_buffers(transmit_buffer, receive_buffer, BUFFER_SIZE) == true) {
258+
status = LOOPBACK_TEST_OK;
259+
} else {
260+
status = LOOPBACK_TEST_FAILURE;
261+
}
262+
} else {
263+
status = LOOPBACK_TEST_SKIP;
264+
}
265+
266+
/* First `required_formats_count` formats are obligate, so we expect that
267+
* communication tests passes. Others formats may be supported, so test can pass or be skipped.
268+
*/
269+
sprintf(message, "format idx: %lu", f_idx);
270+
if (f_idx < required_formats_count) {
271+
TEST_ASSERT_EQUAL_MESSAGE(LOOPBACK_TEST_OK, status, message);
272+
} else {
273+
TEST_ASSERT_NOT_EQUAL_MESSAGE(LOOPBACK_TEST_FAILURE, status, message);
274+
}
275+
}
276+
}
277+
278+
Case cases[] = {
279+
Case("SAI - loopback communication test.", SAI_transmission_test),
280+
Case("SAITransmitter/SAIReceiver - loopback communication test.", SAITransmitter_SAIReceiver_transmission_test),
281+
};
282+
283+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
284+
{
285+
GREENTEA_SETUP(40, "default_auto");
286+
return greentea_test_setup_handler(number_of_cases);
287+
}
288+
289+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
290+
291+
int main()
292+
{
293+
Harness::run(specification);
294+
}

0 commit comments

Comments
 (0)