Skip to content

Commit

Permalink
Add SAI/SAITransmitter/SAIReceiver class test.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mprse authored and 0xc0170 committed May 4, 2018
1 parent 021fca8 commit 9333be1
Showing 1 changed file with 294 additions and 0 deletions.
294 changes: 294 additions & 0 deletions TESTS/mbed_drivers/sai/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "math.h"

#define THREAD_STACK_SIZE 1024

#if !DEVICE_SAI
#error [NOT_SUPPORTED] SAI not supported for this target
#endif

using namespace utest::v1;

/* Since boards on CI do not have wire SAI loop-back connection, some of the functional
* tests can not be executed.
* If you want to fully test SAI support please connect pins as follows:
* - SAI_A_SD <--> SAI_B_SD
* - SAI_A_BCLK <--> SAI_B_BCLK
* - SAI_A_WCLK <--> SAI_B_WCLK
* and enable loop-back tests by setting LOOPBACK_CONNECTION to true.
*/
#define LOOPBACK_CONNECTION (false)

#define BUFFER_SIZE 100

typedef enum
{
LOOPBACK_TEST_OK, LOOPBACK_TEST_SKIP, LOOPBACK_TEST_FAILURE
} loopback_test_tatus_t;

static uint32_t transmit_buffer[BUFFER_SIZE];
static uint32_t receive_buffer[BUFFER_SIZE];

/* Auxiliary function which sets the specified buffer using specified pattern. */
static void set_buffer(void * buffer, uint32_t size, char pattern)
{
char* p_byte = (char*) buffer;

while (size--) {
*p_byte = pattern;
p_byte++;
}
}

/* Auxiliary function which compares two buffers and returns true if both are the same. */
static bool compare_buffers(const void *buffer1, const void *buffer2, uint32_t size)
{
const unsigned char *p1 = (const unsigned char *) buffer1;
const unsigned char *p2 = (const unsigned char *) buffer2;
while (size--) {
if (*p1 != *p2) {
return false;
} else {
p1++;
p2++;
}
}

return true;
}

/* Number of formats which must be supported by SAI device.
* This variable defines number of obligate formats in test_sai_formats array. */
const uint32_t required_formats_count = 5;

/* Array of tested formats. */
static sai_format_t test_sai_formats[] = {
// Formats which are requested for all SAI devices
sai_mode_i2s16,
sai_mode_i2s16w32,
sai_mode_i2s32,
sai_mode_pcm16l,
sai_mode_pcm16s,
// Other formats

};

/* Test that SAI class is able to communicate in loop-back mode.
*
* Given is SAI Class and SAI loop-back connection.
* When SAI object is configured as transmitter with the specified format and
* another SAI object is configured as receiver with the same format used.
* Then transmitter can successfully transmit samples to the receiver.
*/
void SAI_transmission_test()
{
loopback_test_tatus_t status;

if (!LOOPBACK_CONNECTION) {
TEST_IGNORE_MESSAGE("NO LOOPBACK CONNECTION - TEST SKIPPED!");
return;
}

char message[50];

for (uint32_t f_idx = 0; f_idx < (sizeof(test_sai_formats) / sizeof(sai_format_t)); f_idx++) {

SAI sai_transmitter(SAI_A_MCLK, // mclk
SAI_A_BCLK, // bclk
SAI_A_WCLK, // wclk
SAI_A_SD, // SD
&test_sai_formats[f_idx], // format
false, // is input
0, // master clock
false // internal mclk
);

SAI sai_receiver(SAI_B_MCLK, // mclk
SAI_B_BCLK, // bclk
SAI_B_WCLK, // wclk
SAI_B_SD, // SD
&test_sai_formats[f_idx], // format
true, // is input
0, // master clock
false // internal mclk
);

// we should check init status before the actual test - for now there is no such option
sai_result_t transmitter_init_status = SAI_RESULT_OK;
sai_result_t receiver_init_status = SAI_RESULT_OK;

/* Continue test only if SAI device has been successfully configured. */
if (transmitter_init_status == SAI_RESULT_OK && receiver_init_status == SAI_RESULT_OK) {

const uint32_t data_mask = ((1 << test_sai_formats[f_idx].data_length) - 1);

/* Set to unexpected. */
set_buffer(receive_buffer, sizeof(receive_buffer), 0xFF);

for (int i = 0; i < BUFFER_SIZE; i++) {
transmit_buffer[i] = data_mask / 100 * i;
}

uint32_t write_cnt = 0;
uint32_t read_cnt = 0;
uint32_t sample;

/* Send samples and read them back. */
while (1) {
if (write_cnt < BUFFER_SIZE) {
sample = transmit_buffer[write_cnt];
if (sai_transmitter.xfer(&sample) == true) {
write_cnt++;
}
}

if (sai_receiver.xfer(&sample) == true) {
receive_buffer[read_cnt] = sample;
read_cnt++;
}

if (read_cnt == BUFFER_SIZE) {
break;
}
}

if (compare_buffers(transmit_buffer, receive_buffer, BUFFER_SIZE) == true) {
status = LOOPBACK_TEST_OK;
} else {
status = LOOPBACK_TEST_FAILURE;
}
} else {
status = LOOPBACK_TEST_SKIP;
}

/* First `required_formats_count` formats are obligate, so we expect that
* communication tests passes. Others formats may be supported, so test can pass or be skipped.
*/
sprintf(message, "format idx: %lu", f_idx);
if (f_idx < required_formats_count) {
TEST_ASSERT_EQUAL_MESSAGE(LOOPBACK_TEST_OK, status, message);
} else {
TEST_ASSERT_NOT_EQUAL_MESSAGE(LOOPBACK_TEST_FAILURE, status, message);
}
}
}

