mirror of
https://github.com/grblHAL/core.git
synced 2026-02-05 16:50:16 +08:00
Build 20240921
Added generic HAL timer API and function for getting which G65 parameter words were supplied.
This commit is contained in:
16
changelog.md
16
changelog.md
@@ -1,5 +1,21 @@
|
||||
## grblHAL changelog
|
||||
|
||||
<a name="20240921">Build 20240921
|
||||
|
||||
Core:
|
||||
|
||||
* Added generic HAL timer API and function for getting which `G65` parameter words were supplied.
|
||||
|
||||
Networking:
|
||||
|
||||
* Made parsing of HTTP header keywords case insensitive. Ref. [issue #11](https://github.com/grblHAL/Plugin_networking/issues/11).
|
||||
|
||||
SD card (macros):
|
||||
|
||||
* Added inbuilt `G65` macro `P3` for getting and setting NGC numerical parameters, typical use case will be for indexed access. Ref. [discussion #309 comment](https://github.com/grblHAL/core/discussions/309#discussioncomment-10710468).
|
||||
|
||||
---
|
||||
|
||||
<a name="20240907">Build 20240907
|
||||
|
||||
Core:
|
||||
|
||||
@@ -187,6 +187,7 @@ typedef enum {
|
||||
Output_MOSI,
|
||||
Output_SPICLK,
|
||||
Output_SPICS,
|
||||
Output_FlashCS,
|
||||
Output_SdCardCS,
|
||||
Input_SdCardDetect,
|
||||
Output_SPIRST,
|
||||
@@ -385,6 +386,7 @@ PROGMEM static const pin_name_t pin_names[] = {
|
||||
{ .function = Output_MOSI, .name = "MOSI" },
|
||||
{ .function = Output_SPICLK, .name = "SPI CLK" },
|
||||
{ .function = Output_SPICS, .name = "SPI CS" },
|
||||
{ .function = Output_FlashCS, .name = "Flash CS" },
|
||||
{ .function = Output_SdCardCS, .name = "SD card CS" },
|
||||
{ .function = Input_SdCardDetect, .name = "SD card detect" },
|
||||
{ .function = Output_SPIRST, .name = "SPI reset" },
|
||||
|
||||
12
gcode.c
12
gcode.c
@@ -509,11 +509,17 @@ static status_code_t read_parameter (char *line, uint_fast8_t *char_counter, flo
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#endif // NGC_EXPRESSIONS_ENABLE
|
||||
|
||||
#if NGC_PARAMETERS_ENABLE
|
||||
|
||||
static parameter_words_t g65_words = {0};
|
||||
|
||||
parameter_words_t gc_get_g65_arguments (void)
|
||||
{
|
||||
return g65_words;
|
||||
}
|
||||
|
||||
bool gc_modal_state_restore (gc_modal_t *copy)
|
||||
{
|
||||
bool ok = false;
|
||||
@@ -950,6 +956,7 @@ status_code_t gc_execute_block (char *block)
|
||||
if(!is_user_mcode && isnanf(value))
|
||||
FAIL(Status_BadNumberFormat); // [Expected word value]
|
||||
|
||||
g65_words.value = 0;
|
||||
#else
|
||||
|
||||
if((letter < 'A' && letter != '$') || letter > 'Z')
|
||||
@@ -2435,11 +2442,14 @@ status_code_t gc_execute_block (char *block)
|
||||
|
||||
while(gc_block.words.value) {
|
||||
if(gc_block.words.value & 0x1 && gc_value_ptr[idx].value) switch(gc_value_ptr[idx].type) {
|
||||
|
||||
case ValueType_Float:
|
||||
g65_words.value |= (1 << idx);
|
||||
ngc_param_set((ngc_param_id_t)idx, *(float *)gc_value_ptr[idx].value);
|
||||
break;
|
||||
|
||||
case ValueType_UInt32:
|
||||
g65_words.value |= (1 << idx);
|
||||
ngc_param_set((ngc_param_id_t)idx, (float)*(uint32_t *)gc_value_ptr[idx].value);
|
||||
break;
|
||||
|
||||
|
||||
5
gcode.h
5
gcode.h
@@ -238,8 +238,8 @@ typedef enum {
|
||||
UserMCode_Generic3 = 103, //!< 103 - For private use only
|
||||
UserMCode_Generic4 = 104, //!< 104 - For private use only
|
||||
OpenPNP_GetADCReading = 105, //!< 105 - M105
|
||||
Fan_On = 106, //!< 106 - M106
|
||||
Fan_Off = 107, //!< 107 - M107
|
||||
Fan_On = 106, //!< 106 - M106, Marlin format
|
||||
Fan_Off = 107, //!< 107 - M107, Marlin format
|
||||
OpenPNP_GetCurrentPosition = 114, //!< 114 - M114
|
||||
OpenPNP_FirmwareInfo = 115, //!< 115 - M115
|
||||
Trinamic_DebugReport = 122, //!< 122 - M122, Marlin format
|
||||
@@ -685,6 +685,7 @@ void gc_set_tool_offset (tool_offset_mode_t mode, uint_fast8_t idx, int32_t offs
|
||||
plane_t *gc_get_plane_data (plane_t *plane, plane_select_t select);
|
||||
|
||||
#if NGC_PARAMETERS_ENABLE
|
||||
parameter_words_t gc_get_g65_arguments (void);
|
||||
bool gc_modal_state_restore (gc_modal_t *copy);
|
||||
#endif
|
||||
|
||||
|
||||
2
grbl.h
2
grbl.h
@@ -42,7 +42,7 @@
|
||||
#else
|
||||
#define GRBL_VERSION "1.1f"
|
||||
#endif
|
||||
#define GRBL_BUILD 20240907
|
||||
#define GRBL_BUILD 20240921
|
||||
|
||||
#define GRBL_URL "https://github.com/grblHAL"
|
||||
|
||||
|
||||
84
hal.h
84
hal.h
@@ -302,6 +302,13 @@ typedef void (*stepper_output_step_ptr)(axes_signals_t step_outbits, axes_signal
|
||||
*/
|
||||
typedef axes_signals_t (*stepper_get_ganged_ptr)(bool auto_squared);
|
||||
|
||||
/*! \brief Pointer to function for claiming/releasing motor(s) from/to normal step/dir signalling.
|
||||
|
||||
\param axis_id a \a the axis to claim/release motor(s) for.
|
||||
\param claim \a true to claim a motor(s), \a false to release.
|
||||
*/
|
||||
typedef void (*stepper_claim_motor_ptr)(uint_fast8_t axis_id, bool claim);
|
||||
|
||||
/*! \brief Pointer to callback function for outputting the next direction and step pulse signals. _Set by the core on startup._
|
||||
|
||||
To be called by the driver from the main stepper interrupt handler (when the timer times out).
|
||||
@@ -318,6 +325,7 @@ typedef struct {
|
||||
stepper_pulse_start_ptr pulse_start; //!< Handler for starting outputting direction signals and a step pulse. Called from interrupt context.
|
||||
stepper_interrupt_callback_ptr interrupt_callback; //!< Callback for informing about the next step pulse to output. _Set by the core at startup._
|
||||
stepper_get_ganged_ptr get_ganged; //!< Optional handler getting which axes are configured for ganging or auto squaring.
|
||||
stepper_claim_motor_ptr claim_motor; //!< Optional handler for claiming/releasing motor(s) from normal step/dir control.
|
||||
stepper_output_step_ptr output_step; //!< Optional handler for outputting a single step pulse. _Experimental._ Called from interrupt context.
|
||||
motor_iterator_ptr motor_iterator; //!< Optional handler iteration over motor vs. axis mappings. Required for the motors plugin (Trinamic drivers).
|
||||
} stepper_ptrs_t;
|
||||
@@ -484,6 +492,73 @@ typedef struct {
|
||||
*/
|
||||
typedef bool (*irq_claim_ptr)(irq_type_t irq, uint_fast8_t id, irq_callback_ptr callback);
|
||||
|
||||
/************
|
||||
* Timers *
|
||||
************/
|
||||
|
||||
typedef void *hal_timer_t; //!< Timer handle, actual type defined by driver implementation.
|
||||
|
||||
typedef enum {
|
||||
Timer_16bit = 0,
|
||||
Timer_32bit,
|
||||
Timer_64bit
|
||||
} timer_resolution_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t value; //!< All bitmap flags.
|
||||
struct {
|
||||
uint8_t periodic :1, //!<
|
||||
up :1, //!< Timer supports upcounting
|
||||
comp1 :1, //!< Timer supports compare interrupt 0
|
||||
comp2 :1; //!< Timer supports compare interrupt 1
|
||||
};
|
||||
} timer_cap_t;
|
||||
|
||||
typedef void (*timer_irq_handler_ptr)(void *context);
|
||||
|
||||
typedef struct {
|
||||
void *context; //!< Pointer to data to be passed on to the interrupt handlers
|
||||
bool single_shot; //!< Set to true if timer is single shot
|
||||
timer_irq_handler_ptr timeout_callback; //!< Pointer to main timeout callback
|
||||
uint32_t irq0; //!< Compare value for compare interrupt 0
|
||||
timer_irq_handler_ptr irq0_callback; //!< Pointer to compare interrupt 0 callback
|
||||
uint32_t irq1; //!< Compare value for compare interrupt 10
|
||||
timer_irq_handler_ptr irq1_callback; //!< Pointer to compare interrupt 1 callback
|
||||
} timer_cfg_t;
|
||||
|
||||
/*! \brief Pointer to function for claiming a timer.
|
||||
\param cap pointer to a \a timer_cap_t struct containing the required capabilities.
|
||||
\param timebase timebase in ns.
|
||||
\returns a \a hal_timer_t pointer if successful, \a NULL if not.
|
||||
*/
|
||||
typedef hal_timer_t (*timer_claim_ptr)(timer_cap_t cap, uint32_t timebase);
|
||||
|
||||
/*! \brief Pointer to function for configuring a timer.
|
||||
\param timer a \a hal_timer_t pointer.
|
||||
\param cfg pointer to a \a timer_cfg_t struct.
|
||||
\returns \a true if successful.
|
||||
*/
|
||||
typedef bool (*timer_cfg_ptr)(hal_timer_t timer, timer_cfg_t *cfg);
|
||||
|
||||
/*! \brief Pointer to function for starting a timer.
|
||||
\param timer a \a hal_timer_t pointer.
|
||||
\param period delay in.
|
||||
\returns \a true if successful.
|
||||
*/
|
||||
typedef bool (*timer_start_ptr)(hal_timer_t timer, uint32_t period);
|
||||
|
||||
/*! \brief Pointer to function for stopping a running timer.
|
||||
\param timer a \a hal_timer_t pointer.
|
||||
\returns \a true if successful.
|
||||
*/
|
||||
typedef bool (*timer_stop_ptr)(hal_timer_t timer);
|
||||
|
||||
typedef struct {
|
||||
timer_claim_ptr claim;
|
||||
timer_cfg_ptr configure;
|
||||
timer_start_ptr start;
|
||||
timer_stop_ptr stop;
|
||||
} timer_ptrs_t;
|
||||
|
||||
/**************************
|
||||
* RTC (Real Time Clock *
|
||||
@@ -491,13 +566,13 @@ typedef bool (*irq_claim_ptr)(irq_type_t irq, uint_fast8_t id, irq_callback_ptr
|
||||
|
||||
/*! \brief Pointer to function for setting the current datetime.
|
||||
\param datetime pointer to a \a tm struct.
|
||||
\returns true if successful.
|
||||
\\returns \a true if successful.
|
||||
*/
|
||||
typedef bool (*rtc_get_datetime_ptr)(struct tm *datetime);
|
||||
|
||||
/*! \brief Pointer to function for setting the current datetime.
|
||||
\param datetime pointer to a \a tm struct.
|
||||
\returns true if successful.
|
||||
\returns \a true if successful.
|
||||
*/
|
||||
typedef bool (*rtc_set_datetime_ptr)(struct tm *datetime);
|
||||
|
||||
@@ -541,7 +616,7 @@ typedef struct {
|
||||
/*! \brief Driver setup handler.
|
||||
Called once by the core after settings has been loaded. The driver should enable MCU peripherals in the provided function.
|
||||
\param settings pointer to settings_t structure.
|
||||
\returns true if completed successfully and the driver supports the _settings->version_ number, false otherwise.
|
||||
\returns \a true if completed successfully and the driver supports the _settings->version_ number, false otherwise.
|
||||
*/
|
||||
driver_setup_ptr driver_setup;
|
||||
|
||||
@@ -595,6 +670,7 @@ typedef struct {
|
||||
settings_changed_ptr settings_changed; //!< Callback handler to be called on settings loaded or settings changed events.
|
||||
probe_ptrs_t probe; //!< Optional handlers for probe input(s).
|
||||
tool_ptrs_t tool; //!< Optional handlers for tool changes.
|
||||
timer_ptrs_t timer; //!< Optional handlers for claiming and controlling timers.
|
||||
rtc_ptrs_t rtc; //!< Optional handlers for real time clock (RTC).
|
||||
io_port_t port; //!< Optional handlers for axuillary I/O (adds support for M62-M66).
|
||||
rgb_ptr_t rgb0; //!< Optional handler for RGB output to LEDs (neopixels) or lamps.
|
||||
@@ -649,7 +725,7 @@ Then _hal.driver_setup()_ will be called so that the driver can configure the re
|
||||
|
||||
__NOTE__: This is the only driver function that is called directly from the core, all others are called via HAL function pointers.
|
||||
|
||||
\returns true if completed successfully and the driver matches the _hal.version number_, false otherwise.
|
||||
\returns \a true if completed successfully and the driver matches the _hal.version number_, \a false otherwise.
|
||||
*/
|
||||
extern bool driver_init (void);
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ extern char const *const axis_letter[];
|
||||
|
||||
typedef union {
|
||||
uint8_t mask;
|
||||
uint8_t bits;
|
||||
uint8_t value;
|
||||
struct {
|
||||
uint8_t x :1,
|
||||
|
||||
87
stepper2.c
87
stepper2.c
@@ -47,6 +47,7 @@ struct st2_motor {
|
||||
axes_signals_t axis;
|
||||
bool is_spindle;
|
||||
bool is_bound;
|
||||
bool polling;
|
||||
bool position_lost;
|
||||
volatile int64_t position; // absolute step number
|
||||
position_t ptype; //
|
||||
@@ -66,6 +67,8 @@ struct st2_motor {
|
||||
float acceleration; // acceleration steps/s^2
|
||||
axes_signals_t dir; // current direction
|
||||
uint64_t next_step;
|
||||
hal_timer_t step_inject_timer;
|
||||
foreground_task_ptr on_stopped;
|
||||
st2_motor_t *next;
|
||||
};
|
||||
|
||||
@@ -76,6 +79,8 @@ static on_set_axis_setting_unit_ptr on_set_axis_setting_unit;
|
||||
static on_setting_get_description_ptr on_setting_get_description;
|
||||
static on_reset_ptr on_reset;
|
||||
|
||||
static void motor_irq (void *context);
|
||||
|
||||
/*! \brief Calculate basic motor configuration.
|
||||
|
||||
\param motor pointer to a \a st2_motor structure.
|
||||
@@ -200,6 +205,11 @@ static const char *st2_setting_get_description (setting_id_t id)
|
||||
: (on_setting_get_description ? on_setting_get_description(id) : NULL);
|
||||
}
|
||||
|
||||
void st2_motor_register_stopped_callback (st2_motor_t *motor, foreground_task_ptr callback)
|
||||
{
|
||||
motor->on_stopped = callback;
|
||||
}
|
||||
|
||||
/*! \brief Bind and initialize a motor.
|
||||
|
||||
Binds motor 0 as a spindle.
|
||||
@@ -240,9 +250,23 @@ If \a is_spindle is set \a true then axis settings will be changed to step/rev e
|
||||
*/
|
||||
st2_motor_t *st2_motor_init (uint_fast8_t axis_idx, bool is_spindle)
|
||||
{
|
||||
st2_motor_t *motor, *new = motors;
|
||||
st2_motor_t *motor = NULL, *new = motors;
|
||||
|
||||
if((motor = calloc(sizeof(st2_motor_t), 1))) {
|
||||
if(hal.stepper.output_step && (motor = calloc(sizeof(st2_motor_t), 1))) {
|
||||
|
||||
if(hal.timer.claim && (motor->step_inject_timer = hal.timer.claim((timer_cap_t){ .periodic = Off }, 1000))) {
|
||||
timer_cfg_t step_inject_cfg = {
|
||||
.single_shot = true,
|
||||
.timeout_callback = motor_irq
|
||||
};
|
||||
step_inject_cfg.context = motor;
|
||||
hal.timer.configure(motor->step_inject_timer, &step_inject_cfg);
|
||||
} else if(hal.get_micros)
|
||||
motor->polling = true;
|
||||
else {
|
||||
free(motor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!is_spindle) {
|
||||
|
||||
@@ -417,6 +441,9 @@ bool st2_motor_move (st2_motor_t *motor, const float move, const float speed, po
|
||||
motor->step_no = 0; // step counter
|
||||
motor->next_step = hal.get_micros();
|
||||
|
||||
if(motor->step_inject_timer)
|
||||
hal.timer.start(motor->step_inject_timer, motor->delay);
|
||||
|
||||
#ifdef DEBUGOUT
|
||||
uint32_t nn = motor->n;
|
||||
float cn = motor->first_delay;
|
||||
@@ -464,17 +491,12 @@ bool st2_set_position (st2_motor_t *motor, int64_t position)
|
||||
}
|
||||
|
||||
/*! \brief Execute a move commanded by st2_motor_move().
|
||||
|
||||
This should be called from the foreground process as often as possible.
|
||||
\param motor pointer to a \a st2_motor structure.
|
||||
\returns \a true if motor is moving (steps are output), \a false if not (motion is completed).
|
||||
*/
|
||||
bool st2_motor_run (st2_motor_t *motor)
|
||||
__attribute__((always_inline)) static inline bool _motor_run (st2_motor_t *motor)
|
||||
{
|
||||
uint64_t t = hal.get_micros();
|
||||
|
||||
if(motor->state == State_Idle || t - motor->next_step < motor->delay)
|
||||
return motor->state != State_Idle;
|
||||
st2_state_t prev_state = motor->state;
|
||||
|
||||
switch(motor->state) {
|
||||
|
||||
@@ -483,7 +505,7 @@ bool st2_motor_run (st2_motor_t *motor)
|
||||
motor->denom += 4;
|
||||
motor->c64 -= (motor->c64 << 1) / motor->denom; // ramp algorithm
|
||||
motor->delay = (motor->c64 + 32768) >> 16; // round 24.16 format -> int16
|
||||
if (motor->delay < motor->min_delay) { // go to constant speed?
|
||||
if (motor->delay < motor->min_delay) { // go to constant speed?
|
||||
// motor->denom -= 6; // causes issues with speed override for infinite moves
|
||||
motor->state = motor->ptype == Stepper2_InfiniteSteps ? State_RunInfinite : State_Run;
|
||||
motor->step_down = motor->move - motor->step_no;
|
||||
@@ -540,7 +562,41 @@ bool st2_motor_run (st2_motor_t *motor)
|
||||
motor->position++;
|
||||
|
||||
motor->step_no++;
|
||||
motor->next_step = t;
|
||||
|
||||
if(motor->state == State_Idle && prev_state != State_Idle && motor->on_stopped)
|
||||
task_add_delayed(motor->on_stopped, motor, 2);
|
||||
|
||||
return motor->state != State_Idle;
|
||||
}
|
||||
|
||||
ISR_CODE static void ISR_FUNC(motor_irq)(void *context)
|
||||
{
|
||||
if(_motor_run((st2_motor_t *)context))
|
||||
hal.timer.start(((st2_motor_t *)context)->step_inject_timer, ((st2_motor_t *)context)->delay);
|
||||
else
|
||||
hal.timer.stop(((st2_motor_t *)context)->step_inject_timer);
|
||||
}
|
||||
|
||||
/*! \brief Execute a move commanded by st2_motor_move().
|
||||
|
||||
This should be called from the foreground process as often as possible
|
||||
when step output is not driven by interrupts (polling mode).
|
||||
\param motor pointer to a \a st2_motor structure.
|
||||
\returns \a true if motor is moving (steps are output), \a false if not (motion is completed).
|
||||
*/
|
||||
bool st2_motor_run (st2_motor_t *motor)
|
||||
{
|
||||
if(motor->polling && motor->state != State_Idle) {
|
||||
|
||||
uint64_t t = hal.get_micros();
|
||||
|
||||
if(t - motor->next_step >= motor->delay) {
|
||||
|
||||
_motor_run(motor);
|
||||
|
||||
motor->next_step = t;
|
||||
}
|
||||
}
|
||||
|
||||
return motor->state != State_Idle;
|
||||
}
|
||||
@@ -575,6 +631,15 @@ bool st2_motor_stop (st2_motor_t *motor)
|
||||
return motor->state != State_Idle;
|
||||
}
|
||||
|
||||
/*! \brief Check if motor is run by polling.
|
||||
\param motor pointer to a \a st2_motor structure.
|
||||
\returns \a true if motor is run by polling, \a false if not.
|
||||
*/
|
||||
bool st2_motor_poll (st2_motor_t *motor)
|
||||
{
|
||||
return motor->polling;
|
||||
}
|
||||
|
||||
/*! \brief Check if motor is running.
|
||||
\param motor pointer to a \a st2_motor structure.
|
||||
\returns \a true if motor is running, \a false if not.
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "task.h"
|
||||
|
||||
typedef enum {
|
||||
Stepper2_Steps = 0, //!< 0
|
||||
Stepper2_InfiniteSteps, //!< 1
|
||||
@@ -32,6 +34,7 @@ struct st2_motor; // members defined in stepper2.c
|
||||
typedef struct st2_motor st2_motor_t;
|
||||
|
||||
st2_motor_t *st2_motor_init (uint_fast8_t axis_idx, bool is_spindle);
|
||||
bool st2_motor_poll (st2_motor_t *motor);
|
||||
bool st2_motor_bind_spindle (uint_fast8_t axis_idx);
|
||||
float st2_get_speed (st2_motor_t *motor);
|
||||
float st2_motor_set_speed (st2_motor_t *motor, float speed);
|
||||
@@ -42,3 +45,4 @@ bool st2_motor_cruising (st2_motor_t *motor);
|
||||
bool st2_motor_stop (st2_motor_t *motor);
|
||||
int64_t st2_get_position (st2_motor_t *motor);
|
||||
bool st2_set_position (st2_motor_t *motor, int64_t position);
|
||||
void st2_motor_register_stopped_callback (st2_motor_t *motor, foreground_task_ptr callback);
|
||||
|
||||
Reference in New Issue
Block a user