Difference between revisions of "Wallboard 2.0"

From Randomdata wiki
Jump to: navigation, search
m (Researching)
m (Researching)
Line 39: Line 39:
 
We've opened one of the led boards, and found some interesting strings on the boards themselves, to help us identify the source of the boards and to find others working on it.
 
We've opened one of the led boards, and found some interesting strings on the boards themselves, to help us identify the source of the boards and to find others working on it.
  
- http://forums.bit-tech.net/showthread.php?t=177960 <br>
+
* http://forums.bit-tech.net/showthread.php?t=177960 <br>
- http://www.circuitcellar.com/contests/nxpmbeddesignchallenge/winners/DEs/Abstract_3835-Kalk_DE.pdf <br>
+
* http://www.circuitcellar.com/contests/nxpmbeddesignchallenge/winners/DEs/Abstract_3835-Kalk_DE.pdf <br>
- http://www.circuitcellar.com/contests/nxpmbeddesignchallenge/winners/DEs/NXP3835.zip The .zip contains a .pdf with circuit drawings <br>
+
* http://www.circuitcellar.com/contests/nxpmbeddesignchallenge/winners/DEs/NXP3835.zip --> The .zip contains a .pdf with circuit drawings <br>
  
 
== Arduino code ==
 
== Arduino code ==

Revision as of 21:19, 14 January 2014

A followup project to the reverse engineering of the Wallboard.

Wallboard Reverse Engineering

The first project reverse engineered the Wallboard protocol through a Moxa eth-rs232 controller and a cable. The cable has gone lost unfortunately.

New Project

The new goal is to connect a Wallboard to a Raspberry Pi in some way and make a Wallboard available as a clock with extra functions.

A first attempt was to use the serial interface of the RPi directly. Unfortunately, the RPi only has 3.3V and the Wallboard likes to have 5V for its interface. The end result was that the current Wallboard text was deleted, but nothing else could be gotten out of it.

A next attempt was to create a USB to audio-plug cable. We re-used the cable to the RPi serial, and connected that to a serial cable, and used an FTDI chip to convert it to USB. Using a Python program below we managed to get some text to get displayed on the Wallboard.

We searched on Farnell for parts to make this into a nicer cable, and we actually managed to find just just the right cable. The only problem was that the receive and transmit was swapped (probably). We tested them and confirmed that they did not work out of the box. We swapped the cables and it still did not work.

Whipping out the logic analyser we found that the signal on the transmitting was inverted compared to our previously hacked together cable. Fortunately, this cable has a programmable FTDI chip, which can be reprogrammed using the FT_Prog application from [1]. We successfully inverted the Rx and Tx signals, and we replicated the results from our previously engineered cable.


Python implementation prototype

import serial
a = "\x02\x80\x80\x7e\x03"
port = serial.Serial("/dev/ttyAMA0", baudrate=1200,timeout=1)
port.write(a)
port.close()

Open Problems

  • The text we send is displayed and flashes by very quickly, and repeats very quickly which is not what is supposed to happen.
  • Sometimes the write operation just plainly does nothing or freezes what is there.
  • The Wallboard not only receives bytes, but also sends bytes back. Sometimes it just echoes back what you sent, but other times other stuff gets sent back. We have no idea what that is.


It looks like the reverse engineering was not complete, or has not been documented fully...

Researching

We've opened one of the led boards, and found some interesting strings on the boards themselves, to help us identify the source of the boards and to find others working on it.

Arduino code

Thanx to Mr. Kalk and his project we succeeded in connecting an arduino to one part of the wallboard. We made a simple code with the documentation of Mr. Kalk. We needed to change something due to different IC's on the PCB.

#define MAX_DIGITS 12 //amount of chars possible (matrices)
#define MAX_ROWS 7 //amount of rows possible

#include "matrix.h"

char array[MAX_DIGITS][MAX_ROWS];
unsigned long lastTime;

//pinouts for control
int shiftData = 11;
int shiftClr = 12;
int shiftClock = 13;

