March Madness - Arduino Explorer Part 2

The purpose of March Madness is to get going on things and to LEARN. Well I am doing a lot of that. On Saturday I got a new Arduino board. the Duino644 This board is fully Arduino IDE compatible but it is NOT compatible with the Arduino shields. It makes up for this because it has a ton of stuff built in. (real time clock, serial EEPROM, DS Card, speaker, buttons). It also uses the ATmega644 cpu which has more memory (64K), more RAM and more I/O.

I put the kit together and got it working... Mostly... There was a problem with receiving serial data. Turned out to be a bug in the HardwareSerial.cpp driver, it used the wrong interrupt vector. Thanks to Keith C for helping me track this down.

In the process I have learned a lot about the guts of the Arduino environment, the interrupts a little, and more improtantly the mapping of Arduino pins to Ateml ports and bits.

To that end, I added several commands to my Arduino Explorer project from March 13th. The most significant command is "M" which shows you what pin numbers are associated with which actual Atmel port and bit. This information can be found in "pins_arduino.h" but it is several tables that have to be read and understood.

I will continue working on this program. It serves two very important purposes. It will definetly help anyone like mw working on the transition from the Arduino environment to the Atmel environment. It also is a good tool for debugging hardware, both exisiting and new.

Atmega328P (Duemilanove) ATmega644 (Duino644) ATmega1280 (Mega)
Arduino>M
CPU Type         = ATmega328P
Digital pin  0 = D  0  RX Data
Digital pin  1 = D  1  TX Data
Digital pin  2 = D  2
Digital pin  3 = D  3  Timer 7
Digital pin  4 = D  4
Digital pin  5 = D  5  Timer 2
Digital pin  6 = D  6  Timer 1
Digital pin  7 = D  7
Digital pin  8 = B  0
Digital pin  9 = B  1  Timer 3
Digital pin 10 = B  2  Timer 4
Digital pin 11 = B  3  Timer 6
Digital pin 12 = B  4
Digital pin 13 = B  5
Digital pin 14 = C  0 Analog Input 0
Digital pin 15 = C  1 Analog Input 1
Digital pin 16 = C  2 Analog Input 2
Digital pin 17 = C  3 Analog Input 3
Digital pin 18 = C  4 Analog Input 4
Digital pin 19 = C  5 Analog Input 5
Arduino>M
CPU Type         = ATmega644
Digital pin  0 = B  0
Digital pin  1 = B  1
Digital pin  2 = B  2
Digital pin  3 = B  3  Timer 1
Digital pin  4 = B  4  Timer 2
Digital pin  5 = B  5
Digital pin  6 = B  6
Digital pin  7 = B  7
Digital pin  8 = D  0  RX Data
Digital pin  9 = D  1  TX Data
Digital pin 10 = D  2
Digital pin 11 = D  3
Digital pin 12 = D  4  Timer 4
Digital pin 13 = D  5  Timer 3
Digital pin 14 = D  6  Timer 7
Digital pin 15 = D  7  Timer 6
Digital pin 16 = C  0
Digital pin 17 = C  1
Digital pin 18 = C  2
Digital pin 19 = C  3
Digital pin 20 = C  4
Digital pin 21 = C  5
Digital pin 22 = C  6
Digital pin 23 = C  7
Digital pin 24 = A  7 Analog Input 0
Digital pin 25 = A  6 Analog Input 1
Digital pin 26 = A  5 Analog Input 2
Digital pin 27 = A  4 Analog Input 3
Digital pin 28 = A  3 Analog Input 4
Digital pin 29 = A  2 Analog Input 5
Digital pin 30 = A  1 Analog Input 6
Digital pin 31 = A  0 Analog Input 7
CPU Type         = ATmega1280

