vincent wong
Published © GPL3+

Freedom Maraca

A Freedom board Maraca which makes some musical notes using buzzer.

IntermediateFull instructions provided584
Freedom Maraca

Things used in this project

Hardware components

Kinetis Freedom Board with FlexIO
NXP Kinetis Freedom Board with FlexIO
×1
Seeed Studio Grove - Starter Kit for Arduino
×1
USB Battery Pack
×1

Software apps and online services

NXP Kinetis Expert
NXP Kinetis Design Studio Integrated Development Environment (IDE)

Story

Read more

Code

main.c

C/C++
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* All rights reserved.
*
*/

/*  Standard C Included Files */
#include <stdio.h>
#include <string.h>
/*  SDK Included Files */
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_flexio_i2c_master.h"

#include "clock_config.h"
#include "pin_mux.h"
#include "fsl_port.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define BOARD_FLEXIO_BASE FLEXIO0
#define FLEXIO_I2C_SDA_PIN 4U
#define FLEXIO_I2C_SCL_PIN 5U
#define FLEXIO_CLOCK_FREQUENCY 12000000U

#define I2C_BAUDRATE (100000) /* 100K */

#define FOXS8700_WHOAMI (0xC7U)
#define MMA8451_WHOAMI (0x1AU)
#define ACCEL_STATUS (0x00U)
#define ACCEL_XYZ_DATA_CFG (0x0EU)
#define ACCEL_CTRL_REG1 (0x2AU)
/* FOXS8700 and MMA8451 have the same who_am_i register address. */
#define ACCEL_WHOAMI_REG (0x0DU)
#define ACCEL_READ_TIMES (10U)


#define GROVE_BUZZER_GPIO GPIOD
#define GROVE_BUZZER_GPIO_PIN 0U

#define GROVE_LED_GPIO GPIOC
#define GROVE_LED_GPIO_PIN 11U
#define GROVE_BUTTON_GPIO GPIOC
#define GROVE_BUTTON_GPIO_PIN 12U

#define CLK_SPEED 150000000   //Put your board's clock speed here in Hz, FRDM-K82F = 150000000



/*******************************************************************************
 * Prototypes
 ******************************************************************************/

static bool I2C_example_readAccelWhoAmI(void);
static bool I2C_write_accel_reg(FLEXIO_I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t value);
static bool I2C_read_accel_regs(
    FLEXIO_I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize);

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*  FOXS8700 and MMA8451 device address */
const uint8_t g_accel_address[] = {0x1CU, 0x1DU, 0x1EU, 0x1FU};

flexio_i2c_master_handle_t g_m_handle;
FLEXIO_I2C_Type i2cDev;
uint8_t g_accel_addr_found = 0x00;
volatile bool completionFlag = false;
volatile bool nakFlag = false;

// mapping of distance value of X-, Y- and Z-axis to buzzer notes
const char noteMaps[] = { 'C', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'c', ' ' };
const int tempo = 30;


/*******************************************************************************
 * Code
 ******************************************************************************/

/**
 * play sounds
 *
 */

void delay(void)
{
    volatile uint32_t i = 0;
    for (i = 0; i < 10000000; ++i)
    {
        __asm("NOP"); /* delay */
    }
}

void delay2(int t)
{
    volatile uint32_t i = 0;
    for (i = 0; i < t * 10000; ++i)
    {
        __asm("NOP"); /* delay */
    }

}

void delayMicroSeconds(int time)
{
    uint32_t delayNum = CLK_SPEED / 1000000 * time; //turn into 1 micros then multiply
    volatile uint32_t cnt = 0U;
    for(cnt = 0U; cnt < delayNum; ++cnt){
      __asm("NOP");
    }
}


void playTone(int tone, int duration) {
    for (long i = 0; i < duration * 1000L; i += tone * 2) {
//        GPIO_WritePinOutput(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, 20U);
        GPIO_SetPinsOutput(GROVE_BUZZER_GPIO, 1u << GROVE_BUZZER_GPIO_PIN);
        delayMicroSeconds(tone);
        GPIO_ClearPinsOutput(GROVE_BUZZER_GPIO, 1u << GROVE_BUZZER_GPIO_PIN);
        delayMicroSeconds(tone);
    }
    PRINTF("end tone\r\n");
}

