I am using nRF5415-DK and SDK v3.2.2
I want to generate a sine wave using PWM and TIMER. The PWM repeat duty cycle method has limitations, so I am using a timer to trigger the PWM at the required rate.TIMER compare event is connected to the NEXTSTEP task in PWM.
The required sine wave frequency is 1.5kHz with 9-bit resolution and 128 duty cycle values.
I am not able to generate the required frequency. I can only generate upto 250Hz.
#define SINE_RES_BITS (9U)
#define SINE_SAMPLES_COUNT (128U)
#define PWM_TOP_VAL (1 << SINE_RES_BITS) // 512
const float sineLookupTable[SINE_SAMPLES_COUNT] = {
0.0000, 0.5025, 1.0037, 1.5025, 1.9977, 2.4881, 2.9725, 3.4498, 3.9187, 4.3782, 4.8271, 5.2644, 5.6890, 6.1000, 6.4962, 6.8768, 7.2408, 7.5873, 7.9156, 8.2248,
8.5142, 8.7831, 9.0309, 9.2569, 9.4605, 9.6414, 9.7991, 9.9331, 10.0432, 10.1292, 10.1907, 10.2277, 10.2400, 10.2277, 10.1907, 10.1292, 10.0432, 9.9331, 9.7991, 9.6414,
9.4605, 9.2569, 9.0309, 8.7831, 8.5142, 8.2248, 7.9156, 7.5873, 7.2408, 6.8768, 6.4962, 6.1000, 5.6890, 5.2644, 4.8271, 4.3782, 3.9187, 3.4498, 2.9725, 2.4881,
1.9977, 1.5025, 1.0037, 0.5025, 0.0000, -0.5025, -1.0037, -1.5025, -1.9977, -2.4881, -2.9725, -3.4498, -3.9187, -4.3782, -4.8271, -5.2644, -5.6890, -6.1000, -6.4962, -6.8768,
-7.2408, -7.5873, -7.9156, -8.2248, -8.5142, -8.7831, -9.0309, -9.2569, -9.4605, -9.6414, -9.7991, -9.9331, -10.0432, -10.1292, -10.1907, -10.2277, -10.2400, -10.2277, -10.1907, -10.1292,
-10.0432, -9.9331, -9.7991, -9.6414, -9.4605, -9.2569, -9.0309, -8.7831, -8.5142, -8.2248, -7.9156, -7.5873, -7.2408, -6.8768, -6.4962, -6.1000, -5.6890, -5.2644, -4.8271, -4.3782,
-3.9187, -3.4498, -2.9725, -2.4881, -1.9977, -1.5025, -1.0037, -0.5025
};
#define SINEBASELINE (PWM_TOP_VAL / 2)
static nrfx_pwm_t m_pwm_ch1 = NRFX_PWM_INSTANCE(NRF_PWM_INST_GET(20));
static nrfx_timer_t m_timer_ch1 = NRFX_TIMER_INSTANCE(NRF_TIMER20);
static nrf_pwm_values_common_t sine_table[SINE_SAMPLES_COUNT];
static void Scale_Up_BufferF(const float bufferSource[], nrf_pwm_values_common_t bufferResult[], uint8_t val)
{
uint16_t i;
for (i = 0U; i < SINE_SAMPLES_COUNT; i++) {
bufferResult[i] = SINEBASELINE+round(bufferSource[i] * val);
}
}
void sinegen_startTrigger(uint32_t pin_no, uint32_t target_hz)
{
if (target_hz == 0) return;
Scale_Up_BufferF(sineLookupTable, sine_table, 10);
nrfx_pwm_config_t config = NRFX_PWM_DEFAULT_CONFIG(pin_no,
NRF_PWM_PIN_NOT_CONNECTED,
NRF_PWM_PIN_NOT_CONNECTED,
NRF_PWM_PIN_NOT_CONNECTED);
config.top_value = PWM_TOP_VAL;
config.base_clock = NRF_PWM_CLK_16MHz;
config.load_mode = NRF_PWM_LOAD_COMMON;
config.count_mode = NRF_PWM_MODE_UP;
config.step_mode = NRF_PWM_STEP_TRIGGERED;
nrfx_pwm_init(&m_pwm_ch1, &config, NULL, NULL);
/* ---------------- TIMER CONFIG ---------------- */
uint32_t sample_rate = target_hz * SINE_SAMPLES_COUNT;
nrfx_timer_config_t timer_cfg =NRFX_TIMER_DEFAULT_CONFIG(16000000);
nrfx_timer_init(&m_timer_ch1, &timer_cfg, NULL);
uint32_t ticks = 16000000U / sample_rate;
// uint32_t ticks = nrfx_timer_us_to_ticks(&m_timer_ch1,4);
nrfx_timer_extended_compare(&m_timer_ch1, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,false);
/* ---------------- PPI CONFIG ---------------- */
nrfx_err_t err;
/* Declare variables used to hold the (D)PPI channel number */
nrfx_gppi_handle_t gppi_handle_update;
/* Trigger task to update the duty cycle */
err = nrfx_gppi_conn_alloc( nrfx_timer_compare_event_address_get(&m_timer_ch1, NRF_TIMER_CC_CHANNEL0),nrfx_pwm_task_address_get(&m_pwm_ch1, NRF_PWM_TASK_NEXTSTEP), &gppi_handle_update);
if (err != 0) {
// LOG_ERR("nrfx_gppi_conn_alloc error: %08x", err);
return;
}
/* Enable (D)PPI channel */
nrfx_gppi_conn_enable(gppi_handle_update);
/* ---------------- START PWM PLAYBACK ---------------- */
nrf_pwm_sequence_t const seq =
{
.values.p_common = sine_table,
.length = SINE_SAMPLES_COUNT,
.repeats = 0,
.end_delay = 0
};
nrfx_pwm_simple_playback(&m_pwm_ch1, &seq, 1, NRFX_PWM_FLAG_LOOP);
nrfx_timer_enable(&m_timer_ch1);
}