ArMF Imbue: First Look

No need for a new level.

Eric, I also have a spare board here from the prototype run. :wink:

I believe this board doesnā€™t have the caps swapped out for the RTC to work properly but other than that everything is online. Drop me an email if youā€™re interested

seems kickstarter is not usable with a german bank account :frowning:
is that right ??

Iā€™m not sure about the back account but they do accept PayPal these days.
[Correction] They accept Amazon Payments

Remember that link I have up right now is only a preview. The project will not be live until approved by the admins over there. :wink:

@ Skewworks:

Your project is extremely interesting, but there is one claim that I find somewhat difficult to believe: that the VCPU runs as if it were a 117 MHz ā€œArduinoā€.

Given that the VCPU is implemented in NETMF (by which I assume you mean managed code), which is already interpreted, and therefore much slower than native code, and the chip is only 168 MHz to begin with, and generally CPU emulation is done at a fraction of the host CPUā€™s speed, it is my opinion that this statement will need some justification.

But I am a sourpuss like that.

Youā€™re forgetting RLPLite. :wink:

Graphics is also done almost exclusively in RLP.

That said 30% overhead is a rough estimate. Itā€™s not stated on the KickStarter and I would need to run a battery of tests to give an exact overhead amount.

So, when you say NETMF, you mean native code?

Still, 70% of native speed is, frankly, incredible, even if the CPU wasnā€™t doing much else.

Iā€™m willing to believe Iā€™m wrongā€¦

Iā€™ll do my best to create some tests over the next coming weeks. Honestly though, Iā€™m extremely overburdened at the moment.

The way I arrived at the estimate is assuming a default overhead for RLP calls and how many operations I would need to do on the RLP side to perform an average operation from the instruction set.

If you look at the code for Pyxis Oneā€™s VCPU you should have a pretty good idea of the costs as this is based on it.

To give you a better idea, this is an extracted portion of the P1VCPU

