Skip to content

Commit

Permalink
Merge pull request #685 from Paciente8159/itp-loop-as-task
Browse files Browse the repository at this point in the history
Interpolator loop feed as a task
  • Loading branch information
Paciente8159 committed May 3, 2024
2 parents 026261b + 4729e15 commit 24f4a44
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 62 deletions.
11 changes: 9 additions & 2 deletions uCNC/cnc_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,14 +486,21 @@ extern "C"
// #define FORCE_SOFT_POLLING

/**
* Runs a check for state change inside the scheduler. This is a failsafe
* check to pin ISR checking The value sets the frequency of this safety
* Runs a check for state change inside the RTC ISR/task. This is a failsafe
* check monitor the pins in a regular interval. The value sets the frequency of this safety
* check that is executed every 2^(CTRL_SCHED_CHECK) milliseconds. A
* negative value will disable this feature. The maximum is 7
* */

#define CTRL_SCHED_CHECK 4

/**
* EXPERIMENTAL! Uncomment to enable itp step generation to run inside the RTC ISR/task.
* This ensures ITP starving prevention. Usually this will be executed at the same sample
* rate as the interpolator with an upper bound of 1Khz and a lower bound of 3Hz
* */
// #define ENABLE_ITP_FEED_TASK

/**
* Uncomment to invert Emergency stop button
* */
Expand Down
122 changes: 69 additions & 53 deletions uCNC/src/cnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ typedef struct
volatile int8_t alarm;
} cnc_state_t;

static bool cnc_lock_itp = false;
static uint8_t cnc_lock_itp;
static cnc_state_t cnc_state;
bool cnc_status_report_lock;

Expand Down Expand Up @@ -111,15 +111,15 @@ void cnc_init(void)
#endif
cnc_state.loop_state = LOOP_STARTUP_RESET;
// initializes all systems
mcu_init(); // mcu
mcu_io_reset(); // add custom logic to set pins initial state
mcu_init(); // mcu
mcu_io_reset(); // add custom logic to set pins initial state
io_enable_steppers(~g_settings.step_enable_invert); // disables steppers at start
io_disable_probe(); // forces probe isr disabling
serial_init(); // serial
mod_init(); // modules
settings_init(); // settings
itp_init(); // interpolator
planner_init(); // motion planner
io_disable_probe(); // forces probe isr disabling
serial_init(); // serial
mod_init(); // modules
settings_init(); // settings
itp_init(); // interpolator
planner_init(); // motion planner
#if TOOL_COUNT > 0
tool_init();
#endif
Expand Down Expand Up @@ -233,6 +233,7 @@ uint8_t cnc_parse_cmd(void)

bool cnc_dotasks(void)
{

// run io basic tasks
cnc_io_dotasks();

Expand All @@ -244,13 +245,8 @@ bool cnc_dotasks(void)
return false;
}

if (cnc_has_alarm())
{
return !cnc_get_exec_state(EXEC_KILL);
}

// µCNC already in error loop. No point in sending the alarms
if (cnc_state.loop_state >= LOOP_FAULT)
if (cnc_has_alarm() || (cnc_state.loop_state >= LOOP_FAULT))
{
return !cnc_get_exec_state(EXEC_KILL);
}
Expand All @@ -261,17 +257,19 @@ bool cnc_dotasks(void)
return !cnc_get_exec_state(EXEC_INTERLOCKING_FAIL);
}

#ifdef ENABLE_TOOL_PID_CONTROLLER
// run the tool pid update
tool_pid_update();
#endif

#ifndef ENABLE_ITP_FEED_TASK
if (!cnc_lock_itp)
{
cnc_lock_itp = true;
itp_run();
cnc_lock_itp = false;
}
#endif

#ifdef ENABLE_TOOL_PID_CONTROLLER
// run the tool pid update
tool_pid_update();
#endif

#ifdef ENABLE_MAIN_LOOP_MODULES
EVENT_INVOKE(cnc_dotasks, NULL);
Expand Down Expand Up @@ -306,7 +304,7 @@ void cnc_store_motion(void)
cnc_clear_exec_state(EXEC_HOLD);
}

cnc_lock_itp = false;
cnc_lock_itp = 0;
#endif
}