// pinouts for data
int row1 = 2;
int row2 = 3;
int row3 = 4;
int row4 = 5;
int row5 = 6;
int row6 = 7;
int row7 = 8;

void setup() {
  pinMode(shiftData, OUTPUT);
  pinMode(shiftClr, OUTPUT);
  pinMode(shiftClock, OUTPUT);
  
  pinMode(row1, OUTPUT);
  pinMode(row2, OUTPUT);
  pinMode(row3, OUTPUT);
  pinMode(row4, OUTPUT);
  pinMode(row5, OUTPUT);
  pinMode(row6, OUTPUT);
  pinMode(row7, OUTPUT);
  
  digitalWrite(shiftClr,HIGH);
}

void loop() {
  lastTime = millis();
  asciiConversion("Random-Data!");   // WERKT !!!
  while (true){        
    displayLeds();
    if(millis() - lastTime > 3000){
      animatie();  
      if(millis() - lastTime > 6000){
        break;
      }      
    }
  }
}

void animatie(){
  String img[4] = {
    "  - OPEN -  ",
    "  / OPEN /  ",
    "  | OPEN |  ",
    "  \\ OPEN \\  "};
  int count = 15;
  for(int i=0;i<count;i++){
    asciiConversion(img[0]);
    displayLeds();
  }
  for(int i=0;i<count;i++){
    asciiConversion(img[1]);
    displayLeds();
  }
  for(int i=0;i<count;i++){
    asciiConversion(img[2]);
    displayLeds();
  }
    for(int i=0;i<count;i++){
    asciiConversion(img[3]);
    displayLeds();
  } 
}

void displayLeds(){
  loadChar();
  delayMicroseconds(700); //Dit bepaalt momenteel hoe goed de tekens zichtbaar zijn.
}

void loadChar(){
  static int rij;
  unsigned char mask;
  boolean data;
  
  digitalWrite(row1, HIGH);
  digitalWrite(row2, HIGH);
  digitalWrite(row3, HIGH);
  digitalWrite(row4, HIGH);
  digitalWrite(row5, HIGH);
  digitalWrite(row6, HIGH);
  digitalWrite(row7, HIGH);
 
  
  rij++;
  if (rij > 6) rij=0;
    for (int x=0; x < ((MAX_DIGITS*5)); x++)
    {
        mask=1<<(x%5);
        data= (((array[(MAX_DIGITS-1)-(x/5)][6-rij]) & mask) > 0) ? 1 : 0;
        digitalWrite(shiftData, data);
        digitalWrite(shiftClock, LOW);
        digitalWrite(shiftClock, HIGH);
    }
    switch(6-rij){
      case 0: digitalWrite(row1, LOW);break;
      case 1: digitalWrite(row2, LOW);break;
      case 2: digitalWrite(row3, LOW);break;
      case 3: digitalWrite(row4, LOW);break;
      case 4: digitalWrite(row5, LOW);break;
      case 5: digitalWrite(row6, LOW);break;
      case 6: digitalWrite(row7, LOW);break;  
    }
    //delay(1000);
}

void asciiConversion(String string){
  char ch; 
  for(int i = 0; i < MAX_DIGITS;i++) 
  {
    ch = string[i]; //input character from string
    ch = ch - 0x20;
    for(int j = 0; j < MAX_ROWS; j++)
     {       
       array[i][j] = character_data[ch][j];
     }  
  }
}

You need the library matrix.h for translating the characters and strings to acceptable HEX code.

/*
*****************************************************************************************
* File: matrix.h  
* Description: ascii table
*
* Copyright 2011 H.Kalk  ALL RIGHTS RESERVED.
*
*****************************************************************************************
*/