Arduino>M
Digital pin  0 = E  0  RX Data
Digital pin  1 = E  1  TX Data
Digital pin  2 = E  4  Timer 9
Digital pin  3 = E  5  Timer 10
Digital pin  4 = G  5  Timer 2
Digital pin  5 = E  3  Timer 8
Digital pin  6 = H  3  Timer 11
Digital pin  7 = H  4  Timer 12
Digital pin  8 = H  5  Timer 13
Digital pin  9 = H  6  Timer 7
Digital pin 10 = B  4  Timer 6
Digital pin 11 = B  5  Timer 3
Digital pin 12 = B  6  Timer 4
Digital pin 13 = B  7  Timer 1
Digital pin 14 = J  1
Digital pin 15 = J  0
Digital pin 16 = H  1
Digital pin 17 = H  0
Digital pin 18 = D  3
Digital pin 19 = D  2
Digital pin 20 = D  1
Digital pin 21 = D  0
Digital pin 22 = A  0
Digital pin 23 = A  1
Digital pin 24 = A  2
Digital pin 25 = A  3
Digital pin 26 = A  4
Digital pin 27 = A  5
Digital pin 28 = A  6
Digital pin 29 = A  7
Digital pin 30 = C  7
Digital pin 31 = C  6
Digital pin 32 = C  5
Digital pin 33 = C  4
Digital pin 34 = C  3
Digital pin 35 = C  2
Digital pin 36 = C  1
Digital pin 37 = C  0
Digital pin 38 = D  7
Digital pin 39 = G  2
Digital pin 40 = G  1
Digital pin 41 = G  0
Digital pin 42 = L  7
Digital pin 43 = L  6
Digital pin 44 = L  5  Timer 16
Digital pin 45 = L  4  Timer 15
Digital pin 46 = L  3  Timer 14
Digital pin 47 = L  2
Digital pin 48 = L  1
Digital pin 49 = L  0
Digital pin 50 = B  3
Digital pin 51 = B  2
Digital pin 52 = B  1
Digital pin 53 = B  0
Digital pin 54 = F  0 Analog Input 0
Digital pin 55 = F  1 Analog Input 1
Digital pin 56 = F  2 Analog Input 2
Digital pin 57 = F  3 Analog Input 3
Digital pin 58 = F  4 Analog Input 4
Digital pin 59 = F  5 Analog Input 5
Digital pin 60 = F  6 Analog Input 6
Digital pin 61 = F  7 Analog Input 7
Digital pin 62 = K  0 Analog Input 8
Digital pin 63 = K  1 Analog Input 9
Digital pin 64 = K  2 Analog Input 10
Digital pin 65 = K  3 Analog Input 11
Digital pin 66 = K  4 Analog Input 12
Digital pin 67 = K  5 Analog Input 13
Digital pin 68 = K  6 Analog Input 14
Digital pin 69 = K  7 Analog Input 15



//************************************************************************
//*	Arduino Exploer
//*		(C) 2010 by Mark Sproul
//*		Open source as per standard Arduino code
//*
//*	This is done in the old fashion monitor style low level program
//*	it allows you to look at various aspects of the Arduino environment
//*	without writting special code. It can be used for debugging new hardware
//*
//*		0	=	Zero address counters
//*		?	=	Help
//*		B	=	Blink LED
//*		E	=	Dump EEPROM
//*		F	=	Dump FLASH
//*		I	=	I2C scan
//*		M	=	Map I/O pins
//*		P	=	Show ONE pin
//*		R	=	Dump RAM
//*		S	=	Show pins
//*		T	=	Play Tone
//*		W	=	Watch for input change
//************************************************************************

#include	<avr/pgmspace.h>
#include	"EEPROM.h"

#include	<avr/version.h>

#include	"WProgram.h"
#include	"HardwareSerial.h"
#include	"pins_arduino.h"

#include "Wire.h"
extern "C" { 
	#include "utility/twi.h"	// from Wire library, so we can do bus scanning
	//#include "twi.h"			// from Wire library, so we can do bus scanning
}


#ifdef __AVR_ATmega644__
//	#include	
//	SoftwareSerial softSerial		=	SoftwareSerial(1, 0);
#else
#endif


enum 
{
	kDUMP_FLASH	=	0,
	kDUMP_EEPROM,
	kDUMP_RAM
};

unsigned char	*gRamPtr	=	0;
unsigned int	gRamIndex	=	0;
unsigned long	gFlashIndex	=	0;

#if defined(__AVR_ATmega1280__)

	#define	kRXD_pin	0
	#define	kTXD_pin	1
	

	#define	kLED_PIN	13
	#define	kCPU_NAME	"ATmega1280"

	#define	kDigitalPin_First		0
	#define	kDigitalPin_Last		69

	#define	kDigitalPin_FirstAnalog	54

	#define	kAnalogPin_First		0
	#define	kAnalogPin_Last			15

	#define	kDigitalPinCount		69

#elif defined(__AVR_ATmega644__ ) || defined(__AVR_ATmega644P__ )

	#ifdef __AVR_ATmega644__
		#define	kCPU_NAME	"ATmega644 (Duino644)"
	#endif
	#ifdef __AVR_ATmega644P__
		#define	kCPU_NAME	"ATmega644P"
	#endif
	
	#define	kRXD_pin	8
	#define	kTXD_pin	9

	#define	kDigitalPin_First		0
	#define	kDigitalPin_Last		31

	#define	kDigitalPin_FirstAnalog	24

	#define	kAnalogPin_First		0
	#define	kAnalogPin_Last			7

	#define	kDigitalPinCount		31

#else

	#define	kRXD_pin	0
	#define	kTXD_pin	1

	#define	kLED_PIN	13

	#define	kDigitalPin_First		0
	#define	kDigitalPin_Last		19

	#define	kDigitalPin_FirstAnalog	14

	#define	kAnalogPin_First		0
	#define	kAnalogPin_Last			5

	#define	kDigitalPinCount		19
#endif


#ifdef __AVR_ATmega168__ 
	#define	kCPU_NAME	"ATmega168"
#endif

#ifdef __AVR_ATmega328P__
	#define	kCPU_NAME	"ATmega328P"
#endif



#ifdef __AVR_ATmega644__
	#define SPEAKER_PIN1      22  // PC6;
	#define SPEAKER_PIN2      23  // PC7;
#endif



//*	in an attempt to save RAM and use program space more effiently, printed strings are here
#ifdef kCPU_NAME
prog_char	gTextMsg_CPU_Name[]		PROGMEM	=	kCPU_NAME;
#else
prog_char	gTextMsg_CPU_Name[]		PROGMEM	=	"UNKNOWN";
#endif
prog_char	gTextMsg_Explorer[]		PROGMEM	=	"Arduino explorer";
prog_char	gTextMsg_Prompt[]		PROGMEM	=	"Arduino>";
prog_char	gTextMsg_CPU_Type[]		PROGMEM	=	"CPU Type         = ";
prog_char	gTextMsg_AVR_ARCH[]		PROGMEM	=	"__AVR_ARCH__     = ";
prog_char	gTextMsg_AVR_LIBC[]		PROGMEM	=	"AVR LibC Version = ";
prog_char	gTextMsg_DIGITALPIN[]	PROGMEM	=	"Digital Pin # ";
prog_char	gTextMsg_WHAT_PIN[]		PROGMEM	=	"what pin #:";
prog_char	gTextMsg_RX_DATA[]		PROGMEM	=	"  RX Data";
prog_char	gTextMsg_TX_DATA[]		PROGMEM	=	"  TX Data";
prog_char	gTextMsg_AnalogIN[]		PROGMEM	=	"  Analog Input ";


prog_char	gTextMsg_HELP_MSG_1[]	PROGMEM	=	"0=Zero address counters\r\n";
prog_char	gTextMsg_HELP_MSG_2[]	PROGMEM	=	"?=Help\r\n";
prog_char	gTextMsg_HELP_MSG_3[]	PROGMEM	=	"B=Blink LED\r\n";
prog_char	gTextMsg_HELP_MSG_4[]	PROGMEM	=	"E=Dump EEPROM\r\n";
prog_char	gTextMsg_HELP_MSG_5[]	PROGMEM	=	"F=Dump FLASH\r\n";
prog_char	gTextMsg_HELP_MSG_6[]	PROGMEM	=	"I=I2C scan\r\n";
prog_char	gTextMsg_HELP_MSG_7[]	PROGMEM	=	"M=Map I/O pins\r\n";
prog_char	gTextMsg_HELP_MSG_8[]	PROGMEM	=	"P=Show ONE pin\r\n";
prog_char	gTextMsg_HELP_MSG_9[]	PROGMEM	=	"R=Dump RAM\r\n";
prog_char	gTextMsg_HELP_MSG_10[]	PROGMEM	=	"S=Show pins\r\n";
prog_char	gTextMsg_HELP_MSG_11[]	PROGMEM	=	"T=Play Tone\r\n";
prog_char	gTextMsg_HELP_MSG_12[]	PROGMEM	=	"W=Watch for input\r\n\0x00";

