Subversion Repositories MK-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
#define NAME_FORMAT "%-35s"   // one place to specify the format of all the sources of names
24
                               // "-" left justify, "28" minimum width of name, pad with blanks
25
 
26
#if AVR_ATmega1284_FAMILY
27
  #define DIGITAL_PIN_TO_ANALOG_PIN(P) int(analogInputToDigitalPin(0) - (P))
28
  #define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(7) && (P) <= analogInputToDigitalPin(0))
29
#else
30
  #define DIGITAL_PIN_TO_ANALOG_PIN(P) int((P) - analogInputToDigitalPin(0))
31
  #define IS_ANALOG(P) ((P) >= analogInputToDigitalPin(0) && ((P) <= analogInputToDigitalPin(15) || (P) <= analogInputToDigitalPin(7)))
32
#endif
33
 
34
/**
35
 *  This routine minimizes RAM usage by creating a FLASH resident array to
36
 *  store the pin names, pin numbers and analog/digital flag.
37
 *
38
 *  Creating the array in FLASH is a two pass process.  The first pass puts the
39
 *  name strings into FLASH.  The second pass actually creates the array.
40
 *
41
 *  Both passes use the same pin list.  The list contains two macro names. The
42
 *  actual macro definitions are changed depending on which pass is being done.
43
 *
44
 */
45
 
46
// first pass - put the name strings into FLASH
47
 
48
#define _ADD_PIN_2(PIN_NAME, ENTRY_NAME) static const char ENTRY_NAME[] PROGMEM = { PIN_NAME };
49
#define _ADD_PIN(PIN_NAME, COUNTER) _ADD_PIN_2(PIN_NAME, entry_NAME_##COUNTER)
50
#define REPORT_NAME_DIGITAL(COUNTER, NAME) _ADD_PIN(#NAME, COUNTER)
51
#define REPORT_NAME_ANALOG(COUNTER, NAME) _ADD_PIN(#NAME, COUNTER)
52
 
53
#include "pinsDebug_list.h"
54
#line 51
55
 
56
// manually add pins that have names that are macros which don't play well with these macros
57
#if SERIAL_PORT == 0 && (AVR_ATmega2560_FAMILY || AVR_ATmega1284_FAMILY)
58
  static const char RXD_NAME[] PROGMEM = { "RXD" };
59
  static const char TXD_NAME[] PROGMEM = { "TXD" };
60
#endif
61
 
62
/////////////////////////////////////////////////////////////////////////////
63
 
64
// second pass - create the array
65
 
66
#undef _ADD_PIN_2
67
#undef _ADD_PIN
68
#undef REPORT_NAME_DIGITAL
69
#undef REPORT_NAME_ANALOG
70
 
71
#define _ADD_PIN_2(ENTRY_NAME, NAME, IS_DIGITAL) { ENTRY_NAME, NAME, IS_DIGITAL },
72
#define _ADD_PIN(NAME, COUNTER, IS_DIGITAL) _ADD_PIN_2(entry_NAME_##COUNTER, NAME, IS_DIGITAL)
73
#define REPORT_NAME_DIGITAL(COUNTER, NAME) _ADD_PIN(NAME, COUNTER, true)
74
#define REPORT_NAME_ANALOG(COUNTER, NAME) _ADD_PIN(analogInputToDigitalPin(NAME), COUNTER, false)
75
 
76
typedef struct {
77
  const char * const name;
78
  pin_t pin;
79
  bool is_digital;
80
} PinInfo;
81
 
82
const PinInfo pin_array[] PROGMEM = {
83
 
84
  /**
85
   *  [pin name]  [pin number]  [is digital or analog]  1 = digital, 0 = analog
86
   *  Each entry takes up 6 bytes in FLASH:
87
   *     2 byte pointer to location of the name string
88
   *     2 bytes containing the pin number
89
   *         analog pin numbers were convereted to digital when the array was created
90
   *     2 bytes containing the digital/analog bool flag
91
   */
92
 
93
  // manually add pins ...
94
  #if SERIAL_PORT == 0
95
    #if AVR_ATmega2560_FAMILY
96
      { RXD_NAME, 0, true },
97
      { TXD_NAME, 1, true },
98
    #elif AVR_ATmega1284_FAMILY
99
      { RXD_NAME, 8, true },
100
      { TXD_NAME, 9, true },
101
    #endif
102
  #endif
103
 
104
  #include "pinsDebug_list.h"
105
  #line 102
106
 
107
};
108
 