void	Pyxis::runPXE(char* filename)
{
	int		x1,y1,x2,y2,x3,y3;
	long	lTemp,l;
	int		iTemp,i;
	long	lRet;					// Call/Return
	long	registers[31];			// Registers
	unsigned long int acc = 0;		// Accumulator
	unsigned long int fileSize;		// Actual Size of File
	unsigned long int pxefileSize;	// Actual Size of File called by PXE
	unsigned char *buffer;			// uSD Read Buffer
	unsigned char *sdString;			// uSD Read Buffer
	unsigned char res;				// Result
	bool bRes;
	char*	string;
	uint8_t	vRAM[2048];				// Virtual RAM for Programs

	registers[0] = 0;
	registers[1] = 2048;
	registers[2] = 2048;

	// Open the file
	res = SD.openFileRead(filename, 3, &fileSize);
	if (res != 0) return;

	// Seek to Start
	SD.seek(3,0);

	buffer = (unsigned char*)malloc(31);

	while(1)
	{
		// Check Accumulator
		if (acc >= fileSize)
		{
			return;
		}

		// Read the command
		while(1)
		{
			res = SD.read(3,buffer,4);
			if (res == 0) break;
			if (res != 0xD0)
			{
				SD.closeFile(3);
				return;
			}
		}

		/*
		// Uncomment for debugging
		Serial.println("");
		Serial.print("(");
		Serial.print(acc);
		Serial.print(")");
		Serial.print("COMMAND: 0x");
		Serial.print(buffer[0],HEX);
		Serial.print(" 0x");
		Serial.print(buffer[1],HEX);
		Serial.print(" 0x");
		Serial.print(buffer[2],HEX);
		Serial.print(" 0x");
		Serial.println(buffer[3],HEX);
		*/

		switch(buffer[0])
		{
		case 0x00:		// exit
			SD.closeFile(3);
			return;
			break;
		case 0x01:		// xyo
			x1 = registers[buffer[1]];					// 0 - 255 Range
			y1 = registers[buffer[2]];					// 0 - 255 Range
			break;
		case 0x03:		// xyd
			x2 = registers[buffer[1]];					// 0 - 255 Range
			y2 = registers[buffer[2]];					// 0 - 255 Range
			break;
		case 0x05:		// dly
			delay(registers[buffer[1]]);								// Register
			break;
		case 0x06:		// xyt
			x3 = registers[buffer[1]];					// 0 - 255 Range
			y3 = registers[buffer[2]];					// 0 - 255 Range
			break;
		case 0x08:		// bcol
			LCD.backcolor(registers[buffer[1]],registers[buffer[2]],registers[buffer[3]]);
			break;
		case 0x09:		// fcol
			LCD.forecolor(registers[buffer[1]],registers[buffer[2]],registers[buffer[3]]);
			break;
		case 0x0A:		// mov
			registers[buffer[1]] = registers[buffer[2]];
			break;
		case 0x0B:		// sbyt
			vRAM[registers[buffer[1]]] = BYTELOW(registers[buffer[2]]);
			break;
		case 0x0C:		// swrd
			vRAM[registers[buffer[1]]]		= BYTEHIGH(registers[buffer[2]]);
			vRAM[registers[buffer[1]]+1]	= BYTELOW (registers[buffer[2]]);
			break;
		case 0x0D:		// slng
			vRAM[registers[buffer[1]]]		= WORDHIGH_BYTEHIGH(registers[buffer[2]]);
			vRAM[registers[buffer[1]]+1]	= WORDHIGH_BYTELOW (registers[buffer[2]]);
			vRAM[registers[buffer[1]]+2]	= WORDLOW_BYTEHIGH (registers[buffer[2]]);
			vRAM[registers[buffer[1]]+3]	= WORDLOW_BYTELOW  (registers[buffer[2]]);
			break;
		case 0x0E:		// lbyt
			registers[buffer[1]] = vRAM[registers[buffer[2]]];
			break;
		case 0x0F:		// lwrd
			WORDHIGH_BYTEHIGH(registers[buffer[1]]) = 0;
			WORDHIGH_BYTELOW (registers[buffer[1]]) = 0;
			WORDLOW_BYTEHIGH (registers[buffer[1]]) = vRAM[registers[buffer[2]]];
			WORDLOW_BYTELOW  (registers[buffer[1]]) = vRAM[registers[buffer[2]]+1];
			break;
		case 0x10:		// llng
			WORDHIGH_BYTEHIGH(registers[buffer[1]]) = vRAM[registers[buffer[2]]];
			WORDHIGH_BYTELOW (registers[buffer[1]]) = vRAM[registers[buffer[2]]+1];
			WORDLOW_BYTEHIGH (registers[buffer[1]]) = vRAM[registers[buffer[2]]+2];
			WORDLOW_BYTELOW  (registers[buffer[1]]) = vRAM[registers[buffer[2]]+3];
			break;
		case 0x11:		// inc
			registers[buffer[1]]++;
			break;
		case 0x12:		// dec
			registers[buffer[1]]--;
			break;
		case 0x13:		// add
			registers[buffer[1]] = registers[buffer[2]] + registers[buffer[3]];
			break;
		case 0x14:		// addi
			registers[buffer[1]] = registers[buffer[2]] + buffer[3];
			break;
		case 0x15:		// sub
			registers[buffer[1]] = registers[buffer[2]] - registers[buffer[3]];
			break;
		case 0x16:		// subi
			registers[buffer[1]] = registers[buffer[2]] - buffer[3];
			break;
		case 0x17:		// mul
			registers[buffer[1]] = registers[buffer[2]] * registers[buffer[3]];
			break;
		case 0x18:		// muli
			registers[buffer[1]] = registers[buffer[2]] * buffer[3];
			break;
		case 0x19:		// div
			registers[buffer[1]] = registers[buffer[2]] / registers[buffer[3]];
			break;
		case 0x1A:		// divi
			registers[buffer[1]] = registers[buffer[2]] / buffer[3];
			break;
		case 0x1B:		// bor
			registers[buffer[1]] = (registers[buffer[1]] == 1) ? 0 : 1;
			break;
		case 0x1E:		// call
			// Store ACC
			lRet = acc + 4;
			// Set New ACC
			WORDHIGH_BYTEHIGH(lTemp) = 0;
			WORDHIGH_BYTELOW (lTemp) = 0;
			WORDLOW_BYTEHIGH (lTemp) = buffer[1];
			WORDLOW_BYTELOW  (lTemp) = buffer[2];
			lTemp = lTemp * 4; // 4 Bytes per line, jump given in lines
			if (buffer[3] == 0)
			{
				acc = acc + lTemp;
			}
			else
			{
				acc = acc - lTemp;
			}
			// First go to beginning of file
			if (SD.seek(3,0) != 0) return;
			
			// Now seek to where we need to be
			if (SD.seek(3,acc) != 0) return;

			// We'll be adding 4 after this so subtract 4 to stay ahead
			acc = acc - 4;

			break;
		case 0x1F:		// beq
			if (registers[buffer[1]] == registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}

			break;
		case 0x20:		// bneq
			if (registers[buffer[1]] != registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}
			break;
		case 0x21:		// blt
			if (registers[buffer[1]] < registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}
			break;
		case 0x22:		// blte
			if (registers[buffer[1]] <= registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}
			break;
		case 0x23:		// bgt
			if (registers[buffer[1]] > registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}
			break;
		case 0x24:		// bgte
			if (registers[buffer[1]] >= registers[buffer[2]])
			{
				// BRANCH
				if (buffer[3] == 0)
				{
					acc = (registers[1] * 4);
				}
				else
				{
					acc = (registers[1] * 4) - 8;
				}

				// First go to beginning of file
				if (SD.seek(3,0) != 0) return;
				
				// Now seek to where we need to be
				if (SD.seek(3,acc) != 0) return;

				// We'll be adding 4 after this so subtract 4 to stay ahead
				acc = acc - 4;
			}
			break;
		case 0x25:		// jump
			// Set New ACC
			WORDHIGH_BYTEHIGH(lTemp) = 0;
			WORDHIGH_BYTELOW (lTemp) = 0;
			WORDLOW_BYTEHIGH (lTemp) = buffer[1];
			WORDLOW_BYTELOW  (lTemp) = buffer[2];
			lTemp = lTemp * 4;
			if (buffer[3] == 0)
			{
				acc = acc + lTemp;
			}
			else
			{
				acc = acc - lTemp;
			}

			// First go to beginning of file
			if (SD.seek(3,0) != 0) return;
			
			// Now seek to where we need to be
			if (SD.seek(3,acc) != 0) return;

			// We'll be adding 4 after this so subtract 4 to stay ahead
			acc = acc - 4;
			break;
		case 0x26:		// return
			// First go to beginning of file
			if (SD.seek(3,0) != 0) return;
			
			// Now seek to where we need to be
			if (SD.seek(3,lRet) != 0) return;

			// We'll be adding 4 after this so subtract 4 to stay ahead
			acc = lRet - 4;
			break;
		case 0x27:		// LCD extension function
			switch(buffer[1])
			{
			case 0x0A:	// cls
				LCD.cls();
				break;
			case 0x0B:	// scrm (landscape)
				LCD.landscapeMode();
				break;
			case 0x0C:	// scrm (portrait)
				LCD.portraitMode();
				break;
			case 0x0D:	// smoothing mode
				LCD.smoothingMode(registers[buffer[1]]);
				break;
			case 0x20:	// dln
				LCD.drawLine(x1,y1,x2,y2);
				break;
			case 0x21:	// drct
				LCD.drawRect(x1,y1,x2,y2);
				break;
			case 0x22:	// delp
				LCD.drawEllipse(x1,y1,x2,y2);
				break;
			case 0x25:	// dtri
				LCD.drawTriangle(x1,y1,x2,y2,x3,y3);
				break;
			case 0x26:	// frct
				LCD.fillRect(x1,y1,x2,y2);
				break;
			case 0x27:	// felp
				LCD.fillEllipse(x1,y1,x2,y2);
				break;
			case 0x2A:	// ftri
				LCD.fillTriangle(x1,y1,x2,y2,x3,y3);
				break;
			case 0x53:	// dwin
				string = stringFromAddress(registers[buffer[2]],acc+4);
				LCD.drawWindow(string,x1,y1,x2,y2,232,232,232);
				free(string);
				LCD.backcolor(232,232,232);
				break;
			case 0x60:	// sfnt
				LCD.setFont(registers[buffer[1]]);
				break;
			case 0x61:	// dvar
				lTemp = registers[1];

				switch(buffer[3])
				{
				case 0:		// Byte OR Value
					if (buffer[2] == 0)
					{
						// This is a value
						LCD.drawString(lTemp,x1,y1);
					}
					else
					{
						LCD.setPosition(x1,y1);
						for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
						{
							if (i != 0) LCD.drawString(", ");	// It's an array, separate value
							LCD.drawString((int)vRAM[lTemp]);
							lTemp++;
						}
					}
					break;
				case 1:		// Boolean
					LCD.setPosition(x1,y1);
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) LCD.drawString(", ");	// It's an array, separate value
						LCD.drawString((vRAM[lTemp] == 0) ? (char*)"false" : (char*)"true");
						lTemp++;
					}
					break;
				case 2:		// Character
					LCD.setPosition(x1,y1);
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (vRAM[lTemp] == 0) break;
						LCD.drawChar(vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 3:		// Int
					LCD.setPosition(x1,y1);
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) LCD.drawString(", ");	// It's an array, separate value
						BYTEHIGH(iTemp) = vRAM[lTemp];
						BYTELOW (iTemp) = vRAM[lTemp + 1];
						LCD.drawString((int)iTemp);
						lTemp+=2;
					}
					break;
				case 4:		// Long
					LCD.setPosition(x1,y1);
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) LCD.drawString(", ");	// It's an array, separate value
						WORDHIGH_BYTEHIGH(l) = vRAM[lTemp];
						WORDHIGH_BYTELOW (l) = vRAM[lTemp+1];
						WORDLOW_BYTEHIGH (l) = vRAM[lTemp+2];
						WORDLOW_BYTELOW  (l) = vRAM[lTemp+3];
						LCD.drawString((long)l);
						lTemp+=4;
					}
					break;
				}
				break;
			case 0x62:	// dstr
				string = stringFromAddress(registers[buffer[2]],acc+4);
				LCD.drawString(string,x1,y1);
				free(string);
				break;
			default:
				break;
			}
			break;
		case 0x28:		// pmode
			pinMode(registers[buffer[1]],buffer[2]);
			break;
		case 0x29:		// dwrt
			digitalWrite(registers[buffer[1]],registers[buffer[2]]);
			break;
		case 0x2A:		// dread
			lTemp = registers[buffer[2]];				// Get the Variable Address
			switch(buffer[3])							// Store the Value by Type Size
			{
			case 1:		// Boolean,Byte,Character
				vRAM[lTemp] = digitalRead(registers[buffer[1]]);
				break;
			case 2:		// Integer
				vRAM[lTemp] = 0;
				vRAM[lTemp+1] = digitalRead(registers[buffer[1]]);
				break;
			case 4:		// Long
				vRAM[lTemp] = 0;
				vRAM[lTemp+1] = 0;
				vRAM[lTemp+2] = 0;
				vRAM[lTemp+3] = digitalRead(registers[buffer[1]]);
				break;
			}
		case 0x2B:		// awrt
			analogWrite(registers[buffer[1]],registers[buffer[2]]);
			break;
		case 0x2C:		// aread
			lTemp = registers[buffer[2]];				// Get the Variable Address
			iTemp = analogRead(registers[buffer[1]]);
			switch(buffer[3])							// Store the Value by Type Size
			{
			case 1:		// Boolean,Byte,Character
				vRAM[lTemp] = BYTELOW (iTemp);
				break;
			case 2:		// Integer
				vRAM[lTemp] = BYTEHIGH(iTemp);
				vRAM[lTemp+1] = BYTELOW (iTemp);
				break;
			case 4:		// Long
				vRAM[lTemp] = 0;
				vRAM[lTemp+1] = 0;
				vRAM[lTemp+2] = BYTEHIGH(iTemp);
				vRAM[lTemp+3] = BYTELOW (iTemp);
				break;
			}
		case 0x2D:		// SD Write
			// buffer[1] = variable address
			// buffer[2] = size to write
			// buffer[3] = result variable address
			lTemp = registers[buffer[2]];
			sdString = (unsigned char*)malloc(lTemp);
			for (i = 0; i < lTemp; i++) 
			{
				sdString[i] = (unsigned char)vRAM[registers[buffer[1]] + i];
			}
			iTemp = (int)SD.write(2,sdString,lTemp);
			free(sdString);
			vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
			vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
			break;
		case 0x2E:		// SD Commands
			switch(buffer[1])
			{
			case 0x00:		// sdcf
				SD.seek(2,0);
				SD.closeFile(2);
				break;
			case 0x02:		// sdgn
				sdString = (unsigned char*)malloc(12);
				iTemp = (int)SD.getCurrentName(sdString);
				lTemp = registers[buffer[2]];
				for (i = 0; i < 13; i++) 
				{
					vRAM[lTemp] = (char)sdString[i];
					lTemp++;
				}
				free(sdString);
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				break;
			case 0x03:		// sdof
				string = (char*)malloc(13);
				for (i = 0; i < 13; i++)
				{
					string[i] = vRAM[registers[buffer[2]] + i];
				}
				iTemp = (int)SD.openFileWrite(string, 2, &pxefileSize);
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				free(string);
				break;
			case 0x07:		// sdsk
				WORDHIGH_BYTEHIGH(lTemp) = 0;
				WORDHIGH_BYTELOW (lTemp) = 0;
				WORDLOW_BYTEHIGH (lTemp) = vRAM[registers[buffer[2]]];
				WORDLOW_BYTELOW  (lTemp) = vRAM[registers[buffer[2]]];
				iTemp = (int)SD.seek(2,lTemp);
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				free(string);
				break;
			case 0x09:		// sdrm
				string = (char*)malloc(13);
				for (i = 0; i < 13; i++)
				{
					string[i] = vRAM[registers[buffer[2]] + i];
				}
				iTemp = (int)SD.deleteEntry(string);
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				free(string);
				break;
			case 0x0A:		// sdmk
				string = (char*)malloc(13);
				for (i = 0; i < 13; i++)
				{
					string[i] = vRAM[registers[buffer[2]] + i];
				}
				iTemp = (int)SD.createDirectory(string);
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				free(string);
				break;
			case 0x0C:		// sddr
				l = registers[buffer[2]];
				iTemp = (int)SD.dir(0);
				for (i = 1; i < l; i++)
				{
					iTemp = (int)SD.dir(1);
				}
				vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
				vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
				break;
			}
			break;
		case 0x2F:		// SD Read
			// buffer[1] = variable address
			// buffer[2] = size to write
			// buffer[3] = result variable address
			lTemp = registers[buffer[2]];
			sdString = (unsigned char*)malloc(lTemp);
			iTemp = (int)SD.write(2,sdString,lTemp);
			for (i = 0; i < lTemp; i++) 
			{
				vRAM[registers[buffer[1]]] = (char)sdString[i];
			}
			free(sdString);
			vRAM[registers[buffer[3]]] = BYTEHIGH(iTemp);
			vRAM[registers[buffer[3]]+1] = BYTELOW (iTemp);
			break;
		case 0x30:		// la
			BYTEHIGH(iTemp) = buffer[2];				// Address Byte 1
			BYTELOW (iTemp) = buffer[3];				// Address Byte 2 (Max Range 0 - 65535)
			if (buffer[1] > 0) registers[buffer[1]] = iTemp;
			break;
		case 0x31:		// li
			iTemp = 0;
			BYTEHIGH(iTemp) = buffer[2];
			BYTELOW (iTemp) = buffer[3];
			if (buffer[1] > 0) registers[buffer[1]] = iTemp;
			break;
		case 0x32:		// lwu
			break;
		case 0x33:		// lwui
			WORDHIGH_BYTEHIGH(registers[buffer[1]]) = buffer[2];
			WORDHIGH_BYTELOW (registers[buffer[1]]) = buffer[3];
			break;
		case 0x34:		// lwl
			break;
		case 0x35:		// lwli
			WORDLOW_BYTEHIGH(registers[buffer[1]]) = buffer[2];
			WORDLOW_BYTELOW (registers[buffer[1]]) = buffer[3];
			break;
		case 0x36:		// lar
			// buffer[1] = Variable Address Register
			// buffer[2] = Variable Length Register
			// buffer[3] = Disk Address
			string = stringFromAddress(registers[buffer[3]],acc+4,registers[buffer[2]]);
			for (i = 0; i < registers[buffer[2]]; i++)
			{
				vRAM[registers[buffer[1]] + i] = string[i];
			}
			free(string);
			break;
		case 0x40:		// s0pl
			WORDHIGH_BYTEHIGH(l) = 0;
			WORDHIGH_BYTELOW (l) = buffer[1];
			WORDLOW_BYTEHIGH (l) = buffer[2];
			WORDLOW_BYTELOW  (l) = buffer[3];
			string = stringFromAddress(l,acc+4);
			Serial.print(string);
			free(string);
			break;
		case 0x41:		// s0p
			lTemp = registers[buffer[1]];	// Address for Variable

			if (buffer[2] == 0 && buffer[3] == 0)
			{
				// We're printing a register's value
				Serial.print(lTemp);
			}
			else
			{
				switch(buffer[3])		// Variable Type
				{
				case 0:		// Byte
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial.print(", ");	// It's an array, separate value
						Serial.print((int)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 1:		// Boolean
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial.print(", ");	// It's an array, separate value
						Serial.print((vRAM[lTemp] == 0) ? "false" : "true");
						lTemp++;
					}
					break;
				case 2:		// Character
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						Serial.print((char)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 3:		// Int
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial.print(", ");	// It's an array, separate value
						BYTEHIGH(iTemp) = vRAM[lTemp];
						BYTELOW (iTemp) = vRAM[lTemp + 1];
						Serial.print((int)iTemp);
						lTemp+=2;
					}
					break;
				case 4:		// Long
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial.print(", ");	// It's an array, separate value
						WORDHIGH_BYTEHIGH(l) = vRAM[lTemp];
						WORDHIGH_BYTELOW (l) = vRAM[lTemp+1];
						WORDLOW_BYTEHIGH (l) = vRAM[lTemp+2];
						WORDLOW_BYTELOW  (l) = vRAM[lTemp+3];
						Serial.print((long)l);
						lTemp+=4;
					}
					break;
				}
			}
			break;
		case 0x42:		// s0pln
			Serial.println("");
			break;
		case 0x43:		// s1pl
			WORDHIGH_BYTEHIGH(l) = 0;
			WORDHIGH_BYTELOW (l) = buffer[1];
			WORDLOW_BYTEHIGH (l) = buffer[2];
			WORDLOW_BYTELOW  (l) = buffer[3];
			string = stringFromAddress(l,acc+4);
			Serial1.print(string);
			free(string);
			break;
		case 0x44:		// s1p
			lTemp = registers[buffer[1]];	// Address for Variable

			if (buffer[2] == 0 && buffer[3] == 0)
			{
				// We're printing a register's value
				Serial1.print(lTemp);
			}
			else
			{
				switch(buffer[3])		// Variable Type
				{
				case 0:		// Byte
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial1.print(", ");	// It's an array, separate value
						Serial1.print((int)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 1:		// Boolean
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial1.print(", ");	// It's an array, separate value
						Serial1.print((vRAM[lTemp] == 0) ? "false" : "true");
						lTemp++;
					}
					break;
				case 2:		// Character
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						Serial1.print((char)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 3:		// Int
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial1.print(", ");	// It's an array, separate value
						BYTEHIGH(iTemp) = vRAM[lTemp];
						BYTELOW (iTemp) = vRAM[lTemp + 1];
						Serial1.print((int)iTemp);
						lTemp+=2;
					}
					break;
				case 4:		// Long
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial1.print(", ");	// It's an array, separate value
						WORDHIGH_BYTEHIGH(l) = vRAM[lTemp];
						WORDHIGH_BYTELOW (l) = vRAM[lTemp+1];
						WORDLOW_BYTEHIGH (l) = vRAM[lTemp+2];
						WORDLOW_BYTELOW  (l) = vRAM[lTemp+3];
						Serial1.print((long)l);
						lTemp+=4;
					}
					break;
				}
			}
			break;
		case 0x45:		// s1pln
			Serial1.println("");
			break;
		case 0x46:		// s2pl
			WORDHIGH_BYTEHIGH(l) = 0;
			WORDHIGH_BYTELOW (l) = buffer[1];
			WORDLOW_BYTEHIGH (l) = buffer[2];
			WORDLOW_BYTELOW  (l) = buffer[3];
			string = stringFromAddress(l,acc+4);
			Serial2.print(string);
			free(string);
			break;
		case 0x47:		// s2p
			lTemp = registers[buffer[1]];	// Address for Variable

			if (buffer[2] == 0 && buffer[3] == 0)
			{
				// We're printing a register's value
				Serial2.print(lTemp);
			}
			else
			{
				switch(buffer[3])		// Variable Type
				{
				case 0:		// Byte
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial2.print(", ");	// It's an array, separate value
						Serial2.print((int)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 1:		// Boolean
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial2.print(", ");	// It's an array, separate value
						Serial2.print((vRAM[lTemp] == 0) ? "false" : "true");
						lTemp++;
					}
					break;
				case 2:		// Character
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						Serial2.print((char)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 3:		// Int
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial2.print(", ");	// It's an array, separate value
						BYTEHIGH(iTemp) = vRAM[lTemp];
						BYTELOW (iTemp) = vRAM[lTemp + 1];
						Serial2.print((int)iTemp);
						lTemp+=2;
					}
					break;
				case 4:		// Long
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial2.print(", ");	// It's an array, separate value
						WORDHIGH_BYTEHIGH(l) = vRAM[lTemp];
						WORDHIGH_BYTELOW (l) = vRAM[lTemp+1];
						WORDLOW_BYTEHIGH (l) = vRAM[lTemp+2];
						WORDLOW_BYTELOW  (l) = vRAM[lTemp+3];
						Serial2.print((long)l);
						lTemp+=4;
					}
					break;
				}
			}
			break;
		case 0x48:		// s2pln
			Serial2.println("");
			break;
		case 0x49:		// s3pl
			WORDHIGH_BYTEHIGH(l) = 0;
			WORDHIGH_BYTELOW (l) = buffer[1];
			WORDLOW_BYTEHIGH (l) = buffer[2];
			WORDLOW_BYTELOW  (l) = buffer[3];
			string = stringFromAddress(l,acc+4);
			Serial3.print(string);
			free(string);
			break;
		case 0x4A:		// s3p
			lTemp = registers[buffer[1]];	// Address for Variable

			if (buffer[2] == 0 && buffer[3] == 0)
			{
				// We're printing a register's value
				Serial3.print(lTemp);
			}
			else
			{
				switch(buffer[3])		// Variable Type
				{
				case 0:		// Byte
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial3.print(", ");	// It's an array, separate value
						Serial3.print((int)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 1:		// Boolean
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial3.print(", ");	// It's an array, separate value
						Serial3.print((vRAM[lTemp] == 0) ? "false" : "true");
						lTemp++;
					}
					break;
				case 2:		// Character
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						Serial3.print((char)vRAM[lTemp]);
						lTemp++;
					}
					break;
				case 3:		// Int
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial3.print(", ");	// It's an array, separate value
						BYTEHIGH(iTemp) = vRAM[lTemp];
						BYTELOW (iTemp) = vRAM[lTemp + 1];
						Serial3.print((int)iTemp);
						lTemp+=2;
					}
					break;
				case 4:		// Long
					for (i = 0; i < buffer[2]; i++)		// buffer[2] = size of array
					{
						if (i != 0) Serial3.print(", ");	// It's an array, separate value
						WORDHIGH_BYTEHIGH(l) = vRAM[lTemp];
						WORDHIGH_BYTELOW (l) = vRAM[lTemp+1];
						WORDLOW_BYTEHIGH (l) = vRAM[lTemp+2];
						WORDLOW_BYTELOW  (l) = vRAM[lTemp+3];
						Serial3.print((long)l);
						lTemp+=4;
					}
					break;
				}
			}
			break;
		case 0x4B:		// s3pln
			Serial3.println("");
			break;
		case 0x4C:		// rdbp
			iTemp = Pad.readButtons();
			vRAM[registers[buffer[1]]] =  BYTEHIGH(iTemp);
			vRAM[registers[buffer[1]]+1] = BYTELOW(iTemp);
			break;
		case 0x4D:		// upen
			LCD.updatePen(&bRes,&x2,&x3);
			vRAM[registers[buffer[1]]] = (bRes == false) ? 0 : 1;
			vRAM[registers[buffer[2]]] = BYTEHIGH(x2);
			vRAM[registers[buffer[2]]+1] = BYTELOW(x2);
			vRAM[registers[buffer[3]]] = BYTEHIGH(x3);
			vRAM[registers[buffer[3]]+1] = BYTELOW(x3);
			break;
		default:
			Serial.print("Unknown Command: 0x");
			Serial.println(buffer[0],HEX);
			break;
		}

		acc = acc + 4;
	}
	SD.closeFile(3);

}

