c9e35004e7
I've just uploaded a major change to pinsDebug. The big change was creating an array in FLASH that contained every active pin definition. That reduced the RAM memory usage considerably but increased the FLASH usage. Creating the array requires going through the pin list twice. Rather than having two copies of it in the code I moved the list out to another file (pinsDebug_list.h) and then just did two #includes. From the user’s view they’ll see the following changes: 1. Now reports all the names assigned to a pin 2. The port is now reported in addition to the pin number. 3. When PWM0A & PWM1C share a pin, both PWMs are reported 4. More PWM/Timer info is reported One new item that may cause some concern is the usage of the LINE predefined preprocessor macro. It may not be available if the Arduino IDE goes to a different compiler. Includes support for 1284 & 1286 families. Memory usage changes when enabling PINS_DEBUGGING: ATmega2560 FLASH . without 52576 . with new 64592 . with old 62826 . new-out 12016 . old-out 10250 . new-old 1766 . RAM . without 2807 . with new 2875 . with old 3545 . new-out 68 . old-out 738 . new-old -670 ================================================================== minor changes - mostly formatting 1) added newline to end of teensyduino file 2) changed flag name from TEENSYDUINO to TEENSYDUINO_IDE. Got warnings about redefining TEENSYDUINO 3) removed some trailing spaces reduce PROGMEM size & update pin list Reduced PROGMEM usage by 1) converting often used macro to a function 2) moved as much as possible into the function This required creating two arrays of address pointers for the PWM registers. ================================================================== update with new M3, M4, M5 pin names ================================================================== report I/O status for unused/unknown pins
545 lines
17 KiB
C
545 lines
17 KiB
C
/**
|
|
* Marlin 3D Printer Firmware
|
|
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
|
*
|
|
* Based on Sprinter and grbl.
|
|
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
bool endstop_monitor_flag = false;
|
|
|
|
#define NAME_FORMAT "%-28s" // one place to specify the format of all the sources of names
|
|
// "-" left justify, "28" minimum width of name, pad with blanks
|
|
|
|
#define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(0) && ((P) <= analogInputToDigitalPin(15) || (P) <= analogInputToDigitalPin(7)))
|
|
|
|
#define AVR_ATmega2560_FAMILY (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__))
|
|
#define AVR_AT90USB1286_FAMILY (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__))
|
|
#define AVR_ATmega1284_FAMILY (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__))
|
|
|
|
/**
|
|
* This routine minimizes RAM usage by creating a FLASH resident array to
|
|
* store the pin names, pin numbers and analog/digital flag.
|
|
*
|
|
* Creating the array in FLASH is a two pass process. The first pass puts the
|
|
* name strings into FLASH. The second pass actually creates the array.
|
|
*
|
|
* Both passes use the same pin list. The list contains two macro names. The
|
|
* actual macro definitions are changed depending on which pass is being done.
|
|
*
|
|
*/
|
|
|
|
// first pass - put the name strings into FLASH
|
|
|
|
#define _ADD_PIN_2(PIN_NAME, ENTRY_NAME) static const unsigned char ENTRY_NAME[] PROGMEM = {PIN_NAME};
|
|
#define _ADD_PIN(PIN_NAME, COUNTER) _ADD_PIN_2(PIN_NAME, entry_NAME_##COUNTER)
|
|
#define REPORT_NAME_DIGITAL(NAME, COUNTER) _ADD_PIN(#NAME, COUNTER)
|
|
#define REPORT_NAME_ANALOG(NAME, COUNTER) _ADD_PIN(#NAME, COUNTER)
|
|
|
|
#line 0 // set __LINE__ to a known value for the first pass
|
|
|
|
#include "pinsDebug_list.h"
|
|
|
|
#line 59 // set __LINE__ to the correct line number or else compiler error messages don't make sense
|
|
|
|
// manually add pins that have names that are macros which don't play well with these macros
|
|
#if SERIAL_PORT == 0 && (AVR_ATmega2560_FAMILY || AVR_ATmega1284_FAMILY)
|
|
static const unsigned char RXD_NAME[] PROGMEM = {"RXD"};
|
|
static const unsigned char TXD_NAME[] PROGMEM = {"TXD"};
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// second pass - create the array
|
|
|
|
#undef _ADD_PIN_2
|
|
#undef _ADD_PIN
|
|
#undef REPORT_NAME_DIGITAL
|
|
#undef REPORT_NAME_ANALOG
|
|
|
|
#define _ADD_PIN_2( ENTRY_NAME, NAME, IS_DIGITAL) {(const char*) ENTRY_NAME, (const char*)NAME, (const char*)IS_DIGITAL},
|
|
#define _ADD_PIN( NAME, COUNTER, IS_DIGITAL) _ADD_PIN_2( entry_NAME_##COUNTER, NAME, IS_DIGITAL)
|
|
#define REPORT_NAME_DIGITAL(NAME, COUNTER) _ADD_PIN( NAME, COUNTER, (uint8_t)1)
|
|
#define REPORT_NAME_ANALOG(NAME, COUNTER) _ADD_PIN( analogInputToDigitalPin(NAME), COUNTER, 0)
|
|
|
|
|
|
const char* const pin_array[][3] PROGMEM = {
|
|
|
|
/**
|
|
* [pin name] [pin number] [is digital or analog] 1 = digital, 0 = analog
|
|
* Each entry takes up 6 bytes in FLASH:
|
|
* 2 byte pointer to location of the name string
|
|
* 2 bytes containing the pin number
|
|
* analog pin numbers were convereted to digital when the array was created
|
|
* 2 bytes containing the digital/analog bool flag
|
|
*/
|
|
|
|
// manually add pins ...
|
|
#if SERIAL_PORT == 0
|
|
#if AVR_ATmega2560_FAMILY
|
|
{RXD_NAME, 0, 1},
|
|
{TXD_NAME, 1, 1},
|
|
#elif AVR_ATmega1284_FAMILY
|
|
{RXD_NAME, 8, 1},
|
|
{TXD_NAME, 9, 1},
|
|
#endif
|
|
#endif
|
|
|
|
#line 0 // set __LINE__ to the SAME known value for the second pass
|
|
#include "pinsDebug_list.h"
|
|
|
|
}; // done populating the array
|
|
|
|
#line 109 // set __LINE__ to the correct line number or else compiler error messages don't make sense
|
|
|
|
#define n_array (sizeof (pin_array) / sizeof (const char *))/3
|
|
|
|
#if !defined(TIMER1B) // working with Teensyduino extension so need to re-define some things
|
|
#include "pinsDebug_Teensyduino.h"
|
|
#endif
|
|
|
|
|
|
#define PWM_PRINT(V) do{ sprintf(buffer, "PWM: %4d", V); SERIAL_ECHO(buffer); }while(0)
|
|
#define PWM_CASE(N,Z) \
|
|
case TIMER##N##Z: \
|
|
if (TCCR##N##A & (_BV(COM##N##Z##1) | _BV(COM##N##Z##0))) { \
|
|
PWM_PRINT(OCR##N##Z); \
|
|
return true; \
|
|
} else return false
|
|
|
|
/**
|
|
* Print a pin's PWM status.
|
|
* Return true if it's currently a PWM pin.
|
|
*/
|
|
static bool pwm_status(uint8_t pin) {
|
|
char buffer[20]; // for the sprintf statements
|
|
|
|
switch(digitalPinToTimer(pin)) {
|
|
|
|
#if defined(TCCR0A) && defined(COM0A1)
|
|
#if defined (TIMER0A)
|
|
PWM_CASE(0,A);
|
|
#endif
|
|
PWM_CASE(0,B);
|
|
#endif
|
|
|
|
#if defined(TCCR1A) && defined(COM1A1)
|
|
PWM_CASE(1,A);
|
|
PWM_CASE(1,B);
|
|
#if defined(COM1C1) && defined (TIMER1C)
|
|
PWM_CASE(1,C);
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(TCCR2A) && defined(COM2A1)
|
|
PWM_CASE(2,A);
|
|
PWM_CASE(2,B);
|
|
#endif
|
|
|
|
#if defined(TCCR3A) && defined(COM3A1)
|
|
PWM_CASE(3,A);
|
|
PWM_CASE(3,B);
|
|
#ifdef COM3C1
|
|
PWM_CASE(3,C);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef TCCR4A
|
|
PWM_CASE(4,A);
|
|
PWM_CASE(4,B);
|
|
PWM_CASE(4,C);
|
|
#endif
|
|
|
|
#if defined(TCCR5A) && defined(COM5A1)
|
|
PWM_CASE(5,A);
|
|
PWM_CASE(5,B);
|
|
PWM_CASE(5,C);
|
|
#endif
|
|
|
|
case NOT_ON_TIMER:
|
|
default:
|
|
return false;
|
|
}
|
|
SERIAL_PROTOCOLPGM(" ");
|
|
} // pwm_status
|
|
|
|
|
|
|
|
const uint8_t* const PWM_other[][3] PROGMEM = {
|
|
{&TCCR0A, &TCCR0B, &TIMSK0},
|
|
{&TCCR1A, &TCCR1B, &TIMSK1},
|
|
#if defined(TCCR2A) && defined(COM2A1)
|
|
{&TCCR2A, &TCCR2B, &TIMSK2},
|
|
#endif
|
|
#if defined(TCCR3A) && defined(COM3A1)
|
|
{&TCCR3A, &TCCR3B, &TIMSK3},
|
|
#endif
|
|
#ifdef TCCR4A
|
|
{&TCCR4A, &TCCR4B, &TIMSK4},
|
|
#endif
|
|
#if defined(TCCR5A) && defined(COM5A1)
|
|
{&TCCR5A, &TCCR5B, &TIMSK5},
|
|
#endif
|
|
};
|
|
|
|
|
|
const uint8_t* const PWM_OCR[][3] PROGMEM = {
|
|
|
|
#if defined (TIMER0A)
|
|
{&OCR0A,&OCR0B,0},
|
|
#else
|
|
{0,&OCR0B,0},
|
|
#endif
|
|
|
|
#if defined(COM1C1) && defined (TIMER1C)
|
|
{ (const uint8_t*) &OCR1A, (const uint8_t*) &OCR1B, (const uint8_t*) &OCR1C},
|
|
#else
|
|
{ (const uint8_t*) &OCR1A, (const uint8_t*) &OCR1B,0},
|
|
#endif
|
|
|
|
#if defined(TCCR2A) && defined(COM2A1)
|
|
{&OCR2A,&OCR2B,0},
|
|
#endif
|
|
|
|
#if defined(TCCR3A) && defined(COM3A1)
|
|
#if defined(COM3C1)
|
|
{ (const uint8_t*) &OCR3A, (const uint8_t*) &OCR3B, (const uint8_t*) &OCR3C},
|
|
#else
|
|
{ (const uint8_t*) &OCR3A, (const uint8_t*) &OCR3B,0},
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef TCCR4A
|
|
{ (const uint8_t*) &OCR4A, (const uint8_t*) &OCR4B, (const uint8_t*) &OCR4C},
|
|
#endif
|
|
|
|
#if defined(TCCR5A) && defined(COM5A1)
|
|
{ (const uint8_t*) &OCR5A, (const uint8_t*) &OCR5B, (const uint8_t*) &OCR5C},
|
|
#endif
|
|
};
|
|
|
|
|
|
#define TCCR_A(T) pgm_read_word(&PWM_other[T][0])
|
|
#define TCCR_B(T) pgm_read_word(&PWM_other[T][1])
|
|
#define TIMSK(T) pgm_read_word(&PWM_other[T][2])
|
|
#define CS_0 0
|
|
#define CS_1 1
|
|
#define CS_2 2
|
|
#define WGM_0 0
|
|
#define WGM_1 1
|
|
#define WGM_2 3
|
|
#define WGM_3 4
|
|
#define TOIE 0
|
|
|
|
|
|
#define OCR_VAL(T, L) pgm_read_word(&PWM_OCR[T][L])
|
|
|
|
|
|
static void err_is_counter() {
|
|
SERIAL_PROTOCOLPGM(" non-standard PWM mode");
|
|
}
|
|
static void err_is_interrupt() {
|
|
SERIAL_PROTOCOLPGM(" compare interrupt enabled ");
|
|
}
|
|
static void err_prob_interrupt() {
|
|
SERIAL_PROTOCOLPGM(" overflow interrupt enabled");
|
|
}
|
|
static void can_be_used() { SERIAL_PROTOCOLPGM(" can be used as PWM "); }
|
|
|
|
void com_print(uint8_t N, uint8_t Z) {
|
|
uint8_t *TCCRA = (uint8_t*) TCCR_A(N);
|
|
SERIAL_PROTOCOLPGM(" COM");
|
|
SERIAL_PROTOCOLCHAR(N + '0');
|
|
switch(Z) {
|
|
case 'A' :
|
|
SERIAL_PROTOCOLPAIR("A: ", ((*TCCRA & (_BV(7) | _BV(6))) >> 6));
|
|
break;
|
|
case 'B' :
|
|
SERIAL_PROTOCOLPAIR("B: ", ((*TCCRA & (_BV(5) | _BV(4))) >> 4));
|
|
break;
|
|
case 'C' :
|
|
SERIAL_PROTOCOLPAIR("C: ", ((*TCCRA & (_BV(3) | _BV(2))) >> 2));
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void timer_prefix(uint8_t T, char L, uint8_t N){ // T - timer L - pwm n - WGM bit layout
|
|
char buffer[20]; // for the sprintf statements
|
|
uint8_t *TCCRB = (uint8_t*) TCCR_B(T);
|
|
uint8_t *TCCRA = (uint8_t*) TCCR_A(T);
|
|
uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
|
|
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
|
|
|
|
SERIAL_PROTOCOLPGM(" TIMER");
|
|
SERIAL_PROTOCOLCHAR(T + '0');
|
|
SERIAL_PROTOCOLCHAR(L);
|
|
SERIAL_PROTOCOLPGM(" ");
|
|
|
|
if (N == 3) {
|
|
uint8_t *OCRVAL8 = (uint8_t*) OCR_VAL(T, L - 'A');
|
|
PWM_PRINT(*OCRVAL8);
|
|
}
|
|
else {
|
|
uint16_t *OCRVAL16 = (uint16_t*) OCR_VAL(T, L - 'A');
|
|
PWM_PRINT(*OCRVAL16);
|
|
}
|
|
SERIAL_PROTOCOLPAIR(" WGM: ", WGM);
|
|
com_print(T,L);
|
|
SERIAL_PROTOCOLPAIR(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
|
|
|
|
SERIAL_PROTOCOLPGM(" TCCR");
|
|
SERIAL_PROTOCOLCHAR(T + '0');
|
|
SERIAL_PROTOCOLPAIR("A: ", *TCCRA);
|
|
|
|
SERIAL_PROTOCOLPGM(" TCCR");
|
|
SERIAL_PROTOCOLCHAR(T + '0');
|
|
SERIAL_PROTOCOLPAIR("B: ", *TCCRB);
|
|
|
|
uint8_t *TMSK = (uint8_t*) TIMSK(T);
|
|
SERIAL_PROTOCOLPGM(" TIMSK");
|
|
SERIAL_PROTOCOLCHAR(T + '0');
|
|
SERIAL_PROTOCOLPAIR(": ", *TMSK);
|
|
|
|
uint8_t OCIE = L - 'A' + 1;
|
|
if (N == 3) {if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter();}
|
|
else {if (WGM == 0 || WGM == 4 || WGM == 12 || WGM == 13) err_is_counter();}
|
|
if (TEST(*TMSK, OCIE)) err_is_interrupt();
|
|
if (TEST(*TMSK, TOIE)) err_prob_interrupt();
|
|
}
|
|
|
|
|
|
|
|
static void pwm_details(uint8_t pin) {
|
|
char buffer[20]; // for the sprintf statements
|
|
uint8_t WGM;
|
|
|
|
switch(digitalPinToTimer(pin)) {
|
|
|
|
|
|
#if defined(TCCR0A) && defined(COM0A1)
|
|
|
|
#if defined (TIMER0A)
|
|
case TIMER0A:
|
|
timer_prefix(0,'A',3);
|
|
break;
|
|
#endif
|
|
case TIMER0B:
|
|
timer_prefix(0,'B',3);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(TCCR1A) && defined(COM1A1)
|
|
case TIMER1A:
|
|
timer_prefix(1,'A',4);
|
|
break;
|
|
case TIMER1B:
|
|
timer_prefix(1,'B',4);
|
|
break;
|
|
#if defined(COM1C1) && defined (TIMER1C)
|
|
case TIMER1C:
|
|
timer_prefix(1,'C',4);
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(TCCR2A) && defined(COM2A1)
|
|
case TIMER2A:
|
|
timer_prefix(2,'A',3);
|
|
break;
|
|
case TIMER2B:
|
|
timer_prefix(2,'B',3);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(TCCR3A) && defined(COM3A1)
|
|
case TIMER3A:
|
|
timer_prefix(3,'A',4);
|
|
break;
|
|
case TIMER3B:
|
|
timer_prefix(3,'B',4);
|
|
break;
|
|
#if defined(COM3C1)
|
|
case TIMER3C:
|
|
timer_prefix(3,'C',4);
|
|
break;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef TCCR4A
|
|
case TIMER4A:
|
|
timer_prefix(4,'A',4);
|
|
break;
|
|
case TIMER4B:
|
|
timer_prefix(4,'B',4);
|
|
break;
|
|
case TIMER4C:
|
|
timer_prefix(4,'C',4);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(TCCR5A) && defined(COM5A1)
|
|
case TIMER5A:
|
|
timer_prefix(5,'A',4);
|
|
break;
|
|
case TIMER5B:
|
|
timer_prefix(5,'B',4);
|
|
break;
|
|
case TIMER5C:
|
|
timer_prefix(5,'C',4);
|
|
break;
|
|
#endif
|
|
|
|
case NOT_ON_TIMER: break;
|
|
|
|
}
|
|
SERIAL_PROTOCOLPGM(" ");
|
|
|
|
// on pins that have two PWMs, print info on second PWM
|
|
#if AVR_ATmega2560_FAMILY || AVR_AT90USB1286_FAMILY
|
|
// looking for port B7 - PWMs 0A and 1C
|
|
if ( ('B' == digitalPinToPort(pin) + 64) && (0x80 == digitalPinToBitMask(pin))) {
|
|
#if !defined(TEENSYDUINO_IDE)
|
|
SERIAL_EOL;
|
|
SERIAL_PROTOCOLPGM (" . TIMER1C is also tied to this pin ");
|
|
timer_prefix(1,'C',4);
|
|
#else
|
|
SERIAL_EOL;
|
|
SERIAL_PROTOCOLPGM (" . TIMER0A is also tied to this pin ");
|
|
timer_prefix(0,'A',3);
|
|
#endif
|
|
}
|
|
#endif
|
|
} // pwm_details
|
|
|
|
bool get_pinMode(int8_t pin) { return *portModeRegister(digitalPinToPort(pin)) & digitalPinToBitMask(pin); }
|
|
|
|
#if !defined(digitalRead_mod) // use Teensyduino's version of digitalRead - it doesn't disable the PWMs
|
|
int digitalRead_mod(int8_t pin) { // same as digitalRead except the PWM stop section has been removed
|
|
uint8_t port = digitalPinToPort(pin);
|
|
return (port != NOT_A_PIN) && (*portInputRegister(port) & digitalPinToBitMask(pin)) ? HIGH : LOW;
|
|
}
|
|
#endif
|
|
|
|
void print_port(int8_t pin) { // print port number
|
|
#if defined(digitalPinToPort)
|
|
SERIAL_PROTOCOLPGM(" Port: ");
|
|
uint8_t x = digitalPinToPort(pin) + 64;
|
|
SERIAL_CHAR(x);
|
|
uint8_t temp = digitalPinToBitMask(pin);
|
|
for (x = '0'; (x < '9' && !(temp == 1)); x++){
|
|
temp = temp >> 1;
|
|
}
|
|
SERIAL_CHAR(x);
|
|
#else
|
|
SERIAL_PROTOCOLPGM(" ")
|
|
#endif
|
|
}
|
|
|
|
|
|
// pretty report with PWM info
|
|
inline void report_pin_state_extended(int8_t pin, bool ignore, bool extended = true) {
|
|
uint8_t temp_char;
|
|
char *name_mem_pointer;
|
|
char buffer[30]; // for the sprintf statements
|
|
bool found = false;
|
|
bool multi_name_pin = false;
|
|
for (uint8_t x = 0; x < n_array; x++) { // scan entire array and report all instances of this pin
|
|
if (pgm_read_byte(&pin_array[x][1]) == pin) {
|
|
if (found == true) multi_name_pin = true;
|
|
found = true;
|
|
if (multi_name_pin == false) { // report digitial and analog pin number only on the first time through
|
|
sprintf(buffer, "PIN:% 3d ", pin); // digital pin number
|
|
SERIAL_ECHO(buffer);
|
|
print_port(pin);
|
|
if (IS_ANALOG(pin)) {
|
|
sprintf(buffer, " (A%2d) ", int(pin - analogInputToDigitalPin(0))); // analog pin number
|
|
SERIAL_ECHO(buffer);
|
|
}
|
|
else SERIAL_ECHOPGM(" "); // add padding if not an analog pin
|
|
}
|
|
else SERIAL_ECHOPGM(". "); // add padding if not the first instance found
|
|
name_mem_pointer = (char*) pgm_read_word(&pin_array[x][0]);
|
|
for (uint8_t y = 0; y < 28; y++) { // always print pin name
|
|
temp_char = pgm_read_byte(name_mem_pointer + y);
|
|
if (temp_char != 0) MYSERIAL.write(temp_char);
|
|
else {
|
|
for (uint8_t i = 0; i < 28 - y; i++) MYSERIAL.write(" ");
|
|
break;
|
|
}
|
|
}
|
|
if (pin_is_protected(pin) && !ignore)
|
|
SERIAL_ECHOPGM("protected ");
|
|
else {
|
|
if (!(pgm_read_byte(&pin_array[x][2]))) {
|
|
sprintf(buffer, "Analog in =% 5d", analogRead(pin - analogInputToDigitalPin(0)));
|
|
SERIAL_ECHO(buffer);
|
|
}
|
|
else {
|
|
if (!get_pinMode(pin)) {
|
|
// pinMode(pin, INPUT_PULLUP); // make sure input isn't floating - stopped doing this
|
|
// because this could interfere with inductive/capacitive
|
|
// sensors (high impedance voltage divider) and with PT100 amplifier
|
|
SERIAL_PROTOCOLPAIR("Input = ", digitalRead_mod(pin));
|
|
}
|
|
else if (pwm_status(pin)) {
|
|
// do nothing
|
|
}
|
|
else SERIAL_PROTOCOLPAIR("Output = ", digitalRead_mod(pin));
|
|
}
|
|
if (multi_name_pin == false && extended) pwm_details(pin); // report PWM capabilities only on the first pass & only if doing an extended report
|
|
}
|
|
SERIAL_EOL;
|
|
} // end of IF
|
|
} // end of for loop
|
|
|
|
if (found == false) {
|
|
sprintf(buffer, "PIN:% 3d ", pin);
|
|
SERIAL_ECHO(buffer);
|
|
print_port(pin);
|
|
if (IS_ANALOG(pin)) {
|
|
sprintf(buffer, " (A%2d) ", int(pin - analogInputToDigitalPin(0))); // analog pin number
|
|
SERIAL_ECHO(buffer);
|
|
}
|
|
else SERIAL_ECHOPGM(" "); // add padding if not an analog pin
|
|
SERIAL_ECHOPGM("<unused/unknown>");
|
|
if (get_pinMode(pin)) {
|
|
SERIAL_PROTOCOLPAIR(" Output = ", digitalRead_mod(pin));
|
|
}
|
|
else {
|
|
if (IS_ANALOG(pin)) {
|
|
sprintf(buffer, " Analog in =% 5d", analogRead(pin - analogInputToDigitalPin(0)));
|
|
SERIAL_ECHO(buffer);
|
|
}
|
|
else {
|
|
SERIAL_ECHOPGM(" "); // add padding if not an analog pin
|
|
}
|
|
SERIAL_PROTOCOLPAIR(" Input = ", digitalRead_mod(pin));
|
|
}
|
|
// if (!pwm_status(pin)) SERIAL_ECHOPGM(" "); // add padding if it's not a PWM pin
|
|
if (extended) pwm_details(pin); // report PWM capabilities only if doing an extended report
|
|
SERIAL_EOL;
|
|
}
|
|
}
|
|
|
|
inline void report_pin_state(int8_t pin) {
|
|
|
|
report_pin_state_extended(pin, false, false);
|
|
|
|
}
|