109
#define AVR_ATmega2560_FAMILY_PLUS_70 (MB(BQ_ZUM_MEGA_3D) || MB(MIGHTYBOARD_REVE) || MB(MINIRAMBO) || MB(SCOOVO_X9H))
110
 
111
#if AVR_AT90USB1286_FAMILY
112
  // Working with Teensyduino extension so need to re-define some things
113
  #include "pinsDebug_Teensyduino.h"
114
  // Can't use the "digitalPinToPort" function from the Teensyduino type IDEs
115
  // portModeRegister takes a different argument
116
  #define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
117
  #define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
118
  #define digitalPinToPort_DEBUG(p) digitalPinToPort_Teensy(p)
119
  #define get_pinMode(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin))
120
#elif AVR_ATmega2560_FAMILY_PLUS_70   // So we can access/display all the pins on boards using more than 70
121
  #include "pinsDebug_plus_70.h"
122
  #define digitalPinToTimer_DEBUG(p) digitalPinToTimer_plus_70(p)
123
  #define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask_plus_70(p)
124
  #define digitalPinToPort_DEBUG(p) digitalPinToPort_plus_70(p)
125
  bool get_pinMode(int8_t pin) {return *portModeRegister(digitalPinToPort_DEBUG(pin)) & digitalPinToBitMask_DEBUG(pin); }
126
#else
127
  #define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
128
  #define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
129
  #define digitalPinToPort_DEBUG(p) digitalPinToPort(p)
130
  bool get_pinMode(int8_t pin) {return *portModeRegister(digitalPinToPort_DEBUG(pin)) & digitalPinToBitMask_DEBUG(pin); }
131
#endif
132
 
133
#if defined(__AVR_ATmega1284P__)  // 1284 IDE extensions set this to the number of
134
  #undef NUM_DIGITAL_PINS         // digital only pins while all other CPUs have it
135
  #define NUM_DIGITAL_PINS 32     // set to digital only + digital/analog
136
#endif
137
 
138
#define PWM_PRINT(V) do{ sprintf_P(buffer, PSTR("PWM:  %4d"), V); SERIAL_ECHO(buffer); }while(0)
139
#define PWM_CASE(N,Z)                                           \
140
  case TIMER##N##Z:                                             \
