I've fixed the lcd_gotoXY function so it works correctly with 20x4 displays, but at the cost of an extra 54 bytes. That's a lot of extra memory for something that not many people will want, so maybe there should be two versions of the function and the correct one is selected at compile time based on the value of LCD_ROWS.
This is the new version of the function:
Code:
void lcd_gotoXY(byte x, byte y)
{
if ( y > LCD_ROWS )
y = LCD_ROWS - 1; // Safety check for calls beyond the LCD
byte row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
byte dr=0x80+x + row_offsets[y];
lcd_commandWrite(dr);
}
8 bytes of that extra volume is the check for calls to a row beyond that allowed for the given LCD size. Without that check in place it's possible for a call to this function to read random memory beyond the end of the offset array, and send that data to the LCD.
This function can probably be optimized but it's working fine for me on a 20x4 and since I'm running on an ATmega1280 with 128K of memory the size doesn't really matter to me. If someone else wants to have a go at putting it on a diet, go for it!