Skip to content

Commit

Permalink
Merge branch 'feature/sdm_c' into feature/docs_update
Browse files Browse the repository at this point in the history
  • Loading branch information
ed-xmos committed Nov 28, 2023
2 parents fa28fce + 1fe88c9 commit c77ef19
Show file tree
Hide file tree
Showing 51 changed files with 1,940 additions and 479 deletions.
1 change: 1 addition & 0 deletions .xmos_ignore_source_check
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
python/sw_pll/pll_calc.py
register_setup.h
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
lib_sw_pll library change log
=============================

2.0.0
-----

* ADDED: Double integral term to controller
* ADDED: Sigma Delta Modulator option for PLL
* CHANGED: Refactored Python model into analogous objects

1.1.0
-----

Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ if(PROJECT_IS_TOP_LEVEL)
add_subdirectory(modules/fwk_io)
add_subdirectory(tests/test_app)
add_subdirectory(tests/test_app_low_level_api)
add_subdirectory(tests/test_app_sdm_dco)
add_subdirectory(tests/test_app_sdm_ctrl)
endif()
14 changes: 13 additions & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,26 @@ pipeline {
}
zip archive: true, zipFile: "build.zip", dir: "build"
zip archive: true, zipFile: "tests.zip", dir: "tests/bin"
archiveArtifacts artifacts: "tests/bin/timing-report.txt", allowEmptyArchive: false
archiveArtifacts artifacts: "tests/bin/timing-report*.txt", allowEmptyArchive: false