//*	this gets filled with an array from o -> 256 just to prove that we are looking
//*	at RAM
unsigned char	gCharArray[256];
int				gButtonState[kDigitalPinCount + 1];

//************************************************************************
void	PrintFromPROGMEM(void *dataPtr)
{
char	myMessage[64];

	strcpy_P(myMessage, (char *)dataPtr);
	Serial.print(myMessage);
}

//************************************************************************
void	PrintCPUstats()
{


	PrintFromPROGMEM(gTextMsg_CPU_Type);
	PrintFromPROGMEM(gTextMsg_CPU_Name);
	Serial.println();


	PrintFromPROGMEM(gTextMsg_AVR_ARCH);
	Serial.println(__AVR_ARCH__);
	
	PrintFromPROGMEM(gTextMsg_AVR_LIBC);
	Serial.println(__AVR_LIBC_VERSION_STRING__);
	
	Serial.println();
	
	
}


//************************************************************************
static void	DumpHex(byte dumpWhat, unsigned long startAddress, int numRows)
{
int				ii;
int				theValue;
int				lineCount;
char			textString[16];
char			asciiDump[24];
unsigned long	myAddressPointer;

	lineCount			=	0;
	myAddressPointer	=	startAddress;
	while (lineCount < numRows)
	{
		sprintf(textString, "%04X - ", myAddressPointer);
		Serial.print(textString);
		
		asciiDump[0]		=	0;
		for (ii=0; ii<16; ii++)
		{
			switch(dumpWhat)
			{
				case kDUMP_FLASH:
					theValue	=	pgm_read_byte_near(myAddressPointer);
					break;

				case kDUMP_EEPROM:
				#ifndef __MWERKS__
					theValue	=	EEPROM.read(myAddressPointer);
				#endif
					break;

				case kDUMP_RAM:
					theValue	=	gRamPtr[myAddressPointer];
					break;

			}

			sprintf(textString, "%02X ", theValue);
			Serial.print(textString);
			if ((theValue >= 0x20) && (theValue < 0x7f))
			{
				asciiDump[ii % 16]	=	theValue;
			}
			else
			{
				asciiDump[ii % 16]	=	'.';
			}
			
			myAddressPointer++;
		}
		asciiDump[16]	=	0;
		Serial.println(asciiDump);
	
		lineCount++;
	}
}


//*******************************************************************
void ShowPins(void)
{
short	ii;
int		pinValue;

	for (ii = kDigitalPin_First; ii <= kDigitalPin_Last; ii++)
	{
		pinValue	=	digitalRead(ii);
		PrintFromPROGMEM(gTextMsg_DIGITALPIN);
		Serial.print(ii);
		Serial.print(" ");
		Serial.print(pinValue);

		if (ii == kRXD_pin)
		{
			PrintFromPROGMEM(gTextMsg_RX_DATA);
		}
		if (ii == kTXD_pin)
		{
			PrintFromPROGMEM(gTextMsg_TX_DATA);
		}

		Serial.println();
	}
	Serial.println();



	for (ii=kAnalogPin_First; ii <= kAnalogPin_Last; ii++)
	{
		pinValue	=	analogRead(ii);
		Serial.print("Analog Pin # ");
		Serial.print(ii);
		Serial.print(" ");
		Serial.print(pinValue);
		Serial.println();
	}
	Serial.println();

}

//*******************************************************************
void PrintHelp(void)
{
	PrintFromPROGMEM(gTextMsg_HELP_MSG_1);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_2);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_3);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_4);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_5);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_6);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_7);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_8);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_9);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_10);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_11);
	PrintFromPROGMEM(gTextMsg_HELP_MSG_12);
//	PrintFromPROGMEM(gTextMsg_HELP_MSG_13);
//	PrintFromPROGMEM(gTextMsg_HELP_MSG_14);
//	PrintFromPROGMEM(gTextMsg_HELP_MSG_15);
}