Expand Down Expand Up @@ -339,47 +337,62 @@ void cnc_restore_motion(void)
{
cnc_clear_exec_state(EXEC_HOLD);
}
cnc_lock_itp = false;
cnc_lock_itp = 0;
#endif
}

// this function is executed every millisecond
#ifndef DISABLE_RTC_CODE
MCU_CALLBACK void mcu_rtc_cb(uint32_t millis)
{
static bool running = false;

if (!running)
mcu_enable_global_isr();
uint8_t mls = (uint8_t)(0xff & millis);
if ((mls & CTRL_SCHED_CHECK_MASK) == CTRL_SCHED_CHECK_VAL)
{
running = true;
mcu_enable_global_isr();
#ifndef ENABLE_RT_PROBE_CHECKING
mcu_probe_changed_cb();
#endif
#ifndef ENABLE_RT_LIMITS_CHECKING
mcu_limits_changed_cb();
#endif
mcu_controls_changed_cb();
#if (DIN_ONCHANGE_MASK != 0 && ENCODERS < 1)
// extra call in case generic inputs are running with ISR disabled. Encoders need propper ISR to work.
mcu_inputs_changed_cb();
#endif
}

#ifdef ENABLE_MAIN_LOOP_MODULES
if (!cnc_get_exec_state(EXEC_ALARM))
#ifdef ENABLE_ITP_FEED_TASK
static uint8_t itp_feed_counter = (uint8_t)CLAMP(1, (1000 / INTERPOLATOR_FREQ), 255);
mls = itp_feed_counter;
if (!cnc_lock_itp && !mls--)
{
cnc_lock_itp = 1;
if ((cnc_state.loop_state == LOOP_RUNNING) && (cnc_state.alarm == EXEC_ALARM_NOALARM) && !cnc_get_exec_state(EXEC_INTERLOCKING_FAIL))
{
EVENT_INVOKE(rtc_tick, NULL);
itp_run();
}
mls = (uint8_t)CLAMP(1, (1000 / INTERPOLATOR_FREQ), 255);
cnc_lock_itp = 0;
}

itp_feed_counter = mls;
#endif

// checks any limit or control input state change (every 16ms)
#if (!defined(FORCE_SOFT_POLLING) && CTRL_SCHED_CHECK >= 0)
uint8_t mls = (uint8_t)(0xff & millis);
if ((mls & CTRL_SCHED_CHECK_MASK) == CTRL_SCHED_CHECK_VAL)
{
mcu_limits_changed_cb();
mcu_controls_changed_cb();
}
#ifdef ENABLE_MAIN_LOOP_MODULES
if (!cnc_get_exec_state(EXEC_ALARM))
{
EVENT_INVOKE(rtc_tick, NULL);
}
#endif

#if ASSERT_PIN(ACTIVITY_LED)
// this blinks aprox. once every 1024ms
if (!(millis & (0x200 - 1)))
{
io_toggle_output(ACTIVITY_LED);
}
#endif
mcu_disable_global_isr();
running = false;
// this blinks aprox. once every 1024ms
if (!(millis & (0x200 - 1)))
{
io_toggle_output(ACTIVITY_LED);
}
#endif
}
#endif

Expand Down Expand Up @@ -606,7 +619,7 @@ void cnc_delay_ms(uint32_t milliseconds)
} while (mcu_millis() < milliseconds);
}