void playNote(char note, int duration) {
    char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
//    int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
//    int tones[] = { 192, 170, 152, 143, 128, 114, 101, 96 };
        int tones[] = { 191, 170, 151, 143, 127, 113, 101, 95 };

    // play the tone corresponding to the note name
    for (int i = 0; i < 8; i++) {
        if (names[i] == note) {
            PRINTF("tone = %d, duration = %d\r\n", tones[i], duration);
            playTone(tones[i], duration);

        }
    }
}

char mapNote(int distance) {
	int i = distance / 1000;
	if (i >= 10) i = 10;
	return noteMaps[i];
}

/**
 * rest of the codes
 *
 */


static void flexio_i2c_master_callback(FLEXIO_I2C_Type *base,
                                       flexio_i2c_master_handle_t *handle,
                                       status_t status,
                                       void *userData)
{
    /* Signal transfer success when received success status. */
    if (status == kStatus_Success)
    {
        completionFlag = true;
    }
    /* Signal transfer success when received success status. */
    if (status == kStatus_FLEXIO_I2C_Nak)
    {
        nakFlag = true;
    }
}

static bool I2C_example_readAccelWhoAmI(void)
{
    /*
    How to read the device who_am_I value ?
    Start + Device_address_Write , who_am_I_register;
    Repeart_Start + Device_address_Read , who_am_I_value.
    */
    uint8_t who_am_i_reg = ACCEL_WHOAMI_REG;
    uint8_t who_am_i_value = 0x00;
    uint8_t accel_addr_array_size = 0x00;
    bool find_device = false;
    bool result = false;
    uint8_t i = 0;
    uint32_t j = 0;

    flexio_i2c_master_config_t masterConfig;

    /*do hardware configuration*/
    i2cDev.flexioBase = BOARD_FLEXIO_BASE;
    i2cDev.SDAPinIndex = FLEXIO_I2C_SDA_PIN;
    i2cDev.SCLPinIndex = FLEXIO_I2C_SCL_PIN;
    i2cDev.shifterIndex[0] = 0U;
    i2cDev.shifterIndex[1] = 1U;
    i2cDev.timerIndex[0] = 0U;
    i2cDev.timerIndex[1] = 1U;

    /*
     * masterConfig.enableMaster = true;
     * masterConfig.enableInDoze = false;
     * masterConfig.enableInDebug = true;
     * masterConfig.enableFastAccess = false;
     * masterConfig.baudRate_Bps = 100000U;
     */
    FLEXIO_I2C_MasterGetDefaultConfig(&masterConfig);
    masterConfig.baudRate_Bps = I2C_BAUDRATE;

    FLEXIO_I2C_MasterInit(&i2cDev, &masterConfig, FLEXIO_CLOCK_FREQUENCY);

    flexio_i2c_master_transfer_t masterXfer;
    memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = g_accel_address[0];
    masterXfer.direction = kFLEXIO_I2C_Read;
    masterXfer.subaddress = who_am_i_reg;
    masterXfer.subaddressSize = 1;
    masterXfer.data = &who_am_i_value;
    masterXfer.dataSize = 1;

    accel_addr_array_size = sizeof(g_accel_address) / sizeof(g_accel_address[0]);

    for (i = 0; i < accel_addr_array_size; i++)
    {
        masterXfer.slaveAddress = g_accel_address[i];

        FLEXIO_I2C_MasterTransferNonBlocking(&i2cDev, &g_m_handle, &masterXfer);

        /*  wait for transfer completed. */
        while ((nakFlag == false) && (completionFlag == false))
        {
        }
        if (nakFlag == true)
        {
            nakFlag = false;
        }
        if (completionFlag == true)
        {
            completionFlag = false;
            find_device = true;
            g_accel_addr_found = masterXfer.slaveAddress;
            break;
        }
        for (j = 0; j < 0xFFF; j++)
        {
            __NOP();
        }
    }

    if (find_device == true)
    {
        switch (who_am_i_value)
        {
            case FOXS8700_WHOAMI:
                PRINTF("Found a FOXS8700 on board, the device address is 0x%02X. \r\n", masterXfer.slaveAddress);
                result = true;
                break;
            case MMA8451_WHOAMI:
                PRINTF("Found a MMA8451 on board, the device address is 0x%02X. \r\n", masterXfer.slaveAddress);
                result = true;
                break;
            default:

                PRINTF("Found a device, the WhoAmI value is 0x%02X\r\n", who_am_i_value);
                PRINTF("It's not MMA8451 or FXOS8700. \r\n");
                PRINTF("The device address is 0x%02X. \r\n", masterXfer.slaveAddress);
                result = false;
                break;
        }

        return result;
    }
    else
    {
        PRINTF("Not a successful i2c communication\r\n");
        return false;
    }
}

