Understanding the LoL Shield Library

After much poking through lots of code (aptly named as it definitely required deciphering), I am finally beginning to understand what is being done by this obscure collection of alien writing (aka bit-wise operators).

if (data==18000){
        run=false;
      }
      
      //This is where the bit-shifting happens to pull out
      //each LED from a row. If the bit is 1, then the LED
      //is turned on, otherwise it is turned off.
      else for (byte led=0; led<14; ++led) {
        if (data & (1<<led)) {
          LedSign::Set(led, line, 1);
        }
        else {
          LedSign::Set(led, line, 0);
        }
		/*
			after reading http://www.arduino.cc/playground/Code/BitMath#bit_pack, the line
			"if (data & (1<<led)) {" finally makes sense;
			shift the binary value 1 to the left by the number of spaces stored in the variable
			"led"
			then perform a bitwise AND on that value and "data"
			if both that position in "data" and the shifted binary value are 1, then it returns true
			and sets the LED at the column "led" and the row "line" to 1 or on
			
			the shifted binary value acts as a selection pointer to the binary value stored
			in the variable "data"
		*/
      }

    }

Again, the link that demystified that one obscure line of code was
http://www.arduino.cc/playground/Code/BitMath#bit_pack

I liken my experience to that of a chimpanzee examining a hand-crank style egg beater, wondering what practical use it could possibly have been made for. However, my "Aha! moment" was priceless! What was once obscure and convoluted has been revealed to be elegant, but I still can't honestly say simple...

Using my new found knowledge, I intend to rework the Font subset of the library, which currently supports only uppercase letters and a few symbols. My version will include 95 characters from ASCII 32 to 126. I will post updates on my progress.

I made bitmap style arrays for the characters and was able to display each character in sequence after some bug hunting. I think I may have stumbled on the reason why the original author could not store both upper case and lowercase letters in his array; I tried to put all 93 characters into one array and got garbage when I tried to display each character in sequence. I did the math, each array element is 9 bytes long and there are 93 (94 if you count a space, ASCII 32) elements. 94 x 9 = 846, just under 1KB.

I split the array up into letters, numbers and symbols, and it worked fine. Go figure.

Here are the array declarations if you care to use them. I took the characters from the character map of a CrystalFontz 634, 4x20 character LCD screen. Each character is 5 pixels wide by 7 pixels tall.

My next task is to string the characters together somehow and then use the bitmap display function to scroll text across the LoL shield.

/*
	Putting all the characters together in one array causes garbage to 
	appear on the screen at random when attempting to display each 
	character in sequence.
*/

/*
//uint16_t letters[] [9] = {
uint16_t BitMap[][9] = {
	{0,14,17,17,17,31,17,17,0}, 	//65, A
	{0,15,17,17,15,17,17,15,0}, 	//66, B
	{0,14,17,1,1,1,17,14,0}, 		//67, C
	{0,7,9,17,17,17,9,7,0}, 		//68, D
	{0,31,1,1,15,1,1,31,0}, 		//69, E
	{0,31,1,1,15,1,1,1,0}, 		//70, F
	{0,14,17,1,29,17,17,30,0}, 	        //71, G
	{0,17,17,17,31,17,17,17,0}, 	//72, H
	{0,14,4,4,4,4,4,14,0}, 		//73, I
	{0,28,8,8,8,8,9,6,0}, 			//74, J
	{0,17,9,5,3,5,9,17,0}, 		//75, K
	{0,1,1,1,1,1,1,31,0}, 			//76, L
	{0,17,27,21,17,17,17,17,0}, 	//77, M
	{0,17,17,19,21,25,17,17,0}, 	//78, N
	{0,14,17,17,17,17,17,14,0}, 	//79, O
	{0,15,17,17,15,1,1,1,0}, 		//80, P
	{0,14,17,17,17,21,9,22,0}, 	        //81, Q
	{0,15,17,17,15,5,9,17,0}, 		//82, R
	{0,30,1,1,14,16,16,15,0}, 		//83, S
	{0,31,4,4,4,4,4,4,0}, 			//84, T
	{0,17,17,17,17,17,17,14,0}, 	//85, U
	{0,17,17,17,17,17,10,4,0}, 	        //86, V
	{0,17,17,17,21,21,21,10,0}, 	//87, W
	{0,17,17,10,4,10,17,17,0}, 	        //88, X
	{0,17,17,17,10,4,4,4,0}, 		//89, Y
	{0,31,16,8,14,2,1,31,0}, 		//90, Z
	{0,0,0,14,16,30,17,30,0}, 		//97,  a
	{0,1,1,13,19,17,17,15,0}, 		//98,  b
	{0,0,0,14,1,1,17,14,0}, 		//99,  c
	{0,16,16,22,25,17,17,30,0}, 	//100, d
	{0,0,0,14,17,31,1,14,0}, 		//101, e
	{0,12,18,2,7,2,2,2,0}, 		//102, f
	{0,0,30,17,17,30,16,14,0}, 	        //103, g
	{0,1,1,13,19,17,17,17,0}, 		//104, h
	{0,4,0,6,4,4,4,14,0}, 			//105, i
	{0,8,0,12,8,8,9,6,0}, 			//106, j
	{0,1,1,9,5,3,5,9,0}, 			//107, k
	{0,6,4,4,4,4,4,14,0}, 			//108, l
	{0,0,0,10,21,21,21,21,0}, 		//109, m
	{0,0,0,13,19,17,17,17,0}, 		//110, n
	{0,0,0,14,17,17,17,14,0}, 		//111, o
	{0,0,0,15,17,15,1,1,0}, 		//112, p
	{0,0,0,14,9,14,8,24,0}, 		//113, q
	{0,0,0,13,19,1,1,1,0}, 		//114, r
	{0,0,0,14,1,14,16,15,0}, 		//115, s
	{0,2,2,7,2,2,18,12,0}, 		//116, t
	{0,0,0,17,17,17,25,22,0}, 		//117, u
	{0,0,0,17,17,17,10,4,0}, 		//118, v
	{0,0,0,17,17,21,21,10,0}, 		//119, w
	{0,0,0,17,10,4,10,17,0}, 		//120, x
	{0,0,0,17,17,30,16,14,0}, 		//121, y
	{0,0,0,31,8,4,2,31,0}, 		//122, z
	{18000}
};
*/