//executes delay (resumes earlier on error)
// executes delay (resumes earlier on error)
void cnc_dwell_ms(uint32_t milliseconds)
{
milliseconds += mcu_millis();
Expand Down Expand Up @@ -658,7 +671,7 @@ void cnc_call_rt_command(uint8_t command)
case CMD_CODE_FEED_HOLD:
SETFLAG(cnc_state.exec_state, EXEC_HOLD);
__FALL_THROUGH__
case CMD_CODE_JOG_CANCEL:
case CMD_CODE_JOG_CANCEL:
if (cnc_get_exec_state(EXEC_JOG))
{
SETFLAG(cnc_state.exec_state, EXEC_HOLD);
Expand Down Expand Up @@ -732,7 +745,8 @@ void cnc_exec_rt_commands(void)
if (command)
{
// clear all but report. report is handled in cnc_io_dotasks
__ATOMIC__{
__ATOMIC__
{
cnc_state.rt_cmd = RT_CMD_CLEAR;
}
if (CHECKFLAG(command, RT_CMD_RESET))
Expand All @@ -756,9 +770,11 @@ void cnc_exec_rt_commands(void)

if (CHECKFLAG(command, RT_CMD_JOG_CANCEL))
{
while(serial_available()){
while (serial_available())
{
char c = serial_getc();
if(c == EOL){
if (c == EOL)
{
protocol_send_error(STATUS_JOG_CANCELED);
}
}
Expand Down Expand Up @@ -1014,7 +1030,7 @@ bool cnc_check_interlocking(void)
}
mc_sync_position();
parser_sync_position();
// flush all pending commands and motions
// flush all pending commands and motions
mc_flush_pending_motion();
// homing will be cleared inside homing cycle
cnc_clear_exec_state(EXEC_HOLD | EXEC_JOG);
Expand All @@ -1039,7 +1055,7 @@ static void cnc_io_dotasks(void)
mcu_dotasks();
mcu_limits_changed_cb();
mcu_controls_changed_cb();

#if (DIN_ONCHANGE_MASK != 0 && ENCODERS < 1)
// extra call in case generic inputs are running with ISR disabled. Encoders need propper ISR to work.
mcu_inputs_changed_cb();
Expand Down
4 changes: 4 additions & 0 deletions uCNC/src/cnc_hal_config_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,10 @@ extern "C"
#define CTRL_SCHED_CHECK_VAL (1 << (CTRL_SCHED_CHECK))
#endif

#ifdef DISABLE_RTC_CODE
#undef ENABLE_ITP_FEED_TASK
#endif

#ifndef BRESENHAM_16BIT
typedef uint32_t step_t;
#define MAX_STEPS_PER_LINE_BITS (32 - (2 + DSS_MAX_OVERSAMPLING))
Expand Down
5 changes: 0 additions & 5 deletions uCNC/src/core/interpolator.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@
#define INTERPOLATOR_BUFFER_SIZE 5 // number of windows in the buffer
#endif

// sets the sample frequency for the Riemann sum integral
#ifndef INTERPOLATOR_FREQ
#define INTERPOLATOR_FREQ 100
#endif

#define INTERPOLATOR_DELTA_T (1.0f / INTERPOLATOR_FREQ)
// determines the size of the maximum riemann sample that can be performed taking in acount the maximum allowable step rate
#define INTERPOLATOR_DELTA_CONST_T (MIN((1.0f / INTERPOLATOR_BUFFER_SIZE), ((float)(0xFFFF >> DSS_MAX_OVERSAMPLING) / (float)F_STEP_MAX)))
Expand Down
5 changes: 5 additions & 0 deletions uCNC/src/core/interpolator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ extern "C"
#define ITP_STEP_MODE_REALTIME 2
#define ITP_STEP_MODE_SYNC 4

// sets the sample frequency for the Riemann sum integral
#ifndef INTERPOLATOR_FREQ
#define INTERPOLATOR_FREQ 100
#endif

// contains data of the block being executed by the pulse routine
// this block has the necessary data to execute the Bresenham line algorithm
typedef struct itp_blk_
Expand Down
4 changes: 2 additions & 2 deletions uCNC/src/hal/boards/avr/avr.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ build_flags = ${common.build_flags} -mcall-prologues -mrelax -flto -fno-fat-lto-
extends = common_avr
board = uno
;saves a bit of flash
build_flags = ${common_avr.build_flags} -D DISABLE_SETTINGS_MODULES -D DISABLE_MULTISTREAM_SERIAL -D DISABLE_RTC_CODE
build_flags = ${common_avr.build_flags} -D DISABLE_SETTINGS_MODULES -D DISABLE_MULTISTREAM_SERIAL

[atmega328pb]
extends = common_avr
board = Atmega328PB
;saves a bit of flash
platform_packages=platformio/framework-arduino-avr-minicore@^3.0.0
build_flags = ${common_avr.build_flags} -D DISABLE_SETTINGS_MODULES -D DISABLE_MULTISTREAM_SERIAL -D DISABLE_RTC_CODE
build_flags = ${common_avr.build_flags} -D DISABLE_SETTINGS_MODULES -D DISABLE_MULTISTREAM_SERIAL

[env:AVR-UNO]
extends = atmega328p
Expand Down

0 comments on commit 24f4a44

Please sign in to comment.