Hi @bastenhoor , thanks for the interest.
I wrote the code in Renesas e2studio, hacking one of the examples - it's not tidy.
You can move the code sine-synthesis bit across to the Arduino IDE, but you will need the RA4M1 EK dev board to run the I2S channel - or use an SPI DAC.
Note the inner sine code is inline-assembler, which is what makes this possible, with Paul Stoffregen's 11th order Taylor Series Approximation
https://github.com/PaulStoffregen/Audio/blob/master/utility/dspinst.h
Note there is a bug in the original inline assembler code, which I found and fixed.
/***********************************************************************************************************************
* File Name : hal_entry.c
* Description : Contains data structures and functions used in hal_entry.c.
**********************************************************************************************************************/
/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2020 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
#include "common_utils.h"
#include "stdio.h"
#include "I:\Arduino Projects\6 - Uno R4 Boards\Code\Includes\susan_ra4m1_minima_register_defines.h"
// Why are the harmonics of a piano tone not multiples of the base frequency?
// https://physics.stackexchange.com/questions/268568/why-are-the-harmonics-of-a-piano-tone-not-multiples-of-the-base-frequency
// Using Inline Assembly in C/C++
// https://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C
// Note: use the __asm__ ("assembly code"); form.
#define BUFF_SIZE 0x1000U //Sample audio buffer size
/* Destination buffer to receive the sample audio data */
uint8_t g_dest_buff[BUFF_SIZE] = {RESET_VALUE};
/* Source buffer to transmit the sample audio data */
const uint8_t g_src_buff[BUFF_SIZE] = {RESET_VALUE};
#define MAX_TIME 0xffff //Max time value for time out
#define LED_PIN BSP_IO_PORT_01_PIN_06
#define SSIE_BUFF_SIZE 0x10
#define SSIE_MAX_TIME 0x01FF
#define COMPLEX_SINE
#define INHARMONICITY // Live harmonic/tone frequency offsets
#define SINE_24_BITS // Full 25 bit resolution - not needed for 16 bit CD quality output
/*
#define PORTBASE 0x40040000 // Port Base
#define PMISC_PWPR ((volatile unsigned char *)(PORTBASE + 0x0D03)) // Write-Protect Register - 19.2.6
#define PWPR_PFSWE 6 // PmnPFS Register Write Enable; 0: Writing to PmnPFS register disabled, 1: Writing enabled.
#define PWPR_B0WI 7 // PFSWE Bit Write Disable; 0: Writing to the PFSWE bit enabled, 1: Writing disabled
#define P200PFS 0x0880 // Port 2 Pin Function Select Register
#define PFS_P205PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (5 * 4))) // N/C - IRQ1 - CLKOUT
#define PFS_P106PFS_BY ((volatile unsigned char *)(PORTBASE + 0x0843 + ( 6 * 4))) // D6
*/
void R_BSP_WarmStart(bsp_warm_start_event_t event);
/* Private functions */
static void deinit_gpt(void);
static void deinit_ssi(void);
/*******************************************************************************************************************//**
* @addtogroup SSI_EP
* @{
**********************************************************************************************************************/
/* Global variables */
volatile i2s_event_t g_i2s_event = I2S_EVENT_TX_EMPTY; //an actual event updates in callback
#define SSIE_FRAME_RATE 44117 // Adjust to get accurate match
#define AUDIO_MAX_AMPLITUDE 0x7FFFFFFF
#define AUDIO_MAX_GLOBAL 0x1FFFFFFF
#define SINE_GEN_SLOTS 10
#define AUDIO_NOTE_HZ (float)440.00
#define AUDIO_NOTE_PHASE (float)0.00
#define AUDIO_AMP_0 (float)1.00
#define AUDIO_AMP_1 (float)0.70
#define AUDIO_AMP_2 (float)0.35
#define AUDIO_AMP_3 (float)0.20
#define AUDIO_AMP_4 (float)-0.05
#define AUDIO_AMP_5 (float)0.05
#define AUDIO_AMP_6 (float)-0.05
#define AUDIO_AMP_7 (float)0.01
#define AUDIO_AMP_8 (float)-0.05
#define AUDIO_AMP_9 (float)0.01
#define AUDIO_AMP_10 (float)-0.05
#define AUDIO_AMP_11 (float)0.01
#define AUDIO_AMP_12 (float)-0.05
#define AUDIO_ZERO 0
#define AUDIO_FIRST 1
#define AUDIO_SECOND 2
#define AUDIO_THIRD 3
#define AUDIO_FORTH 4
#define AUDIO_FIFTH 5
#define AUDIO_SIXTH 6
#define AUDIO_SEVENTH 7
#define AUDIO_EIGHTH 8
#define AUDIO_NINTH 9
#define AUDIO_TENTH 10
#define AUDIO_ELEVENTH 11
#define AUDIO_TWELFTH 12
// Multiplier for inharmonicity of harmonics
#define AUDIO_INHAM_1 (float)1.00 // 440/440 Note Funderment and Second harmonics match their tones
#define AUDIO_INHAM_2 (float)1.00 // 880/880
#define AUDIO_INHAM_3 (float)1.008 // 1330/1320
#define AUDIO_INHAM_4 (float)1.011 // 1780/1760
#define AUDIO_INHAM_5 (float)1.014 // 2230/2200
#define AUDIO_INHAM_6 (float)1.015 // 2680/2640
#define AUDIO_INHAM_7 (float)1.019 // 3140/3080
#define AUDIO_INHAM_8 (float)1.026 // 3610/3520
#define AUDIO_INHAM_9 (float)1.033 // 4090/3960
#define AUDIO_INHAM_10 (float)1.039 // 4570/4400
#define AUDIO_INHAM_11 (float)1.045 // 5060/4840
#define AUDIO_INHAM_12 (float)1.055 // 5570/5280
static uint32_t sine_freq_table[SINE_GEN_SLOTS];
/*
static float sine_harmonic_table[SINE_GEN_SLOTS] =
{
AUDIO_FIRST, AUDIO_FIRST,
AUDIO_SECOND, AUDIO_THIRD,
AUDIO_FORTH, AUDIO_FIFTH,
AUDIO_SIXTH, AUDIO_SEVENTH,
AUDIO_EIGHTH, AUDIO_NINTH
};
*/
static float sine_amp_table[SINE_GEN_SLOTS] =
{
AUDIO_AMP_0, AUDIO_AMP_1,
AUDIO_AMP_2, AUDIO_AMP_3,
AUDIO_AMP_4, AUDIO_AMP_5,
AUDIO_AMP_6, AUDIO_AMP_7,
AUDIO_AMP_8, AUDIO_AMP_9
};
/*
static float sine_phase_table[SINE_GEN_SLOTS] =
{
AUDIO_NOTE_PHASE, AUDIO_NOTE_PHASE + 90.00,
AUDIO_NOTE_PHASE, AUDIO_NOTE_PHASE + 90.00,
AUDIO_NOTE_PHASE, AUDIO_NOTE_PHASE + 90.00,
AUDIO_NOTE_PHASE, AUDIO_NOTE_PHASE + 90.00
};
*/
// static float sine_inharm_table[SINE_GEN_SLOTS]; // Table to hold inharmonicity ratios for harmonics
static uint32_t sine_hdelta_table[SINE_GEN_SLOTS]; // Table to hold harmonic delta adding
static int32_t sine_output_table[SINE_GEN_SLOTS];
/*******************************************************************************************************************//**
* The RA Configuration tool generates main() and uses it to generate threads if an RTOS is used. This function is
* called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
static int32_t out_sine, out_cosine;
static int32_t acc_sine, acc_cosine;
int32_t result_taylor_sine;
int32_t result_taylor_cosine;
static float sine_freq_local = AUDIO_NOTE_HZ;
static int32_t sine_amp_global = AUDIO_MAX_GLOBAL;
static int32_t sine_amp_local = 0x7FFFFFFF;
uint32_t freq_time_cosine;
static uint32_t freq_time_accumulate = 0;
static uint32_t freq_time_1st_acc = 0;
static uint32_t freq_time_2nd_acc = 0;
static uint32_t freq_time_3rd_acc = 0;
static uint32_t freq_time_4th_acc = 0;
static uint32_t freq_time_5th_acc = 0;
static uint32_t freq_time_6th_acc = 0;
static uint32_t freq_time_7th_acc = 0;
static uint32_t freq_time_8th_acc = 0;
static uint32_t freq_time_9th_acc = 0;
static uint32_t freq_gen_sine = 0;
static uint32_t freq_time_delta = 0x1 << 24; // This value gives 837Hz in fast loop() - was c. 300Hz
// static uint32_t freq_time_delta_1hz = (4294967295 / SSIE_FRAME_RATE); // 97392 at 44.100kHz = 440.18Hz
static uint32_t freq_time_delta_1hz = (4294967295 / SSIE_FRAME_RATE); // 97392 for 44.1kHz
//static uint32_t test_flags = 0;
/* Error status */
fsp_err_t err = FSP_SUCCESS;
fsp_pack_version_t version = {RESET_VALUE};
volatile uint32_t time_out = MAX_TIME; // time_out value which is used to break the infinite loop
/* Unlock Port Pin Write-Protection */
*PMISC_PWPR = 0x00; // Clear BOWI
*PMISC_PWPR = 0x40; // Set PFSWE
*PFS_P205PFS = (0b01001 << 24); // Select PSEL[4:0] for CLKOUT - See Table 19.8
*PFS_P205PFS |= (0x1 << 16); // Port Mode Control - Used as an I/O port for peripheral function
*PFS_P205PFS |= (0x1 << 10); // Port Drive Capability - Set to Middle - Reduces Rise/Fall time from 6 to 4 nS
/* Version get API for FLEX pack information */
R_FSP_VersionGet(&version);
/* Example Project information printed on the Console */
APP_PRINT(BANNER_INFO, EP_VERSION, version.version_id_b.major, version.version_id_b.minor, version.version_id_b.patch);
APP_PRINT("\r\nThe project demonstrates SSI module by transmitting and receiving \r\n"
"the sample audio data in loop back connection and prints the status \r\n"
"by comparing the transmitted and received data buffers \r\n");
/* Open SSI module */
err = R_SSI_Open(&g_i2s_ctrl, &g_i2s_cfg);
/* Handle error */
if(FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n SSI open failed \r\n");
/* Trap here */
APP_ERR_TRAP(err);
}
/* Open GPT in periodic mode as internal clock for SSI bit clock */
err = R_GPT_Open(&g_timer_ctrl, &g_timer_cfg);
/* Handle error */
if(FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n GPT open failed, Closing SSI \r\n");
deinit_ssi();
/* Trap here */
APP_ERR_TRAP(err);
}
/* Start GPT in periodic mode */
err = R_GPT_Start(&g_timer_ctrl);
/* Handle error */
if(FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n GPT start failed, Closing SSI and GPT \r\n");
deinit_ssi();
deinit_gpt();
/* Trap here */
APP_ERR_TRAP(err);
}
// Change SSIE AudioClock source GPT Timer settings
*GPT321_GTSTP = 0x00000010; // Stop Timer 1
*GPT321_GTCCRA = 0x0008; //
*GPT321_GTCCRB = 0x0008; //
*GPT321_GTCCRC = 0x0008; //
*GPT321_GTCCRD = 0x0008; //
*GPT321_GTPR = 0x0010; // 0x0E = 50kHz; 0x0F = 46.9kHz; 0x10 = 44.1kHz with 32bit L/R clock lengths (64bits per cycle)
*GPT321_GTPBR = 0x0010; // when Audio Clock Rate = MCK (without division)
*GPT321_GTCR |= 0x1; // Start Timer 1 with a PreScale of zero
/* Transmit and receive the sample audio data buffer using WriteRead API from source buffer to destination buffer
* through loop back connection from SSITXD to SSIRXD */
// err = R_SSI_WriteRead(&g_i2s_ctrl, g_src_buff, g_dest_buff, BUFF_SIZE);
err = R_SSI_Write(&g_i2s_ctrl, g_src_buff, SSIE_BUFF_SIZE);
/* Handle error */
if(FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n WriteRead API failed, Closing SSI and GPT \r\n");
deinit_ssi();
deinit_gpt();
// Trap here
APP_ERR_TRAP(err);
}
/*Wait for completion of WriteRead operation using I2S_EVENT_IDLE event and time_out. Using these both ensures
*that the DTC transfer will be over by the time transmit underflow occurs during R_SSI_WriteRead processing.
*This is important so the receive buffer can be flushed in the transmit underflow error processing.
*Without this, the last frame (two samples) could be lost during R_SSI_WriteRead. */
// while ((I2S_EVENT_IDLE != g_i2s_event) || ((time_out--) > 0));
/* Compare the transmission of sample audio data from source buffer to destination buffer with WriteRead API */
// int cmp_result = memcmp(g_src_buff, g_dest_buff, sizeof(g_src_buff));
/*
if (RESET_VALUE == cmp_result)
{
APP_PRINT("\r\nCompared the transmitted sample audio data of SSI with received data is successful");
}
else
{
APP_PRINT("\r\nCompared the transmitted sample audio data of SSI with received data is failed");
}
*/
// *SSIE0_SSISCR |= (0x111 << SSISCR_TDFS_2_0); // 111: SSIFTDR has eight stages or more free space
*SSIE0_SSISCR = 0x00000000; // 000: SSIFTDR has one stage or more free space
*SSIE0_SSICR |= (0x1 << SSICR_TUIEN); // Enable transmit underflow interrupt output
// *SSIE0_SSIFCR |= (0x1 << SSIFCR_TIE); // Enable transmit data empty interrupts
uint8_t fifo_load_count = 0;
for(fifo_load_count = 0; fifo_load_count <= 5; fifo_load_count++)
{
*SSIE0_SSIFTDR_HA = 0x000A;
*SSIE0_SSIFTDR_HA = 0x0005;
}
*SSIE0_SSICR |= (0x1 << SSICR_TEN); // Enable transmit operation
// Calculate increment for frequency.
freq_time_delta = (uint32_t)((float)freq_time_delta_1hz * sine_freq_local);
sine_hdelta_table[0] = (uint32_t)((float)freq_time_delta_1hz * sine_freq_local);
sine_hdelta_table[1] = (uint32_t)((float)freq_time_delta_1hz * sine_freq_local);
sine_hdelta_table[2] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 2) * AUDIO_INHAM_2);
sine_hdelta_table[3] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 3) * AUDIO_INHAM_3);
sine_hdelta_table[4] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 4) * AUDIO_INHAM_4);
sine_hdelta_table[5] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 5) * AUDIO_INHAM_5);
sine_hdelta_table[6] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 6) * AUDIO_INHAM_6);
sine_hdelta_table[7] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 7) * AUDIO_INHAM_7);
sine_hdelta_table[8] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 8) * AUDIO_INHAM_8);
sine_hdelta_table[9] = (uint32_t)((( (float)freq_time_delta_1hz * sine_freq_local) * 9) * AUDIO_INHAM_9);
while(true) // While loop operates inside of write-pin timing for paired *PFS_P106PFS_BY operations
{
// R_IOPORT_PinWrite(&g_ioport_ctrl, LED_PIN, BSP_IO_LEVEL_HIGH); // 590nS to set high
// *PFS_P106PFS_BY = 0x05; // 83nS to set high
time_out = SSIE_MAX_TIME;
// err = R_SSI_WriteRead(&g_i2s_ctrl, g_src_buff, g_dest_buff, SSIE_BUFF_SIZE);
// err = R_SSI_Write(&g_i2s_ctrl, g_src_buff, SSIE_BUFF_SIZE);
// while ((I2S_EVENT_IDLE != g_i2s_event) || ((time_out--) > 0));
if((*SSIE0_SSIFSR & ~((uint32_t)0x1 << SSIFSR_TDE)) == (uint32_t)0x0)
{
*PFS_P106PFS_BY = 0x05; // 83nS to set high
#ifdef COMPLEX_SINE
// *SSIE0_SSIFTDR = sine_output_table[0]; // Load previous loops calculated values
// *SSIE0_SSIFTDR = sine_output_table[1];
acc_sine = sine_output_table[1] + sine_output_table[2] + sine_output_table[3] + sine_output_table[4] + sine_output_table[5] + sine_output_table[6] + sine_output_table[7] + sine_output_table[8] + sine_output_table[9];
acc_cosine = sine_output_table[0];
__asm__ ("smmulr %0, %1, %2" : "=r" (out_sine) : "r" (acc_sine), "r" (sine_amp_global));
*SSIE0_SSIFTDR = out_sine; //
__asm__ ("smmulr %0, %1, %2" : "=r" (out_cosine) : "r" (acc_cosine), "r" (sine_amp_global));
*SSIE0_SSIFTDR = out_cosine;
#else
*SSIE0_SSIFTDR = out_sine; // Load previous loops calculated values
*SSIE0_SSIFTDR = out_cosine;
#endif
#ifdef INHARMONICITY
sine_freq_table[0] = freq_time_accumulate += freq_time_delta;
sine_freq_table[1] = freq_time_1st_acc += sine_hdelta_table[1];
sine_freq_table[2] = freq_time_2nd_acc += sine_hdelta_table[2];
sine_freq_table[3] = freq_time_3rd_acc += sine_hdelta_table[3];
sine_freq_table[4] = freq_time_4th_acc += sine_hdelta_table[4];
sine_freq_table[5] = freq_time_5th_acc += sine_hdelta_table[5];
sine_freq_table[6] = freq_time_6th_acc += sine_hdelta_table[6];
sine_freq_table[7] = freq_time_7th_acc += sine_hdelta_table[7];
sine_freq_table[8] = freq_time_8th_acc += sine_hdelta_table[8];
sine_freq_table[9] = freq_time_9th_acc += sine_hdelta_table[9];
#else
sine_freq_table[0] = freq_time_accumulate += freq_time_delta;
sine_freq_table[1] = freq_time_1st_acc += freq_time_delta;
sine_freq_table[2] = freq_time_2nd_acc += (freq_time_delta * 2);
sine_freq_table[3] = freq_time_3rd_acc += (freq_time_delta * 3);
sine_freq_table[4] = freq_time_4th_acc += (freq_time_delta * 4);
sine_freq_table[5] = freq_time_5th_acc += (freq_time_delta * 5);
sine_freq_table[6] = freq_time_6th_acc += (freq_time_delta * 6);
sine_freq_table[7] = freq_time_7th_acc += (freq_time_delta * 7);
sine_freq_table[8] = freq_time_8th_acc += (freq_time_delta * 8);
sine_freq_table[9] = freq_time_9th_acc += (freq_time_delta * 9);
#endif
int32_t angle, sum, p1, p2, p3, p5, p7, p9, p11, term;
#ifdef COMPLEX_SINE
uint8_t sine_gen_count;
for(sine_gen_count = 0; sine_gen_count < SINE_GEN_SLOTS; sine_gen_count++)
{
freq_gen_sine = sine_freq_table[sine_gen_count];
if (freq_gen_sine >= 0xC0000000u || freq_gen_sine < 0x40000000u)
{
angle = (int32_t)freq_gen_sine; // valid from -90 to +90 degrees
}
else
{
angle = (int32_t)(0x7FFFFFFFu - freq_gen_sine);
}
term = angle << 1;
__asm__ ("smmulr %0, %1, %2" : "=r" (p1) : "r" (term), "r" (1686629713));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p1), "r" (p1));
p2 = term << 3;
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p2), "r" (p1));
p3 = term << 3;
term = p1 << 1;
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (term), "r" (p3), "r" (1431655765));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p3), "r" (p2));
p5 = term << 1;
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p5), "r" (286331153));
__asm__ ("smmulr %0, %1, %2" : "=r" (p7) : "r" (p5), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p7), "r" (54539267));
#ifdef SINE_24_BITS
__asm__ ("smmulr %0, %1, %2" : "=r" (p9) : "r" (p7), "r" (p2));
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p9), "r" (6059919));
__asm__ ("smmulr %0, %1, %2" : "=r" (p11) : "r" (p9), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p11), "r" (440721));
#endif
result_taylor_sine = sum << 1;
sine_amp_local = (int)((float)AUDIO_MAX_AMPLITUDE * sine_amp_table[sine_gen_count]);
__asm__ ("smmulr %0, %1, %2" : "=r" (out_sine) : "r" (result_taylor_sine), "r" (sine_amp_local));
sine_output_table[sine_gen_count] = out_sine;
}
#else
if (freq_time_accumulate >= 0xC0000000u || freq_time_accumulate < 0x40000000u)
{
angle = (int32_t)freq_time_accumulate; // valid from -90 to +90 degrees
}
else
{
angle = (int32_t)(0x7FFFFFFFu - freq_time_accumulate);
}
term = angle << 1;
__asm__ ("smmulr %0, %1, %2" : "=r" (p1) : "r" (term), "r" (1686629713));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p1), "r" (p1));
p2 = term << 3;
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p2), "r" (p1));
p3 = term << 3;
term = p1 << 1;
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (term), "r" (p3), "r" (1431655765));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p3), "r" (p2));
p5 = term << 1;
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p5), "r" (286331153));
__asm__ ("smmulr %0, %1, %2" : "=r" (p7) : "r" (p5), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p7), "r" (54539267));
__asm__ ("smmulr %0, %1, %2" : "=r" (p9) : "r" (p7), "r" (p2));
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p9), "r" (6059919));
__asm__ ("smmulr %0, %1, %2" : "=r" (p11) : "r" (p9), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p11), "r" (440721));
result_taylor_sine = sum << 1;
__asm__ ("smmulr %0, %1, %2" : "=r" (out_sine) : "r" (result_taylor_sine), "r" (sine_amp_local));
// *SSIE0_SSIFTDR = out_sine; // Output value at start of loop
freq_time_cosine = freq_time_accumulate + 0x40000000;
if (freq_time_cosine >= 0xC0000000u || freq_time_cosine < 0x40000000u)
{
angle = (int32_t)freq_time_cosine; // valid from -90 to +90 degrees
}
else
{
angle = (int32_t)(0x7FFFFFFFu - freq_time_cosine);
}
term = angle << 1;
__asm__ ("smmulr %0, %1, %2" : "=r" (p1) : "r" (term), "r" (1686629713));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p1), "r" (p1));
p2 = term << 3;
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p2), "r" (p1));
p3 = term << 3;
term = p1 << 1;
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (term), "r" (p3), "r" (1431655765));
__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p3), "r" (p2));
p5 = term << 1;
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p5), "r" (286331153));
__asm__ ("smmulr %0, %1, %2" : "=r" (p7) : "r" (p5), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p7), "r" (54539267));
__asm__ ("smmulr %0, %1, %2" : "=r" (p9) : "r" (p7), "r" (p2));
__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p9), "r" (6059919));
__asm__ ("smmulr %0, %1, %2" : "=r" (p11) : "r" (p9), "r" (p2));
__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p11), "r" (440721));
result_taylor_cosine = sum << 1;
__asm__ ("smmulr %0, %1, %2" : "=r" (out_cosine) : "r" (result_taylor_cosine), "r" (sine_amp_local));
// *SSIE0_SSIFTDR = out_cosine; // Output value at start of loop
#endif
}
else
{
*PFS_P106PFS_BY = 0x04; // 83nS to clear low
}
// R_IOPORT_PinWrite(&g_ioport_ctrl, LED_PIN, BSP_IO_LEVEL_LOW); // 670nS to set low - (includes the while() execution?)
// *PFS_P106PFS_BY = 0x04; // 83nS to clear low
}
}
// https://renesas.github.io/fsp/group___i2_s___a_p_i.html
/*******************************************************************************************************************//**
* @brief User defined SSI callback
* @param[in] p_args
* @return None
**********************************************************************************************************************/
void i2s_callback(i2s_callback_args_t *p_args)
{
// if( NULL != p_args)
// {
if(I2S_EVENT_TX_EMPTY == p_args->event)
{
*PFS_P106PFS_BY = 0x05; // 83nS to set high
// g_i2s_event = p_args->event; // capture callback event for validating the i2s transfer event
*SSIE0_SSIFTDR_HA = 0x000A;
*SSIE0_SSIFTDR_HA = 0x0005;
*PFS_P106PFS_BY = 0x04; // 83nS to clear low
}
else if(I2S_EVENT_IDLE == p_args->event)
{
*PFS_P106PFS_BY = 0x05; // 83nS to set high
}
// }
}
/*******************************************************************************************************************//**
* @brief Close SSI module
* @param[in] None
* @return None
**********************************************************************************************************************/
static void deinit_ssi(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Close SSI Module */
err = R_SSI_Close(&g_i2s_ctrl);
/* Handle error */
if (FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n R_SSI_Close API Failed \r\n");
}
}
/*******************************************************************************************************************//**
* @brief Close GPT module
* @param[in] None
* @return None
**********************************************************************************************************************/
static void deinit_gpt(void)
{
fsp_err_t err = FSP_SUCCESS;
/* Close GPT module */
err = R_GPT_Close(&g_timer_ctrl);
/* Handle error */
if (FSP_SUCCESS != err)
{
APP_ERR_PRINT("\r\n R_SSI_Close API Failed \r\n");
}
}
/*******************************************************************************************************************//**
* This function is called at various points during the startup process. This implementation uses the event that is
* called right before main() to set up the pins.
*
* @param[in] event Where at in the start up process the code is currently at
**********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
if (BSP_WARM_START_POST_C == event)
{
/* C runtime environment and system clocks are setup. */
/* Configure pins. */
R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg);
}
}
/*
void usb_setup(void)
{
g_usb_on_usb.open(&g_basic0_ctrl, &g_basic0_cfg);
}
void usb_print(const char* s)
{
g_usb_on_usb.write(&g_basic0_ctrl, (uint8_t*)s, (uint32_t)strlen(s), USB_CLASS_PCDC);
usb_wait_write_complete();
}
void usb_wait_write_complete(void)
{
usb_status_t usb_write_event = USB_STATUS_NONE;
int32_t timeout_count = UINT16_MAX;
fsp_err_t err = FSP_SUCCESS;
usb_event_info_t event_info;
do
{
g_usb_on_usb.eventGet(&event_info, &usb_write_event);
--timeout_count;
if(0 > timeout_count)
{
timeout_count = 0;
break;
}
}
while(USB_STATUS_WRITE_COMPLETE != usb_write_event);
}
*/
/*******************************************************************************************************************//**
* @} (end defgroup SSI_EP)
**********************************************************************************************************************/