junit 'tests/results.xml'
}
}
}
}
}
stage('Python examples'){
steps {
dir('lib_sw_pll') {
withVenv {
catchError {
sh './tools/ci/do-model-examples.sh'
}
archiveArtifacts artifacts: "python/sw_pll/*.png,python/sw_pll/*.wav", allowEmptyArchive: false
}
}
}
}
}
post {
cleanup {
Expand Down
2 changes: 1 addition & 1 deletion doc/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "XMOS SW PLL",
"project": "SW PLL",
"version": "1.1.0",
"version": "2.0.0",
"architectures": {
"xcore.ai": ["15.2.x"]
}
Expand Down
4 changes: 2 additions & 2 deletions doc/substitutions.rst-inc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.. |full_version_str| replace:: v1.1.0
.. |tools_version| replace:: 15.2.x
.. |full_version_str| replace:: v2.0.0
.. |tools_version| replace:: 15.2.1
.. |I2S| replace:: I\ :sup:`2`\ S
.. |I2C| replace:: I\ :sup:`2`\ C
.. |trademark| replace:: :sup:`TM`
Expand Down
1 change: 1 addition & 0 deletions examples/examples.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
include(${CMAKE_CURRENT_LIST_DIR}/simple/simple.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/simple_sdm/simple_sdm.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/i2s_slave/i2s_slave.cmake)
3 changes: 2 additions & 1 deletion examples/i2s_slave/src/i2s_slave_sw_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ void sw_pll_test(void){
sw_pll_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
BCLKS_PER_LRCLK,
Expand All @@ -189,7 +190,7 @@ void sw_pll_test(void){
PPM_RANGE);


printf("i_windup_limit: %ld\n", sw_pll.i_windup_limit);
printf("i_windup_limit: %ld\n", sw_pll.pi_state.i_windup_limit);


// Initialise app_data
Expand Down
60 changes: 60 additions & 0 deletions examples/shared/src/clock_gen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include <xs1.h>
#include <stdio.h>
#include <xcore/hwtimer.h>
#include <xcore/port.h>

#include "sw_pll_common.h"

#define DO_CLOCKS \
printf("Ref Hz: %d\n", clock_rate >> 1); \
\
unsigned cycle_ticks_int = XS1_TIMER_HZ / clock_rate; \
unsigned cycle_ticks_remaidner = XS1_TIMER_HZ % clock_rate; \
unsigned carry = 0; \
\
period_trig += XS1_TIMER_HZ * 1; \
unsigned time_now = hwtimer_get_time(period_tmr); \
while(TIMER_TIMEAFTER(period_trig, time_now)) \
{ \
port_out(p_clock_gen, port_val); \
hwtimer_wait_until(clock_tmr, time_trig); \
time_trig += cycle_ticks_int; \
carry += cycle_ticks_remaidner; \
if(carry >= clock_rate){ \
time_trig++; \
carry -= clock_rate; \
} \
port_val ^= 1; \
time_now = hwtimer_get_time(period_tmr); \
}

void clock_gen(unsigned ref_frequency, unsigned ppm_range) // Step from - to + this
{
unsigned clock_rate = ref_frequency * 2; // Note double because we generate edges at this rate

unsigned clock_rate_low = (unsigned)(clock_rate * (1.0 - (float)ppm_range / 1000000.0));
unsigned clock_rate_high = (unsigned)(clock_rate * (1.0 + (float)ppm_range / 1000000.0));
unsigned step_size = (clock_rate_high - clock_rate_low) / 20;

printf("Sweep range: %d %d %d, step size: %d\n", clock_rate_low / 2, clock_rate / 2, clock_rate_high / 2, step_size);

hwtimer_t period_tmr = hwtimer_alloc();
unsigned period_trig = hwtimer_get_time(period_tmr);

hwtimer_t clock_tmr = hwtimer_alloc();
unsigned time_trig = hwtimer_get_time(clock_tmr);

port_t p_clock_gen = PORT_I2S_BCLK;
port_enable(p_clock_gen);
unsigned port_val = 1;

for(unsigned clock_rate = clock_rate_low; clock_rate <= clock_rate_high; clock_rate += 2 * step_size){
DO_CLOCKS
}
for(unsigned clock_rate = clock_rate_high; clock_rate > clock_rate_low; clock_rate -= 2 * step_size){
DO_CLOCKS
}
}
6 changes: 6 additions & 0 deletions examples/shared/src/clock_gen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

// Runs a task in a thread that produces a clock that sweeps a reference clock
// between + and - the ppm value specified.
void clock_gen(unsigned ref_frequency, unsigned ppm_range);
43 changes: 43 additions & 0 deletions examples/shared/src/resource_setup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include <stdio.h>
#include "resource_setup.h"

void setup_ref_and_mclk_ports_and_clocks(port_t p_mclk, xclock_t clk_mclk, port_t p_ref_clk_in, xclock_t clk_word_clk, port_t p_ref_clk_count)
{
// Create clock from mclk port and use it to clock the p_ref_clk port.
clock_enable(clk_mclk);
port_enable(p_mclk);
clock_set_source_port(clk_mclk, p_mclk);

// Clock p_ref_clk from MCLK
port_enable(p_ref_clk_in);
port_set_clock(p_ref_clk_in, clk_mclk);

clock_start(clk_mclk);

// Create clock from ref_clock_port and use it to clock the p_ref_clk_count port.
clock_enable(clk_word_clk);
clock_set_source_port(clk_word_clk, p_ref_clk_in);
port_enable(p_ref_clk_count);
port_set_clock(p_ref_clk_count, clk_word_clk);

clock_start(clk_word_clk);
}


void setup_recovered_ref_clock_output(port_t p_recovered_ref_clk, xclock_t clk_recovered_ref_clk, port_t p_mclk, unsigned divider)
{
// Connect clock block with divide to mclk
clock_enable(clk_recovered_ref_clk);
clock_set_source_port(clk_recovered_ref_clk, p_mclk);
clock_set_divide(clk_recovered_ref_clk, divider / 2);
printf("Divider: %u\n", divider);

// Output the divided mclk on a port
port_enable(p_recovered_ref_clk);
port_set_clock(p_recovered_ref_clk, clk_recovered_ref_clk);
port_set_out_clock(p_recovered_ref_clk);
clock_start(clk_recovered_ref_clk);
}
17 changes: 17 additions & 0 deletions examples/shared/src/resource_setup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include <xcore/port.h>

#pragma once

// Sets up the provided resources so that we can count PLL output clocks.
// We do this by clocking the input reference clock port with the output from the PLL
// and its internal counter is used to count the PLL clock cycles(normal timers cannot count custom clocks)
// It also sets up a dummy port clocked by the input reference to act as a timing barrier so that
// the output clock count can be precisely sampled.
void setup_ref_and_mclk_ports_and_clocks(port_t p_mclk, xclock_t clk_mclk, port_t p_ref_clk_in, xclock_t clk_word_clk, port_t p_ref_clk_count);

// Sets up a divided version of the PLL output so it can visually be compared (eg. on a DSO)
// with the input reference clock to the PLL
void setup_recovered_ref_clock_output(port_t p_recovered_ref_clk, xclock_t clk_recovered_ref_clk, port_t p_mclk, unsigned divider);
8 changes: 5 additions & 3 deletions examples/simple/simple.cmake
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#**********************
# Gather Sources
#**********************
file(GLOB_RECURSE APP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.c ${CMAKE_CURRENT_LIST_DIR}/src/*.xc)
set(APP_INCLUDES
${CMAKE_CURRENT_LIST_DIR}/src
file(GLOB_RECURSE APP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.c
${CMAKE_CURRENT_LIST_DIR}/src/*.xc
${CMAKE_CURRENT_LIST_DIR}/../shared/src/*.c )
set(APP_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/src
${CMAKE_CURRENT_LIST_DIR}/../shared/src
)

#**********************
Expand Down
25 changes: 16 additions & 9 deletions examples/simple/src/main.xc
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@

#include <platform.h>
#include <xs1.h>
#include <stdlib.h>

extern void sw_pll_test(void);
extern void clock_gen(void);
extern "C" {
#include "clock_gen.h"
}


int main(void)
{
par
{
on tile[0]: par {
}
on tile[1]: par {
sw_pll_test();
clock_gen();
par
{
on tile[0]: par {
}
on tile[1]: par {
sw_pll_test();
{
clock_gen(48000, 150);
exit(0);
}
}
}
}
return 0;
}
93 changes: 2 additions & 91 deletions examples/simple/src/simple_sw_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <xs1.h>

#include "sw_pll.h"
#include "resource_setup.h"

#define MCLK_FREQUENCY 12288000
#define REF_FREQUENCY 48000
Expand All @@ -21,44 +22,6 @@
//Found solution: IN 24.000MHz, OUT 12.288018MHz, VCO 3047.43MHz, RD 4, FD 507.905 (m = 19, n = 21), OD 2, FOD 31, ERR +1.50ppm
#include "fractions.h"

void setup_ref_and_mclk_ports_and_clocks(port_t p_mclk, xclock_t clk_mclk, port_t p_ref_clk_in, xclock_t clk_word_clk, port_t p_ref_clk_count)
{
// Create clock from mclk port and use it to clock the p_ref_clk port.
clock_enable(clk_mclk);
port_enable(p_mclk);
clock_set_source_port(clk_mclk, p_mclk);

// Clock p_ref_clk from MCLK
port_enable(p_ref_clk_in);
port_set_clock(p_ref_clk_in, clk_mclk);

clock_start(clk_mclk);

// Create clock from ref_clock_port and use it to clock the p_ref_clk_count port.
clock_enable(clk_word_clk);
clock_set_source_port(clk_word_clk, p_ref_clk_in);
port_enable(p_ref_clk_count);
port_set_clock(p_ref_clk_count, clk_word_clk);

clock_start(clk_word_clk);
}


void setup_recovered_ref_clock_output(port_t p_recovered_ref_clk, xclock_t clk_recovered_ref_clk, port_t p_mclk, unsigned divider)
{
// Connect clock block with divide to mclk
clock_enable(clk_recovered_ref_clk);
clock_set_source_port(clk_recovered_ref_clk, p_mclk);
clock_set_divide(clk_recovered_ref_clk, divider / 2);
printf("Divider: %u\n", divider);

// Output the divided mclk on a port
port_enable(p_recovered_ref_clk);
port_set_clock(p_recovered_ref_clk, clk_recovered_ref_clk);
port_set_out_clock(p_recovered_ref_clk);
clock_start(clk_recovered_ref_clk);
}

void sw_pll_test(void){

// Declare mclk and refclk resources and connect up
Expand All @@ -78,6 +41,7 @@ void sw_pll_test(void){
sw_pll_init(&sw_pll,
SW_PLL_15Q16(0.0),
SW_PLL_15Q16(1.0),
SW_PLL_15Q16(0.0),
CONTROL_LOOP_COUNT,
PLL_RATIO,
0,
Expand Down Expand Up @@ -111,56 +75,3 @@ void sw_pll_test(void){
}
}
}

#define DO_CLOCKS \
printf("Ref Hz: %d\n", clock_rate >> 1); \
\
unsigned cycle_ticks_int = XS1_TIMER_HZ / clock_rate; \
unsigned cycle_ticks_remaidner = XS1_TIMER_HZ % clock_rate; \
unsigned carry = 0; \
\
period_trig += XS1_TIMER_HZ * 1; \
unsigned time_now = hwtimer_get_time(period_tmr); \
while(TIMER_TIMEAFTER(period_trig, time_now)) \
{ \
port_out(p_clock_gen, port_val); \
hwtimer_wait_until(clock_tmr, time_trig); \
time_trig += cycle_ticks_int; \
carry += cycle_ticks_remaidner; \
if(carry >= clock_rate){ \
time_trig++; \
carry -= clock_rate; \
} \
port_val ^= 1; \
time_now = hwtimer_get_time(period_tmr); \
}

void clock_gen(void)
{
unsigned clock_rate = REF_FREQUENCY * 2; // Note double because we generate edges at this rate
unsigned ppm_range = 150; // Step from - to + this

unsigned clock_rate_low = (unsigned)(clock_rate * (1.0 - (float)ppm_range / 1000000.0));
unsigned clock_rate_high = (unsigned)(clock_rate * (1.0 + (float)ppm_range / 1000000.0));
unsigned step_size = (clock_rate_high - clock_rate_low) / 20;

printf("Sweep range: %d %d %d, step size: %d\n", clock_rate_low / 2, clock_rate / 2, clock_rate_high / 2, step_size);

hwtimer_t period_tmr = hwtimer_alloc();
unsigned period_trig = hwtimer_get_time(period_tmr);

hwtimer_t clock_tmr = hwtimer_alloc();
unsigned time_trig = hwtimer_get_time(clock_tmr);

port_t p_clock_gen = PORT_I2S_BCLK;
port_enable(p_clock_gen);
unsigned port_val = 1;

for(unsigned clock_rate = clock_rate_low; clock_rate <= clock_rate_high; clock_rate += 2 * step_size){
DO_CLOCKS
}
for(unsigned clock_rate = clock_rate_high; clock_rate > clock_rate_low; clock_rate -= 2 * step_size){
DO_CLOCKS
}
exit(0);
}
Loading

0 comments on commit c77ef19

Please sign in to comment.