/* Test that SAITransmitter class is able to send samples in loop-back mode.
* Test that SAIReceiver class is able to receive samples in loop-back mode.
*
* Given are SAITransmitter and SAIReceiver Classes and SAI loop-back connection.
* When SAI object is configured as transmitter with the specified format and
* another SAI object is configured as receiver with the same format used.
* Then transmitter can successfully transmit samples to the receiver.
*/
void SAITransmitter_SAIReceiver_transmission_test()
{
loopback_test_tatus_t status;

if (!LOOPBACK_CONNECTION) {
TEST_IGNORE_MESSAGE("NO LOOPBACK CONNECTION - TEST SKIPPED!");
return;
}

char message[50];

for (uint32_t f_idx = 0; f_idx < (sizeof(test_sai_formats) / sizeof(sai_format_t)); f_idx++) {

SAITransmitter sai_transmitter(SAI_A_MCLK, SAI_A_BCLK, SAI_A_WCLK, SAI_A_SD, &test_sai_formats[f_idx]);
SAIReceiver sai_receiver(SAI_B_MCLK, SAI_B_BCLK, SAI_B_WCLK, SAI_B_SD, &test_sai_formats[f_idx]);

// we should check init status before the actual test - for now there is no such option
sai_result_t transmitter_init_status = SAI_RESULT_OK;
sai_result_t receiver_init_status = SAI_RESULT_OK;

/* Continue test only if SAI device has been successfully configured. */
if (transmitter_init_status == SAI_RESULT_OK && receiver_init_status == SAI_RESULT_OK) {

const uint32_t data_mask = ((1 << test_sai_formats[f_idx].data_length) - 1);

/* Set to unexpected. */
set_buffer(receive_buffer, sizeof(receive_buffer), 0xFF);

for (int i = 0; i < BUFFER_SIZE; i++) {
transmit_buffer[i] = data_mask / 100 * i;
}

uint32_t write_cnt = 0;
uint32_t read_cnt = 0;
uint32_t sample;

/* Send samples and read them back. */
while (1) {
if (write_cnt < BUFFER_SIZE) {
sample = transmit_buffer[write_cnt];
if (sai_transmitter.send(sample) == true) {
write_cnt++;
}
}

if (sai_receiver.receive(&sample) == true) {
receive_buffer[read_cnt] = sample;
read_cnt++;
}

if (read_cnt == BUFFER_SIZE) {
break;
}
}

if (compare_buffers(transmit_buffer, receive_buffer, BUFFER_SIZE) == true) {
status = LOOPBACK_TEST_OK;
} else {
status = LOOPBACK_TEST_FAILURE;
}
} else {
status = LOOPBACK_TEST_SKIP;
}

/* First `required_formats_count` formats are obligate, so we expect that
* communication tests passes. Others formats may be supported, so test can pass or be skipped.
*/
sprintf(message, "format idx: %lu", f_idx);
if (f_idx < required_formats_count) {
TEST_ASSERT_EQUAL_MESSAGE(LOOPBACK_TEST_OK, status, message);
} else {
TEST_ASSERT_NOT_EQUAL_MESSAGE(LOOPBACK_TEST_FAILURE, status, message);
}
}
}

Case cases[] = {
Case("SAI - loopback communication test.", SAI_transmission_test),
Case("SAITransmitter/SAIReceiver - loopback communication test.", SAITransmitter_SAIReceiver_transmission_test),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(40, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
Harness::run(specification);
}

0 comments on commit 9333be1

Please sign in to comment.