The title line on the KickStarter page says ā€œArMF Imbue : An All-In-On For Everyoneā€. I am guessing that it is suppose to be ā€œArMF Imbue : An All-In-One For Everyoneā€. One instead of on.

@ tstewart - good catch! I canā€™t update anything until admins are done but Iā€™ll change it as soon as its unlocked.

Iā€™m with godefroi in that you need to be prepared on day one to explain the details of Arduino running on this since more people will probably come from that camp than any other. There needs to be something in the project description that tells just how Arduino is operating. I think the tendency will be to assume that itā€™s running natively and youā€™ll have a lot of angry customers if they donā€™t figure out until it arrives that itā€™s actually interpreted. I know you say a little about there being a PC app that does some magic but for an Arduino person thatā€™s never run NETMF and doesnā€™t knows that itā€™s interpreted code, theyā€™re just going to assume Arduino runs as theyā€™re used to it running.

Txt me as soon as itā€™s up. I want to be your first supporter :wink:

txt us all ! We all want to be close to Ianā€™s pledge !

Thanks guys will do! Iā€™ll be sure to mention regular Arduino based off the Due could be ported over as well.

Thereā€™s really not a good shot of the back of the board anywhere. Thereā€™s a few quick glimpses in the video but it would be nice to have a good static pic in the Kickstarter somewhere. Will there be an ICSP port?

How much of this will be open sourced? I donā€™t see an OSHW logo anywhere. If the target market is education (universities) then I would think this would be important.

1 Like

Itā€™s open source. You donā€™t have to out a logo on it for it to be. But perhaps Iā€™ll put it on the final board. KS mentions its open source but Iā€™ll try to make it more clear. Iā€™ll also add a pick of the back.

I see the project is live on Kickstarter now!
http://www.kickstarter.com/projects/skewworks/armf-imbue-an-all-in-one-for-everyone?ref=recently_launched

That literally JUST happened; you are beating me to the punch Bob! :wink:

Is your ā€œArduinoā€ compiler/virtual CPU open source?

I had plans to make it so. However the KickStarter seems to be dead in the water so Iā€™m not sure what the future holds for it.