141
    if (TCCR##N##A & (_BV(COM##N##Z##1) | _BV(COM##N##Z##0))) { \
142
      PWM_PRINT(OCR##N##Z);                                     \
143
      return true;                                              \
144
    } else return false
145
 
146
/**
147
 * Print a pin's PWM status.
148
 * Return true if it's currently a PWM pin.
149
 */
150
static bool pwm_status(uint8_t pin) {
151
  char buffer[20];   // for the sprintf statements
152
 
153
  switch (digitalPinToTimer_DEBUG(pin)) {
154
 
155
    #if defined(TCCR0A) && defined(COM0A1)
156
      #ifdef TIMER0A
157
        #if !AVR_AT90USB1286_FAMILY  // not available in Teensyduino type IDEs
158
          PWM_CASE(0, A);
159
        #endif
160
      #endif
161
      PWM_CASE(0, B);
162
    #endif
163
 
164
    #if defined(TCCR1A) && defined(COM1A1)
165
      PWM_CASE(1, A);
166
      PWM_CASE(1, B);
167
     #if defined(COM1C1) && defined(TIMER1C)
168
      PWM_CASE(1, C);
169
     #endif
170
    #endif
171
 
172
    #if defined(TCCR2A) && defined(COM2A1)
173
      PWM_CASE(2, A);
174
      PWM_CASE(2, B);
175
    #endif
176
 
177
    #if defined(TCCR3A) && defined(COM3A1)
178
      PWM_CASE(3, A);
179
      PWM_CASE(3, B);
180
      #ifdef COM3C1
181
        PWM_CASE(3, C);
182
      #endif
183
    #endif
184
 
185
    #ifdef TCCR4A
186
      PWM_CASE(4, A);
187
      PWM_CASE(4, B);
188
      PWM_CASE(4, C);
189
    #endif
190
 
191
    #if defined(TCCR5A) && defined(COM5A1)
192
      PWM_CASE(5, A);
193
      PWM_CASE(5, B);
194
      PWM_CASE(5, C);
195
    #endif
196
 
197
    case NOT_ON_TIMER:
198
    default:
199
      return false;
200
  }
201
  SERIAL_PROTOCOL_SP(2);
202
} // pwm_status
203
 
204
 
205
const volatile uint8_t* const PWM_other[][3] PROGMEM = {
206
    { &TCCR0A, &TCCR0B, &TIMSK0 },
207
    { &TCCR1A, &TCCR1B, &TIMSK1 },
208
  #if defined(TCCR2A) && defined(COM2A1)
209
    { &TCCR2A, &TCCR2B, &TIMSK2 },
210
  #endif
211
  #if defined(TCCR3A) && defined(COM3A1)
212
    { &TCCR3A, &TCCR3B, &TIMSK3 },
213
  #endif
214
  #ifdef TCCR4A
215
    { &TCCR4A, &TCCR4B, &TIMSK4 },
216
  #endif
217
  #if defined(TCCR5A) && defined(COM5A1)
218
    { &TCCR5A, &TCCR5B, &TIMSK5 },
219
  #endif
220
};
221
 
222
 
223
const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
224
 
225
  #ifdef TIMER0A
226
    { &OCR0A, &OCR0B, 0 },
227
  #else
228
    { 0, &OCR0B, 0 },
229
  #endif
230
 
231
  #if defined(COM1C1) && defined(TIMER1C)
232
   { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, (const uint8_t*)&OCR1C },
233
  #else
234
   { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
235
  #endif
236
 
237
  #if defined(TCCR2A) && defined(COM2A1)
238
    { &OCR2A, &OCR2B, 0 },
239
  #endif
240
 
241
  #if defined(TCCR3A) && defined(COM3A1)
242
    #ifdef COM3C1
243
      { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
244
    #else
245
      { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, 0 },
246
    #endif
247
  #endif
248
 
249
  #ifdef TCCR4A
250
    { (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
251
  #endif
252
 
253
  #if defined(TCCR5A) && defined(COM5A1)
254
    { (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
255
  #endif
256
};
257
 
258
 
259
#define TCCR_A(T)   pgm_read_word(&PWM_other[T][0])
260
#define TCCR_B(T)   pgm_read_word(&PWM_other[T][1])
261
#define TIMSK(T)    pgm_read_word(&PWM_other[T][2])
262
#define CS_0       0
263
#define CS_1       1
264
#define CS_2       2
265
#define WGM_0      0
266
#define WGM_1      1
267
#define WGM_2      3
268
#define WGM_3      4
269
#define TOIE       0
270
 
271
#define OCR_VAL(T, L)   pgm_read_word(&PWM_OCR[T][L])
272
 
273
static void err_is_counter()     { SERIAL_PROTOCOLPGM("   non-standard PWM mode"); }
274
static void err_is_interrupt()   { SERIAL_PROTOCOLPGM("   compare interrupt enabled"); }
275
static void err_prob_interrupt() { SERIAL_PROTOCOLPGM("   overflow interrupt enabled"); }
276
 
277
#if AVR_ATmega2560_FAMILY || AVR_AT90USB1286_FAMILY
278
  static void print_is_also_tied() { SERIAL_PROTOCOLPGM(" is also tied to this pin"); SERIAL_PROTOCOL_SP(14); }
279
#endif
280
 
281
void com_print(uint8_t N, uint8_t Z) {
282
  const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
283
  SERIAL_PROTOCOLPGM("    COM");
284
  SERIAL_PROTOCOLCHAR(N + '0');
285
  switch (Z) {
286
    case 'A':
287
      SERIAL_PROTOCOLPAIR("A: ", ((*TCCRA & (_BV(7) | _BV(6))) >> 6));
288
      break;
289
    case 'B':
290
      SERIAL_PROTOCOLPAIR("B: ", ((*TCCRA & (_BV(5) | _BV(4))) >> 4));
291
      break;
292
    case 'C':
293
      SERIAL_PROTOCOLPAIR("C: ", ((*TCCRA & (_BV(3) | _BV(2))) >> 2));
294
      break;
295
  }
296
}
297
 
298
void timer_prefix(uint8_t T, char L, uint8_t N) {  // T - timer    L - pwm  N - WGM bit layout
299
  char buffer[20];   // for the sprintf statements
300
  const uint8_t *TCCRB = (uint8_t*)TCCR_B(T),
301
                *TCCRA = (uint8_t*)TCCR_A(T);
302
  uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
303
  if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
304
 
305
  SERIAL_PROTOCOLPGM("    TIMER");
306
  SERIAL_PROTOCOLCHAR(T + '0');
307
  SERIAL_PROTOCOLCHAR(L);
308
  SERIAL_PROTOCOL_SP(3);
309
 
310
  if (N == 3) {
311
    const uint8_t *OCRVAL8 = (uint8_t*)OCR_VAL(T, L - 'A');
312
    PWM_PRINT(*OCRVAL8);
313
  }
314
  else {
315
    const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A');
316
    PWM_PRINT(*OCRVAL16);
317
  }
318
  SERIAL_PROTOCOLPAIR("    WGM: ", WGM);
319
  com_print(T,L);
320
  SERIAL_PROTOCOLPAIR("    CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
321
 
322
  SERIAL_PROTOCOLPGM("    TCCR");
323
  SERIAL_PROTOCOLCHAR(T + '0');
324
  SERIAL_PROTOCOLPAIR("A: ", *TCCRA);
325
 
326
  SERIAL_PROTOCOLPGM("    TCCR");
327
  SERIAL_PROTOCOLCHAR(T + '0');
328
  SERIAL_PROTOCOLPAIR("B: ", *TCCRB);
329
 
330
  const uint8_t *TMSK = (uint8_t*)TIMSK(T);
331
  SERIAL_PROTOCOLPGM("    TIMSK");
332
  SERIAL_PROTOCOLCHAR(T + '0');
333
  SERIAL_PROTOCOLPAIR(": ", *TMSK);
334
 
335
  const uint8_t OCIE = L - 'A' + 1;
336
  if (N == 3) { if (WGM == 0 || WGM == 2 || WGM ==  4 || WGM ==  6) err_is_counter(); }
337
  else        { if (WGM == 0 || WGM == 4 || WGM == 12 || WGM == 13) err_is_counter(); }
338
  if (TEST(*TMSK, OCIE)) err_is_interrupt();
339
  if (TEST(*TMSK, TOIE)) err_prob_interrupt();
340
}
341
 
342
static void pwm_details(uint8_t pin) {
343
  switch (digitalPinToTimer_DEBUG(pin)) {
344
 
345
    #if defined(TCCR0A) && defined(COM0A1)
346
      #ifdef TIMER0A
347
        #if !AVR_AT90USB1286_FAMILY  // not available in Teensyduino type IDEs
348
          case TIMER0A: timer_prefix(0, 'A', 3); break;
349
        #endif
350
      #endif
351
      case TIMER0B: timer_prefix(0, 'B', 3); break;
352
    #endif
353
 
354
    #if defined(TCCR1A) && defined(COM1A1)
355
      case TIMER1A: timer_prefix(1, 'A', 4); break;
356
      case TIMER1B: timer_prefix(1, 'B', 4); break;
357
      #if defined(COM1C1) && defined(TIMER1C)
358
        case TIMER1C: timer_prefix(1, 'C', 4); break;
359
      #endif
360
    #endif
361
 
362
    #if defined(TCCR2A) && defined(COM2A1)
363
      case TIMER2A: timer_prefix(2, 'A', 3); break;
364
      case TIMER2B: timer_prefix(2, 'B', 3); break;
365
    #endif
366
 
367
    #if defined(TCCR3A) && defined(COM3A1)
368
      case TIMER3A: timer_prefix(3, 'A', 4); break;
369
      case TIMER3B: timer_prefix(3, 'B', 4); break;
370
      #ifdef COM3C1
371
        case TIMER3C: timer_prefix(3, 'C', 4); break;
372
      #endif
373
    #endif
374
 
375
    #ifdef TCCR4A
376
      case TIMER4A: timer_prefix(4, 'A', 4); break;
377
      case TIMER4B: timer_prefix(4, 'B', 4); break;
378
      case TIMER4C: timer_prefix(4, 'C', 4); break;
379
    #endif
380
 
381
    #if defined(TCCR5A) && defined(COM5A1)
382
      case TIMER5A: timer_prefix(5, 'A', 4); break;
383
      case TIMER5B: timer_prefix(5, 'B', 4); break;
384
      case TIMER5C: timer_prefix(5, 'C', 4); break;
385
    #endif
386
 
387
    case NOT_ON_TIMER: break;
388
 
389
  }
390
  SERIAL_PROTOCOLPGM("  ");
391
 
392
  // on pins that have two PWMs, print info on second PWM
393
  #if AVR_ATmega2560_FAMILY || AVR_AT90USB1286_FAMILY
394
    // looking for port B7 - PWMs 0A and 1C
395
    if (digitalPinToPort_DEBUG(pin) == 'B' - 64 && 0x80 == digitalPinToBitMask_DEBUG(pin)) {
396
      #if !AVR_AT90USB1286_FAMILY
397
        SERIAL_PROTOCOLPGM("\n .");
398
        SERIAL_PROTOCOL_SP(18);
399
        SERIAL_PROTOCOLPGM("TIMER1C");
400
        print_is_also_tied();
401
        timer_prefix(1, 'C', 4);
402
      #else
403
        SERIAL_PROTOCOLPGM("\n .");
404
        SERIAL_PROTOCOL_SP(18);
405
        SERIAL_PROTOCOLPGM("TIMER0A");
406
        print_is_also_tied();
407
        timer_prefix(0, 'A', 3);
408
      #endif
409
    }
410
  #endif
411
} // pwm_details
412
 
413
#ifndef digitalRead_mod                   // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
414
  int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
415
    const uint8_t port = digitalPinToPort_DEBUG(pin);
416
    return (port != NOT_A_PIN) && (*portInputRegister(port) & digitalPinToBitMask_DEBUG(pin)) ? HIGH : LOW;
417
  }
418
#endif
419
 
420
void print_port(int8_t pin) {   // print port number
421
  #ifdef digitalPinToPort_DEBUG
422
    uint8_t x;
423
    SERIAL_PROTOCOLPGM("  Port: ");
424
    #if AVR_AT90USB1286_FAMILY
425
      x = (pin == 46 || pin == 47) ? 'E' : digitalPinToPort_DEBUG(pin) + 64;
426
    #else
427
      x = digitalPinToPort_DEBUG(pin) + 64;
428
    #endif
429
    SERIAL_CHAR(x);
430
 
431
    #if AVR_AT90USB1286_FAMILY
432
      if (pin == 46)
433
        x = '2';
434
      else if (pin == 47)
435
        x = '3';
436
      else {
437
        uint8_t temp = digitalPinToBitMask_DEBUG(pin);
438
        for (x = '0'; x < '9' && temp != 1; x++) temp >>= 1;
439
      }
440
    #else
441
      uint8_t temp = digitalPinToBitMask_DEBUG(pin);
442
      for (x = '0'; x < '9' && temp != 1; x++) temp >>= 1;
443
    #endif
444
    SERIAL_CHAR(x);
445
  #else
446
    SERIAL_PROTOCOL_SP(10);
447
  #endif
448
}
449
 
450
static void print_input_or_output(const bool isout) {
451
  serialprintPGM(isout ? PSTR("Output = ") : PSTR("Input  = "));
452
}
453
 
454
// pretty report with PWM info
455
inline void report_pin_state_extended(int8_t pin, bool ignore, bool extended = false, const char *start_string = "") {
456
  uint8_t temp_char;
457
  char *name_mem_pointer, buffer[30];   // for the sprintf statements
458
  bool found = false, multi_name_pin = false;
459
  for (uint8_t x = 0; x < COUNT(pin_array); x++)  {    // scan entire array and report all instances of this pin
460
    if (pgm_read_byte(&pin_array[x].pin) == pin) {
461
      if (found) multi_name_pin = true;
462
      found = true;
463
      if (!multi_name_pin) {    // report digitial and analog pin number only on the first time through
464
        sprintf_P(buffer, PSTR("%sPIN: %3d "), start_string, pin);     // digital pin number
465
        SERIAL_ECHO(buffer);
466
        print_port(pin);
467
        if (IS_ANALOG(pin)) {
468
          sprintf_P(buffer, PSTR(" (A%2d)  "), int(pin - analogInputToDigitalPin(0)));    // analog pin number
469
          SERIAL_ECHO(buffer);
470
        }
471
        else SERIAL_ECHO_SP(8);   // add padding if not an analog pin
472
      }
473
      else {
474
        SERIAL_CHAR('.');
475
        SERIAL_ECHO_SP(26 + strlen(start_string));  // add padding if not the first instance found
476
      }
477
      name_mem_pointer = (char*)pgm_read_word(&pin_array[x].name);
478
      for (uint8_t y = 0; y < 28; y++) {                   // always print pin name
479
        temp_char = pgm_read_byte(name_mem_pointer + y);
480
        if (temp_char != 0)
481
          SERIAL_CHAR(temp_char);
482
        else {
483
          for (uint8_t i = 0; i < 28 - y; i++) SERIAL_CHAR(' ');
484
          break;
485
        }
486
      }
487
      if (extended) {
488
        if (pin_is_protected(pin) && !ignore)
489
          SERIAL_ECHOPGM("protected ");
490
        else {
491
          #if AVR_AT90USB1286_FAMILY //Teensy IDEs don't know about these pins so must use FASTIO
492
            if (pin == 46 || pin == 47) {
493
              if (pin == 46) {
494
                print_input_or_output(GET_OUTPUT(46));
495
                SERIAL_PROTOCOL(READ(46));
496
              }
497
              else if (pin == 47) {
498
                print_input_or_output(GET_OUTPUT(47));
499
                SERIAL_PROTOCOL(READ(47));
500
              }
501
            }
502
            else
503
          #endif
504
          {
505
            if (!(pgm_read_byte(&pin_array[x].is_digital))) {
506
              sprintf_P(buffer, PSTR("Analog in = %5d"), analogRead(pin - analogInputToDigitalPin(0)));
507
              SERIAL_ECHO(buffer);
508
            }
509
            else {
510
 
511
              if (!get_pinMode(pin)) {
512
                //pinMode(pin, INPUT_PULLUP);  // make sure input isn't floating - stopped doing this
513
                                               // because this could interfere with inductive/capacitive
514
                                               // sensors (high impedance voltage divider) and with PT100 amplifier
515
                print_input_or_output(false);
516
                SERIAL_PROTOCOL(digitalRead_mod(pin));
517
              }
518
              else if (pwm_status(pin)) {
519
                // do nothing
520
              }
521
              else {
522
                print_input_or_output(true);
523
                SERIAL_PROTOCOL(digitalRead_mod(pin));
524
              }
525
            }
526
            if (!multi_name_pin && extended) pwm_details(pin);  // report PWM capabilities only on the first pass & only if doing an extended report
527
          }
528
        }
529
      }
530
      SERIAL_EOL();
531
    }  // end of IF
532
  } // end of for loop
533
 
534
  if (!found) {
535
    sprintf_P(buffer, PSTR("%sPIN: %3d "), start_string, pin);
536
    SERIAL_ECHO(buffer);
537
    print_port(pin);
538
    if (IS_ANALOG(pin)) {
539
      sprintf_P(buffer, PSTR(" (A%2d)  "), int(pin - analogInputToDigitalPin(0)));    // analog pin number
540
      SERIAL_ECHO(buffer);
541
    }
542
    else
543
      SERIAL_ECHO_SP(8);   // add padding if not an analog pin
544
    SERIAL_ECHOPGM("<unused/unknown>");
545
    if (extended) {
546
      #if AVR_AT90USB1286_FAMILY  //Teensy IDEs don't know about these pins so must use FASTIO
547
        if (pin == 46 || pin == 47) {
548
          SERIAL_PROTOCOL_SP(12);
549
          if (pin == 46) {
550
            print_input_or_output(GET_OUTPUT(46));
551
            SERIAL_PROTOCOL(READ(46));
552
          }
553
          else {
554
            print_input_or_output(GET_OUTPUT(47));
555
            SERIAL_PROTOCOL(READ(47));
556
          }
557
        }
558
        else
559
      #endif
560
      {
561
        if (get_pinMode(pin)) {
562
          SERIAL_PROTOCOL_SP(12);
563
          print_input_or_output(true);
564
          SERIAL_PROTOCOL(digitalRead_mod(pin));
565
        }
566
        else {
567
          if (IS_ANALOG(pin)) {
568
            sprintf_P(buffer, PSTR("   Analog in = %5d"), analogRead(pin - analogInputToDigitalPin(0)));
569
            SERIAL_ECHO(buffer);
570
            SERIAL_ECHOPGM("   ");
571
          }
572
          else
573
          SERIAL_ECHO_SP(12);   // add padding if not an analog pin
574
 
575
          print_input_or_output(false);
576
          SERIAL_PROTOCOL(digitalRead_mod(pin));
577
        }
578
        //if (!pwm_status(pin)) SERIAL_CHAR(' ');    // add padding if it's not a PWM pin
579
        if (extended) pwm_details(pin);  // report PWM capabilities only if doing an extended report
580
      }
581
    }
582
    SERIAL_EOL();
583
  }
584
}