/*************************** Supported ASCII characters **************************************

ASCII    CHAR    ASCII    CHAR    ASCII    CHAR    ASCII    CHAR    ASCII    CHAR    ASCII    CHAR
0x20             0x30    0        0x40    @        0x50    P        0x60    `        0x70    p        
0x21    !        0x31    1        0x41    A        0x51    Q        0x61    a        0x71    q        
0x22    "        0x32    2        0x42    B        0x52    R        0x62    b        0x72    r
0x23    #        0x33    3        0x43    C        0x53    S        0x63    c        0x73    s
0x24    $        0x34    4        0x44    D        0x54    T        0x64    d        0x74    t
0x25    %        0x35    5        0x45    E        0x55    U        0x65    e        0x75    u
0x26    &        0x36    6        0x46    F        0x56    V        0x66    f        0x76    v
0x27    '        0x37    7        0x47    G        0x57    W        0x67    g        0x77    w        
0x28    (        0x38    8        0x48    H        0x58    X        0x68    h        0x78    x    
0x29    )        0x39    9        0x49    I        0x59    Y        0x69    i        0x79    y
0x2A    *        0x3A    :        0x4A    J        0x5A    Z        0x6A    j        0x7A    z
0x2B    +        0x3B    ;        0x4B    K        0x5B    [        0x6B    k        0x7B    {
0x2C    ,        0x3C    <        0x4C    L        0x5C    \        0x6C    l        0x7C    |
0x2D    -        0x3D    =        0x4D    M        0x5D    ]        0x6D    m        0x7D    }
0x2E    .        0x3E    >        0x4E    N        0x5E    ^        0x6E    n        0x7E    ~
0x2F    /        0x3F    ?        0x4F    O        0x5F    _        0x6F    o        


****************************** Supported ASCII characters **************************************/

