16 x 16 Led Matrix under IR remote control with mouse pad

Just finished it this evening. The video shows 4 seamless cascadable 8x8 led matrix driven by Max7219. I found an IR remote that has a mouse pad on it, so I put these together. It is pretty cool given that it was done in a day, well, with help of LedControl lib.

http://player.youku.com/player.php/sid/XNTA2ODAwNDQ0/v.swf

I am planning to do a game, not sure what though, need some ideas.

Now with sprite drawing with my new led matrix control library that is FAST enough.

Sketch for above demo shown in video

//
//
// Written by Peter Y Lin, a.k.a MJKZZ
//
// Do whatever you want to do with this code but use this code at your own risk
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include "LedMatrix.h"

#define TICK_IR_BREAK		5000
#define TICK_IR_ONE_MIN		400
#define TICK_IR_ONE_MAX		600

#define	MAX_IR_PULSE		24
#define MAX_IR_DATA			8
#define MAX_IR_REPEAT		1
#define	PIN_IR				2

#define IR_CODE_UP			0xC500
#define	IR_CODE_DOWN		0xC480
#define IR_CODE_LEFT		0xC560
#define IR_CODE_RIGHT		0xC460
#define IR_CODE_UPLEFT		0xC562
#define IR_CODE_UPRIGHT		0xC462
#define IR_CODE_DOWNLEFT	0xC566
#define	IR_CODE_DOWNRIGHT	0xC466
#define IR_CODE_UPARROW		0xC590
#define IR_CODE_DOWNARROW	0xC4D0
#define IR_CODE_LEFTARROW	0xC430
#define IR_CODE_RIGHTARROW	0xC420

volatile unsigned int		g_tkPulse	= 0;
volatile unsigned int		g_ctPulse	= 0;
volatile unsigned int		g_arPulse[MAX_IR_PULSE];
volatile unsigned int		g_irCode	= 0;
volatile unsigned int		g_irTemp	= 0;
volatile unsigned int		g_ctCode	= 0;

LedMatrix					ledDisplay	= LedMatrix(5, 6, 7, 16, 16);

//
// This is a bitmap for a sprite
// The first two bytes specify width and height of
// sprite and the rest are bitmaps for sprite
//
byte g_sprite[6] = 
{
	0x03,		// width
	0x04,		// height
	0b10110000, 
	0b01001000, 
	0b01000100,
	0b10100010,
};

volatile unsigned char		g_x		= 0;
volatile unsigned char		g_y		= 0;

void isr_ir()
{
	g_tkPulse	= TCNT1;
	TCNT1		= 0;

	if (g_tkPulse > TICK_IR_BREAK)
	{		
		g_ctPulse = 0;
	}
	else if (g_ctPulse < MAX_IR_PULSE)
	{
		g_arPulse[g_ctPulse] = g_tkPulse;
		g_ctPulse++;

		if (g_ctPulse == 16)
		{
			g_irTemp = 0;
			for(int i=0; i<g_ctPulse; i++)
			{
				if (g_arPulse[i] > TICK_IR_ONE_MIN && g_arPulse[i] < TICK_IR_ONE_MAX)
				{
					g_irTemp |= 1;
				}
				g_irTemp = g_irTemp << 1;
			}

			if (g_irTemp == g_irCode)
			{
				if (g_ctCode < MAX_IR_REPEAT)
				{
					g_ctCode++;
				}
			}
			else
			{
				g_ctCode = 1;
			}
			g_irCode = g_irTemp;
		}
	}
}

void setup()
{
	Serial.begin(115200);

	TCCR1A = 0b00000000;
	TCCR1B = 0b00000011;    // Clk*64 = 4uS
	TCCR1C = 0b00000000;

	pinMode(PIN_IR, INPUT);
	attachInterrupt(0, isr_ir, FALLING);

	ledDisplay.init(8);
	ledDisplay.blank();
	ledDisplay.sprite(g_x, g_y, (const char *)g_sprite, 6, GRAPHIC_DRAW_SRC);

	ledDisplay.update();
}

void loop()
{
	if (g_ctCode == MAX_IR_REPEAT)
	{
		//Serial.print("Code = ");
		//Serial.println(g_irCode, HEX);
		ledDisplay.sprite(g_x, g_y, (const char *)g_sprite, 6, GRAPHIC_DRAW_XOR);

		switch(g_irCode)
		{
		case IR_CODE_LEFT:
		case IR_CODE_LEFTARROW:
			if (g_x)
			{
				g_x--;
			}
			break;
		case IR_CODE_RIGHT:
		case IR_CODE_RIGHTARROW:
			if (g_x < ledDisplay.getWidth()-3)
			{
				g_x++;
			}
			break;
		case IR_CODE_UP:
		case IR_CODE_UPARROW:
			if (g_y)
			{
				g_y--;
			}
			break;
		case IR_CODE_DOWN:
		case IR_CODE_DOWNARROW:
			if (g_y < ledDisplay.getHeight()-4)
			{
				g_y++;
			}
			break;
		case IR_CODE_UPLEFT:
			if (g_y)
			{
				g_y--;
			}
			if (g_x)
			{
				g_x--;
			}
			break;
		case IR_CODE_UPRIGHT:
			if (g_y)
			{
				g_y--;
			}
			if (g_x < ledDisplay.getWidth()-3)
			{
				g_x++;
			}
			break;
		case IR_CODE_DOWNLEFT:
			if (g_y < ledDisplay.getHeight()-4)
			{
				g_y++;
			}
			if (g_x)
			{
				g_x--;
			}
			break;
		case IR_CODE_DOWNRIGHT:
			if (g_y < ledDisplay.getHeight()-4)
			{
				g_y++;
			}
			if (g_x < ledDisplay.getWidth()-3)
			{
				g_x++;
			}
			break;
		}

		Serial.println(g_x, DEC);

		ledDisplay.sprite(g_x, g_y, (const char *)g_sprite, 6, GRAPHIC_DRAW_SRC);
		ledDisplay.update();
		g_irCode = 0;
		g_ctCode = 0;
	}
}

Very cool. Thanks for sharing!

Geoff

I’m trying the library with your eBay matrix module, i have simplifyed the code for only drawing an expanding / contracting rectangle

#include <avr/io.h>
#include "LedMatrix.h"

LedMatrix  				ledDisplay	= LedMatrix(51, 53, 52, 16, 16);

void setup()
{
  ledDisplay.init(8);
  ledDisplay.blank();
  ledDisplay.update();
  Serial.begin(9600);
}

void loop()
{
  for (int i=0;i<16;i++) {
   ledDisplay.rectangle(0,0,i,6,1);
   ledDisplay.update();
   Serial.println(i);
   delay(50);
  }
  for (int i=16;i>0;i--) {
   ledDisplay.rectangle(0,0,i,6,0);
   ledDisplay.update();
   Serial.println(i);
   delay(50);
  }
  ledDisplay.blank();
  ledDisplay.update();
}

I have only 2 modules cascaded,

when matrix is defined 16x16 it work

LedMatrix(51, 53, 52, 16, 16);

when matrix is defined 16x8

LedMatrix(51, 53, 52, 16, 8);

all the two matrix show the same thing and

when matrix is defined 8x16

LedMatrix(51, 53, 52, 8, 16);

only one matrix module (on the left) work.

Probably you not intend develop the library for use it rectangular matrix, but if a day you want make the work… :slight_smile: