添加热敏打印机调试功能

This commit is contained in:
admin
2026-02-27 16:39:54 +08:00
parent 2b6bcc83dc
commit 46a800c499
10 changed files with 951 additions and 35 deletions

View File

@@ -23,14 +23,21 @@
#endif
#if CONFIG_TQ_KEY_PRINT_BOOST_ACTIVE_HIGH
#define BOOST_ON_LEVEL 1
#define BOOST_OFF_LEVEL 0
#define BOOST_DEFAULT_ACTIVE_HIGH 1
#else
#define BOOST_ON_LEVEL 0
#define BOOST_OFF_LEVEL 1
#define BOOST_DEFAULT_ACTIVE_HIGH 0
#endif
#define ADC_RAW_MAX 4095
#define DEBUG_SHIFT_CLOCK_US_MIN 1
#define DEBUG_SHIFT_CLOCK_US_MAX 50
#define DEBUG_LATCH_PULSE_US_MIN 1
#define DEBUG_LATCH_PULSE_US_MAX 50
static const uint16_t k_default_shift_clock_high_us = 5;
static const uint16_t k_default_shift_clock_low_us = 5;
static const uint16_t k_default_latch_pulse_us = 1;
static const bool k_default_strobe_active_high = true;
static const char *TAG = "direct_printer";
static const uint8_t k_print_yield_lines = 8;
@@ -46,6 +53,7 @@ typedef struct {
bool initialized;
bool connected;
uint8_t motor_phase;
platform_direct_debug_config_t debug;
SemaphoreHandle_t lock;
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_handle_t adc2_handle;
@@ -57,6 +65,31 @@ static direct_printer_state_t s_state;
static const uint8_t k_motor_step_table[4] = {0x05, 0x09, 0x0A, 0x06};
static int boost_on_level_locked(void) {
return s_state.debug.boost_active_high ? 1 : 0;
}
static int boost_off_level_locked(void) {
return s_state.debug.boost_active_high ? 0 : 1;
}
static int strobe_active_level_locked(void) {
return s_state.debug.strobe_active_high ? 1 : 0;
}
static int strobe_idle_level_locked(void) {
return s_state.debug.strobe_active_high ? 0 : 1;
}
static void set_debug_defaults_locked(void) {
memset(&s_state.debug, 0, sizeof(s_state.debug));
s_state.debug.shift_clock_high_us = k_default_shift_clock_high_us;
s_state.debug.shift_clock_low_us = k_default_shift_clock_low_us;
s_state.debug.latch_pulse_us = k_default_latch_pulse_us;
s_state.debug.strobe_active_high = k_default_strobe_active_high;
s_state.debug.boost_active_high = BOOST_DEFAULT_ACTIVE_HIGH != 0;
}
static bool is_gpio_valid(int gpio_num) {
return gpio_num >= 0;
}
@@ -118,9 +151,10 @@ static esp_err_t config_input_pin(int gpio_num, bool pull_up, const char *name)
}
static void set_stb_level_locked(int level) {
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_12_PIN, level);
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_34_PIN, level);
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_56_PIN, level);
int out_level = level ? strobe_active_level_locked() : strobe_idle_level_locked();
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_12_PIN, out_level);
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_34_PIN, out_level);
set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_56_PIN, out_level);
}
static void motor_apply_pattern_locked(uint8_t pattern) {
@@ -141,13 +175,19 @@ static void safe_drive_off_locked(bool keep_boost_on) {
set_gpio_level_if_valid(CONFIG_TQ_PRINT_LAT_PIN, 1);
motor_off_locked();
if (!keep_boost_on) {
set_gpio_level_if_valid(CONFIG_TQ_KEY_PRINT_PIN, BOOST_OFF_LEVEL);
set_gpio_level_if_valid(CONFIG_TQ_KEY_PRINT_PIN, boost_off_level_locked());
}
}
static void pulse_latch_locked(void) {
uint16_t latch_us = s_state.debug.latch_pulse_us;
if (latch_us < DEBUG_LATCH_PULSE_US_MIN) {
latch_us = DEBUG_LATCH_PULSE_US_MIN;
} else if (latch_us > DEBUG_LATCH_PULSE_US_MAX) {
latch_us = DEBUG_LATCH_PULSE_US_MAX;
}
set_gpio_level_if_valid(CONFIG_TQ_PRINT_LAT_PIN, 0);
esp_rom_delay_us(1);
esp_rom_delay_us(latch_us);
set_gpio_level_if_valid(CONFIG_TQ_PRINT_LAT_PIN, 1);
}
@@ -174,15 +214,28 @@ static void motor_step_once_locked(uint16_t step_delay_us) {
}
static void write_line_bits_locked(const uint8_t *line, size_t line_bytes) {
uint16_t high_us = s_state.debug.shift_clock_high_us;
uint16_t low_us = s_state.debug.shift_clock_low_us;
if (high_us < DEBUG_SHIFT_CLOCK_US_MIN) {
high_us = DEBUG_SHIFT_CLOCK_US_MIN;
} else if (high_us > DEBUG_SHIFT_CLOCK_US_MAX) {
high_us = DEBUG_SHIFT_CLOCK_US_MAX;
}
if (low_us < DEBUG_SHIFT_CLOCK_US_MIN) {
low_us = DEBUG_SHIFT_CLOCK_US_MIN;
} else if (low_us > DEBUG_SHIFT_CLOCK_US_MAX) {
low_us = DEBUG_SHIFT_CLOCK_US_MAX;
}
for (size_t i = 0; i < line_bytes; ++i) {
uint8_t byte = line[i];
for (int bit = 7; bit >= 0; --bit) {
int pixel = ((byte >> bit) & 0x01) ? 1 : 0;
set_gpio_level_if_valid(CONFIG_TQ_SPI_SHARED_MOSI_PIN, pixel);
set_gpio_level_if_valid(CONFIG_TQ_SPI_SHARED_CLK_PIN, 1);
esp_rom_delay_us(1);
esp_rom_delay_us(high_us);
set_gpio_level_if_valid(CONFIG_TQ_SPI_SHARED_CLK_PIN, 0);
esp_rom_delay_us(1);
esp_rom_delay_us(low_us);
}
}
}
@@ -423,17 +476,18 @@ esp_err_t platform_direct_printer_init(void) {
if (s_state.lock == NULL) {
return ESP_ERR_NO_MEM;
}
set_debug_defaults_locked();
esp_err_t err = ESP_OK;
err = config_output_pin(CONFIG_TQ_PRINT_STB_12_PIN, 0, "print_stb12");
err = config_output_pin(CONFIG_TQ_PRINT_STB_12_PIN, strobe_idle_level_locked(), "print_stb12");
if (err != ESP_OK) {
return err;
}
err = config_output_pin(CONFIG_TQ_PRINT_STB_34_PIN, 0, "print_stb34");
err = config_output_pin(CONFIG_TQ_PRINT_STB_34_PIN, strobe_idle_level_locked(), "print_stb34");
if (err != ESP_OK) {
return err;
}
err = config_output_pin(CONFIG_TQ_PRINT_STB_56_PIN, 0, "print_stb56");
err = config_output_pin(CONFIG_TQ_PRINT_STB_56_PIN, strobe_idle_level_locked(), "print_stb56");
if (err != ESP_OK) {
return err;
}
@@ -466,7 +520,7 @@ esp_err_t platform_direct_printer_init(void) {
if (err != ESP_OK) {
return err;
}
err = config_output_pin(CONFIG_TQ_KEY_PRINT_PIN, BOOST_OFF_LEVEL, "print_boost");
err = config_output_pin(CONFIG_TQ_KEY_PRINT_PIN, boost_off_level_locked(), "print_boost");
if (err != ESP_OK) {
return err;
}
@@ -527,7 +581,7 @@ esp_err_t platform_direct_printer_connect(uint32_t timeout_ms) {
}
if (!s_state.connected) {
set_gpio_level_if_valid(CONFIG_TQ_KEY_PRINT_PIN, BOOST_ON_LEVEL);
set_gpio_level_if_valid(CONFIG_TQ_KEY_PRINT_PIN, boost_on_level_locked());
vTaskDelay(pdMS_TO_TICKS(10));
safe_drive_off_locked(true);
s_state.connected = true;
@@ -577,6 +631,103 @@ esp_err_t platform_direct_printer_get_sensors(platform_printer_sensors_t *out_se
return ESP_OK;
}
esp_err_t platform_direct_printer_get_debug_config(platform_direct_debug_config_t *out_config) {
#if !CONFIG_TQ_DIRECT_PRINTER_ENABLE
(void)out_config;
return ESP_ERR_NOT_SUPPORTED;
#else
if (out_config == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t init_rc = platform_direct_printer_init();
if (init_rc != ESP_OK) {
return init_rc;
}
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(500)) != pdTRUE) {
return ESP_ERR_TIMEOUT;
}
*out_config = s_state.debug;
xSemaphoreGive(s_state.lock);
return ESP_OK;
#endif
}
esp_err_t platform_direct_printer_set_debug_config(const platform_direct_debug_config_t *config,
bool reset_defaults,
char *err,
size_t err_len) {
#if !CONFIG_TQ_DIRECT_PRINTER_ENABLE
(void)config;
(void)reset_defaults;
write_err(err, err_len, "direct backend disabled");
return ESP_ERR_NOT_SUPPORTED;
#else
if (config == NULL && !reset_defaults) {
write_err(err, err_len, "invalid args");
return ESP_ERR_INVALID_ARG;
}
esp_err_t init_rc = platform_direct_printer_init();
if (init_rc != ESP_OK) {
write_err(err, err_len, "direct backend not initialized");
return init_rc;
}
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) != pdTRUE) {
write_err(err, err_len, "direct printer lock timeout");
return ESP_ERR_TIMEOUT;
}
if (reset_defaults) {
set_debug_defaults_locked();
}
if (config != NULL) {
if (config->shift_clock_high_us < DEBUG_SHIFT_CLOCK_US_MIN ||
config->shift_clock_high_us > DEBUG_SHIFT_CLOCK_US_MAX ||
config->shift_clock_low_us < DEBUG_SHIFT_CLOCK_US_MIN ||
config->shift_clock_low_us > DEBUG_SHIFT_CLOCK_US_MAX) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "shift clock us out of range (1..50)");
return ESP_ERR_INVALID_ARG;
}
if (config->latch_pulse_us < DEBUG_LATCH_PULSE_US_MIN ||
config->latch_pulse_us > DEBUG_LATCH_PULSE_US_MAX) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "latch pulse us out of range (1..50)");
return ESP_ERR_INVALID_ARG;
}
if (config->override_strobe_on_us != 0 &&
(config->override_strobe_on_us < 100 || config->override_strobe_on_us > 10000)) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "strobe_on_us must be 0 or 100..10000");
return ESP_ERR_INVALID_ARG;
}
if (config->override_strobe_interval_us > 10000) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "strobe_interval_us must be 0..10000");
return ESP_ERR_INVALID_ARG;
}
if (config->override_motor_step_us != 0 &&
(config->override_motor_step_us < 100 || config->override_motor_step_us > 20000)) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "motor_step_us must be 0 or 100..20000");
return ESP_ERR_INVALID_ARG;
}
if (config->override_steps_per_line > 8) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "steps_per_line must be 0..8");
return ESP_ERR_INVALID_ARG;
}
s_state.debug = *config;
}
safe_drive_off_locked(s_state.connected);
xSemaphoreGive(s_state.lock);
return ESP_OK;
#endif
}
esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *request,
char *err,
size_t err_len) {
@@ -610,19 +761,6 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
timeout_ms = runtime_policy_direct_printer_operation_timeout_ms();
}
const uint16_t strobe_on_us = (request->strobe_on_time_us > 0)
? request->strobe_on_time_us
: runtime_policy_direct_printer_strobe_on_us();
const uint16_t strobe_interval_us = (request->strobe_interval_us > 0)
? request->strobe_interval_us
: runtime_policy_direct_printer_strobe_interval_us();
const uint16_t motor_step_us = (request->motor_step_delay_us > 0)
? request->motor_step_delay_us
: runtime_policy_direct_printer_motor_step_us();
const uint8_t steps_per_line = (request->motor_steps_per_line > 0)
? request->motor_steps_per_line
: runtime_policy_direct_printer_steps_per_line();
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) != pdTRUE) {
write_err(err, err_len, "direct printer lock timeout");
return ESP_ERR_TIMEOUT;
@@ -634,6 +772,32 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
return ESP_ERR_INVALID_STATE;
}
uint16_t strobe_on_us = (request->strobe_on_time_us > 0)
? request->strobe_on_time_us
: runtime_policy_direct_printer_strobe_on_us();
uint16_t strobe_interval_us = (request->strobe_interval_us > 0)
? request->strobe_interval_us
: runtime_policy_direct_printer_strobe_interval_us();
uint16_t motor_step_us = (request->motor_step_delay_us > 0)
? request->motor_step_delay_us
: runtime_policy_direct_printer_motor_step_us();
uint8_t steps_per_line = (request->motor_steps_per_line > 0)
? request->motor_steps_per_line
: runtime_policy_direct_printer_steps_per_line();
if (s_state.debug.override_strobe_on_us > 0) {
strobe_on_us = s_state.debug.override_strobe_on_us;
}
if (s_state.debug.override_strobe_interval_us > 0) {
strobe_interval_us = s_state.debug.override_strobe_interval_us;
}
if (s_state.debug.override_motor_step_us > 0) {
motor_step_us = s_state.debug.override_motor_step_us;
}
if (s_state.debug.override_steps_per_line > 0) {
steps_per_line = s_state.debug.override_steps_per_line;
}
esp_err_t rc = ESP_OK;
if (!request->ignore_precheck) {
rc = precheck_before_print_locked(err, err_len);
@@ -725,6 +889,9 @@ esp_err_t platform_direct_printer_gap_move(uint32_t timeout_ms, char *err, size_
esp_err_t rc = ESP_OK;
uint16_t steps = runtime_policy_direct_printer_gap_steps();
uint16_t step_delay_us = runtime_policy_direct_printer_motor_step_us();
if (s_state.debug.override_motor_step_us > 0) {
step_delay_us = s_state.debug.override_motor_step_us;
}
platform_printer_sensors_t sensors = {0};
sample_sensors_locked(&sensors);