Serial lines, SRAM and odd behavior

Hey Guys,

I’m trying to port some old DOS software that came with a serial printer. The code I have compiles as-is but refuses to do much of anything. My initial thought was that I was running out of SRAM so I moved the font tables into PROGMEM. The code looks like this (complete file is attached, couldn’t post it):

	/***************************************************************************
	 *	This is the data for a sample bitmapped font.  It is included as "C"
	 *	source code to allow it to be readily ported to various systems.
	 ***************************************************************************/

	unsigned char character_65[] =	/* 'A' */
		{
		 56,  27,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
		0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00,
		0x00, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0x80,
		0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F,
		0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00,
		0x00, 0x00, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00,
		0x00, 0x00, 0xE0, 0xBF, 0x03, 0x00, 0x00, 0x00,
		0x00, 0xFC, 0x87, 0x03, 0x00, 0x00, 0x00, 0x80,
		0xFF, 0x80, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x1F,
		0x80, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x80,
		0x03, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x80, 0x03,
		0x00, 0x00, 0x00, 0xC0, 0x1F, 0x80, 0x03, 0x00,
		0x00, 0x00, 0x80, 0xFF, 0x80, 0x03, 0x00, 0x00,
		0x00, 0x00, 0xFE, 0x87, 0x03, 0x00, 0x00, 0x00,
		0x00, 0xF0, 0xBF, 0x03, 0x00, 0x00, 0x00, 0x00,
		0xC0, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
		0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
		0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
		0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x07, 0x00,
		0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x04, 0x00, 
		};


unsigned char *CharTable[] = 
		{
		0,	/* character_0 */
		0,	/* character_1 */
		0,	/* character_2 */
		0,	/* character_3 */
		0,	/* character_4 */
		0,	/* character_5 */
		0,	/* character_6 */
		0,	/* character_7 */
		0,	/* character_8 */
		0,	/* character_9 */
		0,	/* character_10 */
		0,	/* character_11 */
		0,	/* character_12 */
		0,	/* character_13 */
		0,	/* character_14 */
		0,	/* character_15 */
		0,	/* character_16 */
		0,	/* character_17 */
		0,	/* character_18 */
		0,	/* character_19 */
		0,	/* character_20 */
		0,	/* character_21 */
		0,	/* character_22 */
		0,	/* character_23 */
		0,	/* character_24 */
		0,	/* character_25 */
		0,	/* character_26 */
		0,	/* character_27 */
		0,	/* character_28 */
		0,	/* character_29 */
		0,	/* character_30 */
		0,	/* character_31 */
		character_32,
		character_33,
		character_34,
		character_35,
		character_36,
		character_37,
		character_38,
		character_39,
		character_40,
		character_41,
		character_42,
		character_43,
		character_44,
		character_45,
		character_46,
		character_47,
		character_48,
		character_49,
		character_50,
		character_51,
		character_52,
		character_53,
		character_54,
		character_55,
		character_56,
		character_57,
		character_58,
		character_59,
		character_60,
		character_61,
		character_62,
		character_63,
		character_64,
		character_65,
		character_66,
		character_67,
		character_68,
		character_69,
		character_70,
		character_71,
		character_72,
		character_73,
		character_74,
		character_75,
		character_76,
		character_77,
		character_78,
		character_79,
		character_80,
		character_81,
		character_82,
		character_83,
		character_84,
		character_85,
		character_86,
		character_87,
		character_88,
		character_89,
		character_90,
		character_91,
		character_92,
		character_93,
		character_94,
		character_95,
		character_96,
		character_97,
		character_98,
		character_99,
		character_100,
		character_101,
		character_102,
		character_103,
		character_104,
		character_105,
		character_106,
		character_107,
		character_108,
		character_109,
		character_110,
		character_111,
		character_112,
		character_113,
		character_114,
		character_115,
		character_116,
		character_117,
		character_118,
		character_119,
		character_120,
		character_121,
		character_122,
		character_123,
		character_124,
		character_125,
		character_126,
		character_127,
		};




/* global variables */
unsigned char BitBuffer[LABEL_WIDTH][LABEL_HEIGHT];  /* bitmap buffer            */
char EditBuffer[MAX_ROWS][MAX_COLS];        /* editor buffer            */
int xPos, yPos;
int nLabelLines;
int nFontHeight;
int nPrinterModel;

void Send(char ch)
{
	Serial1.write(ch);
}

/***************************************************************************
 *  DrawBitmap
 *
 *  This function copies the bitmap for the specified character from the
 *  font table to the bitmap data buffer.  The character is placed at the
 *  coordinates (xPos, yPos).
 *
 *  Parameters: ch = ASCII character to "draw"
 *
 *  Returns:    TRUE if successful, else FALSE
 ***************************************************************************/
int DrawBitmap(char ch)
{
	unsigned char *pCharData;
	int width, height;
	int w, x, y;

	pCharData = (unsigned char *) CharTable[ch];
	height = (int) *pCharData++;
	width = (int) *pCharData++;
	height = (height + 7) / 8;              /* convert height to bytes */

	if ( width == 0 )                       /* return if invalid char */
		return FALSE;

	if ( xPos + width > LABEL_WIDTH )       /* return if too wide */
		return FALSE;

	if ( yPos + height > LABEL_HEIGHT )     /* return if too tall */
		return FALSE;

	if ( ch != 32 )                         /* don't bitmap spaces */
		{
		/* set absolute limits */
		height += yPos;
		w = width + xPos;

		/* copy the character data to the bitmap buffer */
		for ( x = xPos; x < w; ++x )
			for ( y = yPos; y < height; ++y )
				BitBuffer[x][y] = *pCharData++;
		}

	xPos += width;                          /* update current position */
	return TRUE;                            /* success! */
}

