/** * Marlin 3D Printer Firmware * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #pragma once /** * Pins Debugging for HC32 * * - NUMBER_PINS_TOTAL * - MULTI_NAME_PAD * - getPinByIndex(index) * - printPinNameByIndex(index) * - getPinIsDigitalByIndex(index) * - digitalPinToAnalogIndex(pin) * - getValidPinMode(pin) * - isValidPin(pin) * - isAnalogPin(pin) * - digitalRead_mod(pin) * - pwm_status(pin) * - printPinPWM(pin) * - printPinPort(pin) * - printPinNumber(pin) * - printPinAnalog(pin) */ #include "../../inc/MarlinConfig.h" #include "fastio.h" #include #ifndef BOARD_NR_GPIO_PINS #error "Expected BOARD_NR_GPIO_PINS not found." #endif #define NUM_DIGITAL_PINS BOARD_NR_GPIO_PINS #define NUMBER_PINS_TOTAL BOARD_NR_GPIO_PINS #define isValidPin(P) IS_GPIO_PIN(P) // Note: pin_array is defined in `Marlin/src/pins/pinsDebug.h`, and since this file is included // after it, it is available in this file as well. #define getPinByIndex(x) pin_t(pin_array[x].pin) #define digitalRead_mod(P) extDigitalRead(P) #define printPinNumber(P) do{ sprintf_P(buffer, PSTR("%3hd "), int16_t(P)); SERIAL_ECHO(buffer); }while(0) #define printPinAnalog(P) do{ sprintf_P(buffer, PSTR(" (A%2d) "), digitalPinToAnalogIndex(P)); SERIAL_ECHO(buffer); }while(0) #define printPinNameByIndex(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0) #define MULTI_NAME_PAD 21 // Space needed to be pretty if not first name assigned to a pin // // Pins that will cause a hang / reset / disconnect in M43 Toggle and Watch utils // #ifndef M43_NEVER_TOUCH // Don't touch any of the following pins: // - Host serial pins, and // - Pins that could be connected to oscillators (see datasheet, Table 2.1): // - XTAL = PH0, PH1 // - XTAL32 = PC14, PC15 #define IS_HOST_USART_PIN(Q) (Q == BOARD_USART2_TX_PIN || Q == BOARD_USART2_RX_PIN) #define IS_OSC_PIN(Q) (Q == PH0 || Q == PH1 || Q == PC14 || Q == PC15) #define M43_NEVER_TOUCH(Q) (IS_HOST_USART_PIN(Q) || IS_OSC_PIN(Q)) #endif int8_t digitalPinToAnalogIndex(const pin_t pin) { if (!isValidPin(pin)) return -1; const int8_t adc_channel = int8_t(PIN_MAP[pin].adc_info.channel); return pin_t(adc_channel); } bool isAnalogPin(pin_t pin) { if (!isValidPin(pin)) return false; if (PIN_MAP[pin].adc_info.channel != ADC_PIN_INVALID) return _GET_MODE(pin) == INPUT_ANALOG && !M43_NEVER_TOUCH(pin); return false; } bool getValidPinMode(const pin_t pin) { return isValidPin(pin) && !IS_INPUT(pin); } bool getPinIsDigitalByIndex(const int16_t index) { const pin_t pin = getPinByIndex(index); return (!isAnalogPin(pin)); } /** * @brief print pin PWM status * @return true if pin is currently a PWM pin, false otherwise */ bool pwm_status(const pin_t pin) { // Get timer assignment for pin timera_config_t *unit; en_timera_channel_t channel; en_port_func_t port_function; if (!timera_get_assignment(pin, unit, channel, port_function) || unit == nullptr) { // No pwm pin or no unit assigned return false; } // A pin that is PWM output is: // - Assigned to a timerA unit (tested above) // - Unit is initialized // - Channel is active // - PinMode is OUTPUT_PWM return timera_is_unit_initialized(unit) && timera_is_channel_active(unit, channel) && getPinMode(pin) == OUTPUT_PWM; } void printPinPWM(const pin_t pin) { // Get timer assignment for pin timera_config_t *unit; en_timera_channel_t channel; en_port_func_t port_function; if (!timera_get_assignment(pin, unit, channel, port_function) || unit == nullptr) return; // No pwm pin or no unit assigned // Print timer assignment of pin, eg. "TimerA1Ch2 Func4" SERIAL_ECHOPGM("TimerA", TIMERA_REG_TO_X(unit->peripheral.register_base), "Ch", TIMERA_CHANNEL_TO_X(channel), " Func", int(port_function)); SERIAL_ECHO_SP(3); // 3 spaces // Print timer unit state, eg. "1/16 PERAR=1234" OR "N/A" if (timera_is_unit_initialized(unit)) { // Unit initialized, print // - Timer clock divider // - Timer period value (PERAR) const uint8_t clock_divider = timera_clk_div_to_n(unit->state.base_init->enClkDiv); const uint16_t period = TIMERA_GetPeriodValue(unit->peripheral.register_base); SERIAL_ECHOPGM("1/", clock_divider, " PERAR=", period); } else { // Unit not initialized SERIAL_ECHOPGM("N/A"); return; } SERIAL_ECHO_SP(3); // 3 spaces // Print timer channel state, e.g. "CMPAR=1234" OR "N/A" if (timera_is_channel_active(unit, channel)) { // Channel active, print // - Channel compare value const uint16_t compare = TIMERA_GetCompareValue(unit->peripheral.register_base, channel); SERIAL_ECHOPGM("CMPAR=", compare); } else { // Channel inactive SERIAL_ECHOPGM("N/A"); } } void printPinPort(pin_t pin) { const char port = 'A' + char(pin >> 4); // Pin div 16 const int16_t gbit = PIN_MAP[pin].bit_pos; char buffer[8]; sprintf_P(buffer, PSTR("P%c%hd "), port, gbit); if (gbit < 10) { SERIAL_CHAR(' '); } SERIAL_ECHO(buffer); }