const char character_data[116][7] =
    {
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
        { 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x0C },
        { 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00 },
        { 0x0A, 0x0A, 0x1F, 0x0A, 0x00, 0x0A, 0x0A },
        { 0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04 },
        { 0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03 },
        { 0x0C, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0D },
        { 0x0C, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00 },
        { 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02 },
        { 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08 },
        { 0x00, 0x04, 0x15, 0x0E, 0x15, 0x04, 0x00 },
        { 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00 },
        { 0x00, 0x00, 0x00, 0x00, 0x0C, 0x04, 0x08 },
        { 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 },
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C },
        { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 },

        { 0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E },
        { 0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F },
        { 0x0E, 0x11, 0x01, 0x0E, 0x01, 0x11, 0x0E },
        { 0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02 },
        { 0x1F, 0x10, 0x10, 0x1E, 0x01, 0x11, 0x0E },
        { 0x0E, 0x11, 0x10, 0x1E, 0x11, 0x11, 0x0E },
        { 0x1F, 0x11, 0x01, 0x02, 0x04, 0x04, 0x04 },
        { 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E },
        { 0x0E, 0x11, 0x11, 0x0F, 0x01, 0x11, 0x0E },
        { 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00 },
        { 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x04, 0x08 },
        { 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02 },
        { 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00 },
        { 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08 },
        { 0x0E, 0x11, 0x01, 0x02, 0x04, 0x00, 0x04 },

        { 0x0E, 0x11, 0x01, 0x0D, 0x15, 0x15, 0x0E },
        { 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, 0x11 },
        { 0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E },
        { 0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E },
        { 0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E },
        { 0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F },
        { 0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10 },
        { 0x0E, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0F },
        { 0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11 },
        { 0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x0E },
        { 0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11 },
        { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F },
        { 0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11 },
        { 0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x11 }, 
        { 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E },

        { 0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10 },
        { 0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D },
        { 0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x11 },
        { 0x0E, 0x11, 0x10, 0x0E, 0x01, 0x11, 0x0E },
        { 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
        { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E },
        { 0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04 },
        { 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A },
        { 0x11, 0x11, 0x0A, 0x14, 0x0A, 0x11, 0x11 },
        { 0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04 },
        { 0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F },
        { 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C },
        { 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 },
        { 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E },
        { 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00 }, 
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F },

        { 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00 },
        { 0x00, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F },
        { 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1E },
        { 0x00, 0x00, 0x0E, 0x10, 0x10, 0x11, 0x0E },
        { 0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0F },
        { 0x00, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   // e character  
        { 0x06, 0x09, 0x08, 0x1C, 0x08, 0x08, 0x08 },
        { 0x00, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x0E },
        { 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11 },
        { 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x0E },
        { 0x02, 0x00, 0x06, 0x02, 0x02, 0x12, 0x0C },
        { 0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12 },
        { 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x00, 0x00, 0x1A, 0x15, 0x15, 0x11, 0x11 },
        { 0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11 },
        { 0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E }, 

        { 0x00, 0x00, 0x1E, 0x11, 0x1E, 0x10, 0x10 },
        { 0x00, 0x00, 0x0D, 0x13, 0x0F, 0x01, 0x01 },
        { 0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10 },
        { 0x00, 0x00, 0x0E, 0x10, 0x0E, 0x01, 0x1E },
        { 0x08, 0x08, 0x1C, 0x08, 0x08, 0x09, 0x06 },
        { 0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D },
        { 0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04 },
        { 0x00, 0x00, 0x11, 0x15, 0x15, 0x15, 0x0A },
        { 0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11 },
        { 0x00, 0x00, 0x11, 0x11, 0x0F, 0x01, 0x0E },
        { 0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F },
        { 0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02 },
        { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
        { 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08 },
        { 0x00, 0x00, 0x08, 0x15, 0x02, 0x00, 0x00 },
        { 0x00, 0x00, 0x08, 0x15, 0x02, 0x00, 0x00 },
        
        { 0x0E, 0x11, 0x10, 0x11, 0x0E, 0x04, 0x0C },   //128 euro teken moet c/circumflex zijn
        { 0x08, 0x04, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //129 e met streepje linksboven
        { 0x02, 0x04, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //130 e met streepje rechtsboven
        { 0x04, 0x0A, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //131 e met dakje?? zou moeten zijn
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x04 },   //132
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05 },   //133
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x06 },   //134
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x07 },   //135
        { 0x04, 0x0A, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //136 e met dakje
        { 0x0A, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //137 e met puntjes erop
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A },   //138
        { 0x0A, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x0E },   //139 i met puntjes erop
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //140
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //141
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //142
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //143
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //144
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //145
        { 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00 },   //146 4 horizontal line's
        { 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }    //147 1 horizontale streep

    };
 //     { 0x18, 0x17, 0x01, 0x17, 0x01, 0x17, 0x18 },     // euro sign 

Scrolling text

Bitmap, printing and scrolling

#define MAX_DIGITS 12 //amount of chars possible (matrices)
#define MAX_ROWS 7 //amount of rows possible

const char character_data[116][7] =
    {
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
        { 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x0C },
        { 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00 },
        { 0x0A, 0x0A, 0x1F, 0x0A, 0x00, 0x0A, 0x0A },
        { 0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04 },
        { 0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03 },
        { 0x0C, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0D },
        { 0x0C, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00 },
        { 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02 },
        { 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08 },
        { 0x00, 0x04, 0x15, 0x0E, 0x15, 0x04, 0x00 },
        { 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00 },
        { 0x00, 0x00, 0x00, 0x00, 0x0C, 0x04, 0x08 },
        { 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 },
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C },
        { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 },

        { 0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E },
        { 0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F },
        { 0x0E, 0x11, 0x01, 0x0E, 0x01, 0x11, 0x0E },
        { 0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02 },
        { 0x1F, 0x10, 0x10, 0x1E, 0x01, 0x11, 0x0E },
        { 0x0E, 0x11, 0x10, 0x1E, 0x11, 0x11, 0x0E },
        { 0x1F, 0x11, 0x01, 0x02, 0x04, 0x04, 0x04 },
        { 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E },
        { 0x0E, 0x11, 0x11, 0x0F, 0x01, 0x11, 0x0E },
        { 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00 },
        { 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x04, 0x08 },
        { 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02 },
        { 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00 },
        { 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08 },
        { 0x0E, 0x11, 0x01, 0x02, 0x04, 0x00, 0x04 },

        { 0x0E, 0x11, 0x01, 0x0D, 0x15, 0x15, 0x0E },
        { 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, 0x11 },
        { 0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E },
        { 0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E },
        { 0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E },
        { 0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F },
        { 0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10 },
        { 0x0E, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0F },
        { 0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11 },
        { 0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x0E },
        { 0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11 },
        { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F },
        { 0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11 },
        { 0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x11 }, 
        { 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E },

        { 0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10 },
        { 0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D },
        { 0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x11 },
        { 0x0E, 0x11, 0x10, 0x0E, 0x01, 0x11, 0x0E },
        { 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
        { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E },
        { 0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04 },
        { 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A },
        { 0x11, 0x11, 0x0A, 0x14, 0x0A, 0x11, 0x11 },
        { 0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04 },
        { 0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F },
        { 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C },
        { 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 },
        { 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E },
        { 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00 }, 
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F },

        { 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00 },
        { 0x00, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F },
        { 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1E },
        { 0x00, 0x00, 0x0E, 0x10, 0x10, 0x11, 0x0E },
        { 0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0F },
        { 0x00, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   // e character  
        { 0x06, 0x09, 0x08, 0x1C, 0x08, 0x08, 0x08 },
        { 0x00, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x0E },
        { 0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11 },
        { 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x0E },
        { 0x02, 0x00, 0x06, 0x02, 0x02, 0x12, 0x0C },
        { 0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12 },
        { 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E },
        { 0x00, 0x00, 0x1A, 0x15, 0x15, 0x11, 0x11 },
        { 0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11 },
        { 0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E }, 

        { 0x00, 0x00, 0x1E, 0x11, 0x1E, 0x10, 0x10 },
        { 0x00, 0x00, 0x0D, 0x13, 0x0F, 0x01, 0x01 },
        { 0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10 },
        { 0x00, 0x00, 0x0E, 0x10, 0x0E, 0x01, 0x1E },
        { 0x08, 0x08, 0x1C, 0x08, 0x08, 0x09, 0x06 },
        { 0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D },
        { 0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04 },
        { 0x00, 0x00, 0x11, 0x15, 0x15, 0x15, 0x0A },
        { 0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11 },
        { 0x00, 0x00, 0x11, 0x11, 0x0F, 0x01, 0x0E },
        { 0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F },
        { 0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02 },
        { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 },
        { 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08 },
        { 0x00, 0x00, 0x08, 0x15, 0x02, 0x00, 0x00 },
        { 0x00, 0x00, 0x08, 0x15, 0x02, 0x00, 0x00 },
        
        { 0x0E, 0x11, 0x10, 0x11, 0x0E, 0x04, 0x0C },   //128 euro teken moet c/circumflex zijn
        { 0x08, 0x04, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //129 e met streepje linksboven
        { 0x02, 0x04, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //130 e met streepje rechtsboven
        { 0x04, 0x0A, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //131 e met dakje?? zou moeten zijn
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x04 },   //132
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05 },   //133
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x06 },   //134
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x07 },   //135
        { 0x04, 0x0A, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //136 e met dakje
        { 0x0A, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E },   //137 e met puntjes erop
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A },   //138
        { 0x0A, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x0E },   //139 i met puntjes erop
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //140
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //141
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //142
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //143
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //144
        { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00 },   //145
        { 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00 },   //146 4 horizontal line's
        { 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00 }    //147 1 horizontale streep
    };

char array[MAX_DIGITS][MAX_ROWS];
unsigned long lastTime;

#define HBITS 120
#define HARRAY 17
#define ROW_STROBE HIGH
#define ROW_OFF LOW
unsigned char bitfield[MAX_ROWS][HARRAY];
char * scrolltext;
int textoffset;
int widthused;

//pinouts for control
int shiftData = 11;
int shiftClr = 12;
int shiftClock = 13;

// pinouts for data
int row1 = 2;
int row2 = 3;
int row3 = 4;
int row4 = 5;
int row5 = 6;
int row6 = 7;
int row7 = 8;

void setup() {
  pinMode(shiftData, OUTPUT);
  pinMode(shiftClr, OUTPUT);
  pinMode(shiftClock, OUTPUT);
  
  pinMode(row1, OUTPUT);
  pinMode(row2, OUTPUT);
  pinMode(row3, OUTPUT);
  pinMode(row4, OUTPUT);
  pinMode(row5, OUTPUT);
  pinMode(row6, OUTPUT);
  pinMode(row7, OUTPUT);
  
  digitalWrite(shiftClr,HIGH);
  
  scrolltext = "RandomData for teh win!";
  textoffset = 0;
  widthused = HBITS;
}

void loop() 
{  
    displayMatrix();
}