/*
uint16_t numbers [][9] = {
//uint16_t BitMap[][9] = {
	{0,14,17,25,21,19,17,14,0}, 	//48, 0
	{0,4,6,4,4,4,4,14,0}, 			//49, 1
	{0,14,17,16,8,4,2,31,0}, 		//50, 2
	{0,31,8,4,8,16,17,14,0}, 		//51, 3
	{0,8,12,10,9,31,8,8,0}, 		//52, 4
	{0,31,1,15,16,16,17,14,0},     	//53, 5
	{0,12,2,1,15,17,17,14,0}, 		//54, 6
	{0,31,16,8,4,2,2,2,0}, 		//55, 7
	{0,14,17,17,14,17,17,14,0}, 	//56, 8
	{0,14,17,17,30,16,8,6,0}, 		//57, 9
	{18000}
};
*/

//uint16_t symbols [][9] = {
uint16_t BitMap[][9] = {
	{0,4,4,4,4,4,0,4,0}, 			//33, !
	{0,10,10,10,0,0,0,0,0}, 		//34, "
	{0,10,10,31,10,31,10,10,0}, 	//35, #
	{0,4,30,5,14,20,15,4,0}, 		//36, $
	{0,3,19,8,4,2,25,24,0}, 		//37, %
	{0,6,9,5,2,21,9,22,0}, 		//38, &
	{0,6,4,2,0,0,0,0,0}, 			//39, '
	{0,8,4,2,2,2,4,8,0}, 			//40, (
	{0,2,4,8,8,8,4,2,0}, 			//41, )
	{0,0,4,21,14,21,4,0,0}, 		//42, *
	{0,4,4,31,4,4,0,0,0}, 			//43, +
	{0,0,0,0,6,4,2,0,0}, 			//44, ,
	{0,0,0,0,31,0,0,0,0}, 			//45, -
	{0,0,0,0,0,0,6,6,0}, 			//46, .
	{0,0,16,8,4,2,1,0,0}, 			//47, /
	{0,6,6,0,6,6,0,0,0}, 			//58, :
	{0,6,6,0,6,4,2,0,0}, 			//59, ;
	{0,8,4,2,1,2,4,8,0}, 			//60, <
	{0,0,31,0,31,0,0,0,0}, 		//61, =
	{0,2,4,8,16,8,4,2,0}, 			//62, >
	{0,14,17,16,8,4,0,4,0}, 		//63, ?
	{0,14,17,25,21,29,1,14,0}, 	        //64, @
	{0,14,2,2,2,2,2,14,0}, 		//91, [
	{0,0,1,2,4,8,16,0,0}, 			//92, backslash, 
	//putting in an actual backslash character in this comment prevents 
	//the next character from showing
	{0,14,8,8,8,8,8,14,0}, 		//93, ]
	{0,4,10,17,0,0,0,0,0}, 		//94, ^
	{0,0,0,0,0,0,0,31,0}, 			//95, _
	{0,2,4,8,8,0,0,0,0}, 			//96, `
	{0,8,4,4,2,4,4,8,0}, 			//123, {
	{0,4,4,4,0,4,4,4,0}, 			//124, |
	{0,2,4,4,8,4,4,2,0}, 			//125, }
	{0,0,2,21,8,0,0,0,0}, 			//126, ~
	{18000}
};

I recently saw the video at Arduino LoL Shield improved scaning - YouTube and downloaded the zip file that ikkei3 posted in the comments.

http://web.mac.com/kxm_ikkei/Si­te/LoL_files/LoL_Shield-100913­.zip

Upon examining his version of Font.cpp, I found that he had created a character set based on columns, not rows like in the example included with the library.

I also went through the code and figured out just what everything did and made clear comments about what was going on. It's too big to put in a code block here so here is a link to my edited version:

Font.cpp