static bool I2C_write_accel_reg(FLEXIO_I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t value)
{
    flexio_i2c_master_transfer_t masterXfer;
    memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = device_addr;
    masterXfer.direction = kFLEXIO_I2C_Write;
    masterXfer.subaddress = reg_addr;
    masterXfer.subaddressSize = 1;
    masterXfer.data = &value;
    masterXfer.dataSize = 1;

    /*  direction=write : start+device_write;cmdbuff;xBuff; */
    /*  direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */

    FLEXIO_I2C_MasterTransferNonBlocking(&i2cDev, &g_m_handle, &masterXfer);

    /*  Wait for transfer completed. */
    while ((!nakFlag) && (!completionFlag))
    {
    }

    nakFlag = false;

    if (completionFlag == true)
    {
        completionFlag = false;
        return true;
    }
    else
    {
        return false;
    }
}

static bool I2C_read_accel_regs(
    FLEXIO_I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize)
{
    flexio_i2c_master_transfer_t masterXfer;
    memset(&masterXfer, 0, sizeof(masterXfer));
    masterXfer.slaveAddress = device_addr;
    masterXfer.direction = kFLEXIO_I2C_Read;
    masterXfer.subaddress = reg_addr;
    masterXfer.subaddressSize = 1;
    masterXfer.data = rxBuff;
    masterXfer.dataSize = rxSize;

    /*  direction=write : start+device_write;cmdbuff;xBuff; */
    /*  direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */

    FLEXIO_I2C_MasterTransferNonBlocking(&i2cDev, &g_m_handle, &masterXfer);

    /*  Wait for transfer completed. */
    while ((!nakFlag) && (!completionFlag))
    {
    }

    nakFlag = false;

    if (completionFlag == true)
    {
        completionFlag = false;
        return true;
    }
    else
    {
        return false;
    }
}

/*!
 * @brief Main function
 */
int main(void)
{
    /* Define the init structure for the output LED pin*/
    gpio_pin_config_t led_config = {
        kGPIO_DigitalOutput, 0,
    };

    gpio_pin_config_t button_config = {
        kGPIO_DigitalInput, 0,
    };

    bool isThereAccel = false;

    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();


    CLOCK_EnableClock(kCLOCK_PortD);

    PORT_SetPinMux(PORTD, 0U, kPORT_MuxAsGpio);
    PORT_SetPinMux(PORTC, 12U, kPORT_MuxAsGpio);
    PORT_SetPinMux(PORTC, 11U, kPORT_MuxAsGpio);

    /* Init output LED GPIO. */
    GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);
    GPIO_PinInit(GROVE_BUTTON_GPIO, GROVE_BUTTON_GPIO_PIN, &button_config);
    GPIO_PinInit(GROVE_LED_GPIO, GROVE_LED_GPIO_PIN, &led_config);



    CLOCK_EnableClock(kCLOCK_PortB);
    /* FlexIO-I2C SDA pin */
    /* Affects PORTB_PCR10 register */
    PORT_SetPinMux(PORTB, 10U, kPORT_MuxAlt7);
    /* FlexIO-I2C SCL pin */
    /* Affects PORTB_PCR11 register */
    PORT_SetPinMux(PORTB, 11U, kPORT_MuxAlt7);

    CLOCK_EnableClock(kCLOCK_PortA);
    /* Affects PORTA_PCR1 register */
    PORT_SetPinMux(PORTA, 1U, kPORT_MuxAlt4);
    /* Affects PORTA_PCR2 register */
    PORT_SetPinMux(PORTA, 2U, kPORT_MuxAlt4);


    CLOCK_SetFlexio0Clock(2U);

    PRINTF("\r\nFlexIO I2C example read accelerometer value\r\n");

    FLEXIO_I2C_MasterTransferCreateHandle(&i2cDev, &g_m_handle, flexio_i2c_master_callback, NULL);
    isThereAccel = I2C_example_readAccelWhoAmI();

    /*  read the accel xyz value if there is accel device on board */
    if (true == isThereAccel)
    {
        uint8_t databyte = 0;
        uint8_t write_reg = 0;
        uint8_t readBuff[7];
        int16_t x, y, z;
        uint8_t status0_value = 0;

        /*  please refer to the "example FXOS8700CQ Driver Code" in FXOS8700 datasheet. */
        /*  write 0000 0000 = 0x00 to accelerometer control register 1 */
        /*  standby */
        /*  [7-1] = 0000 000 */
        /*  [0]: active=0 */
        write_reg = ACCEL_CTRL_REG1;
        databyte = 0;
        I2C_write_accel_reg(&i2cDev, g_accel_addr_found, write_reg, databyte);

        /*  write 0000 0001= 0x01 to XYZ_DATA_CFG register */
        /*  [7]: reserved */
        /*  [6]: reserved */
        /*  [5]: reserved */
        /*  [4]: hpf_out=0 */
        /*  [3]: reserved */
        /*  [2]: reserved */
        /*  [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB */
        /*  databyte = 0x01; */
        write_reg = ACCEL_XYZ_DATA_CFG;
        databyte = 0x01;
        I2C_write_accel_reg(&i2cDev, g_accel_addr_found, write_reg, databyte);

        /*  write 0000 1101 = 0x0D to accelerometer control register 1 */
        /*  [7-6]: aslp_rate=00 */
        /*  [5-3]: dr=001 for 200Hz data rate (when in hybrid mode) */
        /*  [2]: lnoise=1 for low noise mode */
        /*  [1]: f_read=0 for normal 16 bit reads */
        /*  [0]: active=1 to take the part out of standby and enable sampling */
        /*   databyte = 0x0D; */
        write_reg = ACCEL_CTRL_REG1;
        databyte = 0x0d;
        I2C_write_accel_reg(&i2cDev, g_accel_addr_found, write_reg, databyte);
        PRINTF("The accel values:\r\n");


        bool playing;
        int buttonState;
        int lastButtonState;

        int distance;
        char note;
        int beat = 1;

        while(1)
        {
            buttonState = GPIO_ReadPinInput(GROVE_BUTTON_GPIO, GROVE_BUTTON_GPIO_PIN);

            if (buttonState == 0U && lastButtonState == 1U && playing == false) {
            	playing = true;
            	lastButtonState = buttonState;

            } else if (buttonState == 0U && lastButtonState == 1U && playing == true) {
            	playing = false;
            	lastButtonState = buttonState;
            } else {
            	lastButtonState = buttonState;
            }

            if (playing == true) {
				status0_value = 0;
				/*  wait for new data are ready. */
				while (status0_value != 0xff)
				{
					I2C_read_accel_regs(&i2cDev, g_accel_addr_found, ACCEL_STATUS, &status0_value, 1);
				}

				/*  Multiple-byte Read from STATUS (0x00) register */
				I2C_read_accel_regs(&i2cDev, g_accel_addr_found, ACCEL_STATUS, readBuff, 7);

				status0_value = readBuff[0];
				x = ((int16_t)(((readBuff[1] * 256U) | readBuff[2]))) / 4U;
				y = ((int16_t)(((readBuff[3] * 256U) | readBuff[4]))) / 4U;
				z = ((int16_t)(((readBuff[5] * 256U) | readBuff[6]))) / 4U;

				distance = (x*x + y*y + z*z) / 1000;
				PRINTF("status_reg = 0x%x , x = %5d , y = %5d , z = %5d, d = %5d \r\n", status0_value, x, y, z, distance);

				note = mapNote(distance);

				if (note == ' ')
				{
					delay2(beat * tempo); // rest
					PRINTF("rest\r\n");
				}
				else
				{
					if (note == 'c' || note == 'e' || note == 'g' || note == 'b') {
						GPIO_WritePinOutput(GROVE_LED_GPIO, GROVE_LED_GPIO_PIN, 1U);
					} else {
						GPIO_WritePinOutput(GROVE_LED_GPIO, GROVE_LED_GPIO_PIN, 0U);
					}

					PRINTF("note = %c, duration = %d\r\n", note, beat * tempo);
					playNote(note, beat * tempo);
				}

				// pause between notes
				delay2(tempo / 2);

            }   // is playing
        }
    }

    PRINTF("\r\nEnd of Poke Ball App .\r\n");
    while (1)
    {
    }
}

Credits

vincent wong

vincent wong

80 projects • 203 followers

Comments