//****************************************************************************
//*	Scan the I2C bus between addresses from_addr and to_addr.
//*	On each address, call the callback function with the address and result.
//*	If result==0, address was found, otherwise, address wasn't found
//*	(can use result to potentially get other status on the I2C bus, see twi.c)
//*	Assumes Wire.begin() has already been called
//*	2009, Tod E. Kurt, http://todbot.com/blog/
//****************************************************************************
void ScanI2CBus(byte from_addr, byte to_addr) 
{
byte addr;
byte rc;
byte data; // not used, just an address to feed to twi_writeTo()
int	foundCount;

	Serial.print("starting scanning of I2C bus from ");
	Serial.print(from_addr, DEC);
	Serial.print(" to ");
	Serial.print(to_addr, DEC);
	Serial.println("...");

	data		=	0;
	foundCount	=	0;
	for(addr = from_addr; addr <= to_addr; addr++ )
	{
		Serial.print("addr:");
		Serial.print(addr,DEC);
		rc	=	twi_writeTo(addr, &data, 0, 1);
		if (rc == 0)
		{
			foundCount++;
		}
		Serial.print( (rc==0) ? " found!":"       ");
		Serial.print( (addr%4) ? "\t":"\r\n");
	}
	Serial.println();

	Serial.print( "I2C device count = ");
	Serial.println(foundCount);
}

//************************************************************************
void	GetInputTextString(char *inputTextString, int maxLen)
{
boolean	keepGoing;
char	theChar;
int		cc;

	keepGoing	=	true;
	cc			=	0;
	while (keepGoing && (cc < maxLen))
	{
		if (Serial.available())
		{
			theChar	=	Serial.read();
			Serial.write(theChar);
			if (theChar == 0x08)	//*	backspace
			{
				cc--;
				if (cc < 0)
				{
					cc	=	0;
				}
			}
			else if (theChar >= 0x20)
			{
				inputTextString[cc++]	=	theChar;
			}
			else
			{
				inputTextString[cc]	=	0;
				keepGoing			=	false;
			}
		}
	}
}

//************************************************************************
void	ShowOneDigitalPin()
{
char	inputTextString[16];
int		pinNumber;
int		pinValue;

	PrintFromPROGMEM(gTextMsg_WHAT_PIN);
	GetInputTextString(inputTextString, 8);
	Serial.println();
	
	pinNumber	=	atoi(inputTextString);
	
	while (!Serial.available())
	{
		pinValue	=	digitalRead(pinNumber);
		PrintFromPROGMEM(gTextMsg_DIGITALPIN);
		Serial.print(pinNumber);
		Serial.print(" ");
		Serial.print(pinValue);
		Serial.write(0x0d);
	}
}


//************************************************************************
void	SetOneAnalogPin()
{
char	inputTextString[16];
int		pinNumber;

	PrintFromPROGMEM(gTextMsg_WHAT_PIN);
	GetInputTextString(inputTextString, 8);
	Serial.println();
	
	pinNumber	=	atoi(inputTextString);
	
	analogWrite(pinNumber, 128);
	while (!Serial.available())
	{
	}
	analogWrite(pinNumber, 0);
}


//************************************************************************
void ShowPinMap()
{
int		ii;
int		portNum;
int		pinMask;
int		pinNum;
int		timerNum;
char	textString[32];

	PrintFromPROGMEM(gTextMsg_CPU_Type);
	PrintFromPROGMEM(gTextMsg_CPU_Name);
	Serial.println();

	for (ii = 0; ii<= kDigitalPinCount; ii++)
	{

		portNum		=	digitalPinToPort(ii);
		pinMask		=	digitalPinToBitMask(ii);
		timerNum	=	digitalPinToTimer(ii);

		//*	figure out the pin number from the mask
		pinNum	=	0;
		while (pinMask != 0)
		{
			pinNum++;
			pinMask	=	pinMask >> 1;
		}
		pinNum--;

		sprintf(textString, "Digital pin %2d = %c %2X", ii, (0x40 + portNum), pinNum);
		Serial.print(textString);
		if (timerNum != NOT_ON_TIMER)
		{
			sprintf(textString, "  Timer %d", timerNum);
			Serial.print(textString);
		}
		if (ii == kRXD_pin)
		{
			PrintFromPROGMEM(gTextMsg_RX_DATA);
		}
		if (ii == kTXD_pin)
		{
			PrintFromPROGMEM(gTextMsg_TX_DATA);
		}
		if (ii >= kDigitalPin_FirstAnalog)
		{
			PrintFromPROGMEM(gTextMsg_AnalogIN);
			Serial.print(ii - kDigitalPin_FirstAnalog);
		}
		Serial.println();
	}
}