/***************************************************************************
 *  Convert
 *
 *  This function converts the text in the edit buffer to a bitmapped image
 *  in the bitmap buffer.
 *
 *  Parameters: None
 *
 *  Returns:    Nothing
 ***************************************************************************/
void Convert(void)
{
	unsigned char row, col, ch;

	ClearBitmapBuffer();                /* clear out any junk */
	yPos = 0;                           /* start at the top */
	for (row=0; row<nLabelLines; ++row) /* process all rows */
		{
		xPos = 0;                       /* left side of character */
		col = 0;                        /* start with 1st character */
		while ( (ch = EditBuffer[row][col++]) != 0 )
			{
			if ( !DrawBitmap(ch) )      /* add to bitmap buffer */
				break;                  /* break if off the label */
			}

		yPos += nFontHeight;            /* start next line */
		}
}

/***************************************************************************
 *  Print
 *
 *  This function converts the bitmapped image in the bitmap buffer to the
 *  appropriate printer commands.
 *
 *  Parameters: None
 *
 *  Returns:    Nothing
 ***************************************************************************/
void Print(void)
{
	int i, count;
	int x, y;
	unsigned char linebuf[LABEL_HEIGHT];

	Send(CMD_DENSITY);      /* send density prefix          */
	Send(0x80);             /* set "normal" density         */

	Send(CMD_MARGIN);       /* set left margin              */
	Send(0);            /* 0mm for standard size label on narrow printer */
	for ( x = 0; x < LABEL_WIDTH; ++x )
		{
		/* copy data to local buffer and count printable bytes      */
		i = 0;
		count = 0;
		for ( y = LABEL_HEIGHT-1; y >= 0; --y )
			{
			if ( (linebuf[i++] = BitBuffer[x][y]) != 0 )
				count = i;
			}

		if ( count == 0 )               /* any printable data?      */
			{
			Send(CMD_LINEFEED);         /* no, just send line feed  */
			}
		else
			{
			Send(CMD_PRINT);            /* send print command       */
			Send(count);                /* send record size         */

			for ( i = 0; i < count; ++i )
				Send(linebuf[i]);       /* send data to the printer */
			}
		}

	Send(CMD_FORMFEED);                 /* advance label            */
}
boolean done = FALSE;
void loop()
{
	//ClearEditBuffer();
	strcpy(EditBuffer[0], "Smart Label Printer");
	Convert();
	Print();
	done = TRUE;
	Serial.println("Done!");
	delay(2500);
}

any thoughts… ?

sketch_feb07c.pde (101 KB)

Yes you haven't got enough memory.

How much space is this taking:-

unsigned char BitBuffer[LABEL_WIDTH][LABEL_HEIGHT];  /* bitmap buffer            */
char EditBuffer[MAX_ROWS][MAX_COLS];        /* editor buffer            */

so I moved the font tables into PROGMEM

Couldn't spot where you did this.

Sorry… I copied and pasted an older copy. I had switched the whole font table into progmem… attached is a current version that compiles loads and then does the dreaded nothing.

Edit: you’re right. I didnt even notice that was still left in ram. I am however running on a mega 256 (8k of SRAM?).

sketch_feb07c.pde (103 KB)

PROGMEM unsigned char BitBuffer[LABEL_WIDTH][LABEL_HEIGHT]; /* bitmap buffer /

BitBuffer
[j] = (unsigned char) 0;*

_ BitBuffer[y] = *pCharData++;_

  • if ( (linebuf[i++] = BitBuffer[y]) != 0 )[/quote]*
    By declaring BitBuffer as PROGMEM data you are guaranteeing that your Sketch will not work. PROGMEM is read-only. BitBuffer must be read+write.
    The same is true for EditBuffer.
    BitBuffer alone grossly exceeds the amount of SRAM available…
    | LABEL_X_MM | | 81 |
    | - | - | - |
    | LABEL_WIDTH | LABEL_X_MM * 8 | 648 |
    | LABEL_HEIGHT | LABEL_Y_MM | 24 |
    | BitBuffer | [LABEL_WIDTH][LABEL_HEIGHT] | 15552 |

Thanks for the replies guys. I’ve reworked this whole thing, and I’ve got it printing single characters:

This code works:

for (int i = 0; i < CharTable[97][1]; i++)
{
	Serial2.write(0x04);
	Serial2.write(0x07);
	for (int j = 6; j > -1; j--)
	{
		Serial2.write(CharTable[97][j + 7 * i + 2]);
	}
	delay(5);
}
delay(10);
}

but when I try to do something like this I’m crashing the arduino.

for (char charPtr = 33; charPtr < 35; charPtr++)
{
	for (int i = 0; i < CharTable[charPtr][1]; i++)
	{
		Serial2.write(0x04);
		Serial2.write(0x07);
		for (int j = 6; j > -1; j--)
		{
			Serial2.write(CharTable[charPtr][j + 7 * i + 2]);
		}
		delay(5);
	}
        delay(10);
}

am I missing something obvious here?

Thanks
-Alex

sketch_feb11a.pde (92.9 KB)