void displayMatrix()
{
    for (int reps = 0; reps < 2; reps++)
    {
        for (int i = 0; i < MAX_ROWS; i++)
        {
            pushrow(i);
            delayMicroseconds(700); //Dit bepaalt momenteel hoe goed de tekens zichtbaar zijn.
        }
    }  
    shiftrow();
}

void pushrow(int row)
{
    digitalWrite(row1, ROW_OFF);
    digitalWrite(row2, ROW_OFF);
    digitalWrite(row3, ROW_OFF);
    digitalWrite(row4, ROW_OFF);
    digitalWrite(row5, ROW_OFF);
    digitalWrite(row6, ROW_OFF);
    digitalWrite(row7, ROW_OFF);

    int last = ((HBITS - 7) >> 3);
    unsigned char seg = bitfield[row][last];
    for (int seq = 0; seq < (HBITS & 7); seq++)
    {          
        digitalWrite(shiftData, seg & 1);
        digitalWrite(shiftClock, LOW);
        digitalWrite(shiftClock, HIGH);
        seg >>= 1;
    }    
    for (int index = last; index >= 0; index--)
    {
        unsigned char seg = bitfield[row][index];
        for (int seq = 0; seq < 8; seq++)
        {          
            digitalWrite(shiftData, seg & 1);
            digitalWrite(shiftClock, LOW);
            digitalWrite(shiftClock, HIGH);
            seg >>= 1;
        }
    }
    

    switch(row)
    {
        case 0: digitalWrite(row1, ROW_STROBE);break;
        case 1: digitalWrite(row2, ROW_STROBE);break;
        case 2: digitalWrite(row3, ROW_STROBE);break;
        case 3: digitalWrite(row4, ROW_STROBE);break;
        case 4: digitalWrite(row5, ROW_STROBE);break;
        case 5: digitalWrite(row6, ROW_STROBE);break;
        case 6: digitalWrite(row7, ROW_STROBE);break;  
    }
}

void shiftrow()
{
    for (int row = 0; row < MAX_ROWS; row++)
    {  
        bitfield[row][0] <<= 1; 
        for (int i = 1; i < HARRAY; i++)
        {
            unsigned char carry = bitfield[row][i];
            bitfield[row][i] = carry << 1;
            if (carry & 0x80) bitfield[row][i-1] |= 0x01;
        }
    }
    widthused--;
    if (widthused < HBITS)
    {
        //scrolltext = "ABCDEFG";
        
        char appendchar = scrolltext[textoffset];
        if (appendchar == 0)
        {
            textoffset = 0;
        }
        else
        {
            textoffset++;  
            appendchar -= 0x20;
        }
        
        /*
        for (int i = 0; i < MAX_ROWS; i++)
        {
            bitfield[i][HARRAY-1] = (1 << i) | (1 << (6 - i));
        }
        */
        
        //appendchar = 'A';
        for (int i = 0; i < MAX_ROWS; i++)
        {
            bitfield[i][HARRAY-1] = (character_data[appendchar][i]) << 3;
        }
        
        /*
        bitfield[0][HARRAY-1] = 0x3E << 1;
        bitfield[1][HARRAY-1] = 0x41 << 1;
        bitfield[2][HARRAY-1] = 0x55 << 1;
        bitfield[3][HARRAY-1] = 0x41 << 1;
        bitfield[4][HARRAY-1] = 0x5D << 1;
        bitfield[5][HARRAY-1] = 0x41 << 1;
        bitfield[6][HARRAY-1] = 0x3E << 1;
        */

        widthused += 7;
    }
}