//************************************************************************
void PlayTone()
{
#ifdef __AVR_ATmega644__
	pinMode(SPEAKER_PIN1, OUTPUT);
	pinMode(SPEAKER_PIN2, OUTPUT);
	digitalWrite(SPEAKER_PIN1, LOW);
	tone(SPEAKER_PIN2, 600, 500);
#else
	Serial.println("Tone not supported");
#endif

}


//************************************************************************
void BlinkLED()
{
#ifdef kLED_PIN
	Serial.println("LED should be blinking");

	pinMode(kLED_PIN, OUTPUT);
	while (!Serial.available())
	{
		digitalWrite(kLED_PIN, HIGH);
		delay(200);
		digitalWrite(kLED_PIN, LOW);
		delay(200);
	}
	pinMode(kLED_PIN, INPUT);
#else

	Serial.println("LED Blink not supported");
#endif

}


//************************************************************************
void	CheckOneInput(int inputNum)
{
int	inputState;

	inputState	=	digitalRead(inputNum);
	
	if (inputState != gButtonState[inputNum])
	{
		PrintFromPROGMEM(gTextMsg_DIGITALPIN);
		Serial.print(inputNum);
		Serial.print(" is now ");
		Serial.print(inputState);
		Serial.println();
		
		gButtonState[inputNum]	=	inputState;
	}
}


//************************************************************************
//*	Watch for input changes
void	WatchForInputChange()
{
int	ii;

	while (!Serial.available())
	{
		for (ii = kDigitalPin_First; ii <= kDigitalPin_Last; ii++)
		{
			//*	we dont want to do this on RXD and TXD
			if ((ii != kRXD_pin) && (ii != kTXD_pin))
			{
				CheckOneInput(ii);
			}
		}


	}
}

#pragma mark -


//************************************************************************
void setup()
{
int	ii;

	Serial.begin(9600);
	
	Serial.println();


	PrintFromPROGMEM(gTextMsg_Explorer);
	Serial.println();
	PrintHelp();



	for (ii = kDigitalPin_First; ii <= kDigitalPin_Last; ii++)
	{
		if ((ii != kRXD_pin) && (ii != kTXD_pin))
		{
			pinMode(ii, INPUT);
			digitalWrite(ii, HIGH);	//*	turn on pull up resister
		}
	}

	//*	get the current state of the inputs
	for (ii=0; ii <= kDigitalPinCount; ii++)
	{
		gButtonState[ii]	=	digitalRead(ii);
	}


	//*	put something in RAM so we can verify what we are looking at
	for (ii=0; ii<256; ii++)
	{
		gCharArray[ii]	=	ii;
	}

	gFlashIndex	=	0;


	PrintFromPROGMEM(gTextMsg_Prompt);

#if defined(__AVR_ATmega644__)
	PlayTone();
#endif
}


//************************************************************************
void loop()
{
char	theChar;
	
	if (Serial.available())
	{
		theChar	=	Serial.read();
		if (theChar >= 0x60)
		{
			theChar	=	theChar & 0x5f;	//*	force upper case
		}
		Serial.print(theChar);
		Serial.println();
		switch(theChar)
		{
			case '0':
				gFlashIndex	=	0;
				gRamIndex	=	0;
				break;
			
			case '?':
				PrintCPUstats();
				PrintHelp();
				break;
			
			case 'B':
				BlinkLED();
				break;
				
			case 'E':
				DumpHex(kDUMP_EEPROM, 0, 32);
				break;
			
			case 'F':
				DumpHex(kDUMP_FLASH, gFlashIndex, 16);
				gFlashIndex	+=	256;
				break;
			
			case 'I':
				Wire.begin();
				ScanI2CBus(1, 127);
				break;
			
			case 'M':
				ShowPinMap();
				break;
				
			case 'P':
				ShowOneDigitalPin();
				break;
				
			case 'R':
				DumpHex(kDUMP_RAM, gRamIndex, 16);
				gRamIndex	+=	256;
				break;
			
			case 'S':
				ShowPins();
				break;
			
			case 'T':
				PlayTone();
				break;
				
			case 'W':
				WatchForInputChange();
				break;
				
			case 'Z':
				SetOneAnalogPin();
				break;
				
				
		}
		Serial.println();
		PrintFromPROGMEM(gTextMsg_Prompt);
	}
}