Things used in this project

Hardware components:
Photon new
Particle Photon
×1
Hoverlabs Beam
you need 1-3 beams
×1
12002 04
Breadboard (generic)
×1
11026 02
Jumper wires (generic)
you need 8 jumper wires
×1
Software apps and online services:
Particle WebIDE
Blynk logo avatars
Blynk
optional for transfer individual text to the beam grid

Code

Die Losungen - MainC/C++
Tab 1/5
// Die Losungen - every day a new bible verse
// ScruffR & Ingo Lohs
// v1.0, 24.07.2017
// works with Particle Photon v0.6.2 and Electron v0.6.1
// Display: Hoverlabs Beam

// Include LIBs from Particle ---------------------

#include <SparkJson.h> // v0.0.2
#include <blynk.h>     // v0.4.7

// Include LIBs via Tabs ---------------------

#include "application.h"
#include "beam.h"
#ifdef IGNORE 
#include "charactermap.h"
#include "frames.h"
#endif

SYSTEM_MODE(SEMI_AUTOMATIC)
SYSTEM_THREAD(ENABLED)

// USERs CONFIG AREA: WIFI & BLYNK ---------------------

#if ( PLATFORM_ID != PLATFORM_ELECTRON_PRODUCTION )
const char defaultSSID[] = "<YOUR SSID HERE>";
const char defaultPWD[]  = "<YOUR WiFi PASSWORD HERE>";
const int  defaultAUTH   = WPA2;
const int  defaultWCIPH  = WLAN_CIPHER_AES_TKIP;
#endif 

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
const char auth[] = "<YOUR BLYNK TOKEN HERE>";

// DEFINITIONS ---------------------

// Attach virtual serial terminal to Virtual Pin V0
WidgetTerminal terminal(V0);

const int pinSYNC   = D7;
const int pinRESET  = D3;
const int pinIRQ    = D2; 
const int BEAMCOUNT =  1; // USERs CONFIG: set number of beams daisy chained together - works with 1, 2 or 3

const int loopCount             =   1;
const int msDelayPerCharPlay    = 460;

enum DISPLAY_METHOD {
    NONE,
    PLAY,
    DISPLAY
};

Beam b = Beam(pinRESET, pinIRQ, BEAMCOUNT);

/*
      "Datum": "2017-05-05T00:00:00",
      "Wtag": "Freitag", 
      "Sonntag": {},
      "Losungstext": "Du sollst dein Herz nicht verhärten und deine Hand nicht zuhalten gegenüber deinem armen Bruder.",
      "Losungsvers": "5.Mose 15,7",
      "Lehrtext": "Wenn jemand dieser Welt Güter hat und sieht seinen Bruder darben und verschließt sein Herz vor ihm, wie bleibt dann die Liebe Gottes in ihm?",
      "Lehrtextvers": "1.Johannes 3,17"
*/

// TESTING ---------------------

char datum[20];        //= "2017-01-01T00:00:00";
char wochentag[12];    //= "XXXXXXXXtag";
char sonntag[12];      //= "YYYYYYYYtag";
char losungstext[256]; //= "LosungsText: Das ist ein längerer Text ÄÖÜ";
char losungsvers[32];  //= "LosungVers ÄÖÜ";
char lehrtext[256];    //= "LehrText: Das ist ein längerer Text ÄÖÜ";
char lehrtextvers[32]; //= "LehrTextVers ÄÖÜ";
char customMessage[256] = "Meine Gemeinde: www.emf-bielefeld.de";

uint32_t msLastTime;
uint32_t msDelay;
int      lastDay = 0;

// SERIAL LOG ---------------------

SerialLogHandler myLogger(LOG_LEVEL_INFO);

// BLYNK Terminal Widget ---------------------

BLYNK_WRITE(V0)
{
  if (strlen((const char*)param.asStr())) {
    strncpy(customMessage, (const char*)param.asStr(), sizeof(customMessage));
    customMessage[sizeof(customMessage)-1] = '\0';    
    terminal.print(customMessage);
  } 
  else {
    terminal.print(customMessage);
    memset(customMessage, 0, sizeof(customMessage)); 
  }
  terminal.flush();
}

// FUNCTION ---------------------

volatile bool proceede = false;
void isrBeam() {
    proceede = true;
}

// SETUP ---------------------

void setup() {
  Wire.setSpeed(CLOCK_SPEED_400KHZ);
  Wire.begin();
  b.begin();
  b.setSpeed(1);
  b.print("Die Losungen");
  b.play();
  delay(3000);

  // setup a time zone, which is part of the ISO6801 format 
  Time.zone(isDST() ? +2.00 : +1.00);  

  // Subscribe to the integration response event
  Particle.subscribe("hook-response/tageslosung", myHandler, MY_DEVICES);

  #if ( PLATFORM_ID != PLATFORM_ELECTRON_PRODUCTION )
  WiFi.on();
  if (!WiFi.hasCredentials()) {
    WiFi.setCredentials(defaultSSID, defaultPWD, defaultAUTH, defaultWCIPH);
    for(uint32_t _ms = millis(); millis() - _ms < 500; Particle.process());
    WiFi.off();
  }
  #endif
  
  Particle.connect();
  waitUntil(Particle.connected);

  Blynk.begin(auth);
  terminal.println("Die Losungen");
  terminal.println("Thanks to Richard Klose");
  terminal.println("with special thanks to");
  terminal.println("ScruffR for Coding");
  terminal.println("https://community.particle.io");
  terminal.println("Ingo Lohs");
  
  while(Serial.read() >= 0) Particle.process(); // flush USB Serial RX buffer

  Particle.publish("tageslosung", "MyLosung", PRIVATE);
}

// LOOP ---------------------

void loop() {
  static uint32_t msPublish = millis();

  Blynk.run();

  if (lastDay != Time.day() && millis() - msPublish > 60000) {
    Particle.syncTime(); 
    waitFor(Particle.syncTimeDone, 5000); // works with v0.6.1 with Photon & Electron
    msPublish = millis();
    if (lastDay == Time.day()) return; // if sync brought us back before midnight, try a bit later again
    // request new day's data
    Particle.publish("tageslosung", "MyLosung", PRIVATE);
  }

  print_out_on_Beam();
    
}

// FUNCTION to DISPLAY DATA ---------------------

void print_out_on_Beam() {
  static int step = 0;
  char  dynText[32];
  const char* txt = NULL;
  DISPLAY_METHOD method = NONE; 

  // don't procede if we need to wait a bit
  if(msDelay && millis() - msLastTime < msDelay) return;
  msDelay = 0;
 
  switch (step++) {
    case 0:
      txt = customMessage;
      method = PLAY;
      break;

    case 1:
    case 5:
      Time.zone(isDST() ? +2.00 : +1.00);  
      snprintf(dynText, sizeof(dynText), "%s", (const char*)Time.format("%d.%m.%Y %H:%M"));
      //snprintf(dynText, sizeof(dynText), "%s", (const char*)Time.format("%H:%M"));
      txt = dynText;
      method = DISPLAY;
      break;

    case 2:
      txt = wochentag; 
      method = DISPLAY;
      break;
      
    case 3:
      txt = losungstext;
      method = PLAY;
      break;
      
    case 4:
      txt = losungsvers;
      msDelay = 10000;
      method = DISPLAY;
      break;
      
    case 6:
      txt =lehrtext;
      method = PLAY;
      break;
      
    case 7:
      txt = lehrtextvers;
      msDelay = 10000;
      method = DISPLAY;
      break;
      
    default:
      step = 0;
      break;
  }
  
  Blynk.virtualWrite(V0, txt);
  Blynk.virtualWrite(V0, "\n"); // Carriage Return - every text displays in a new line

  b.print(txt); 
  switch (method) {
    case PLAY:
      b.setLoops(loopCount);
      //b.setScroll(LEFT,4);
      //b.setSpeed(6);
      b.play();
      msDelay = BEAMCOUNT * 2000 + strlen(txt) * msDelayPerCharPlay * loopCount;
      break;
    case DISPLAY:
      if (!msDelay) msDelay = 5000;
      b.display();
      break;
    default:
      break;
  }
  msLastTime = millis();

  // Beam can begin scrolling text with just print() and play() > Beam using ONLY Strings to display  
  /*
  // methods like setSpeed(), setScroll() setLoops(), setMode() can be called 
  //on the fly to change the existing default settings
  b.setSpeed(2);      //increase speed
  b.setSpeed(1);      //increase speed again!
  b.setSpeed(15);     //reduce speed to lowest setting
  */
}

// WEBHOOK HANDLER TO GET DATA ---------------------

void myHandler(const char *event, const char *data)
{
  static int cntEvents = 0;
  char mutableCopy[strlen(data)+1];
  strcpy(mutableCopy, data);

  // Start SparkJSON Example	    
  Log.info("%d: %s, data: %s", ++cntEvents, event, data);
  if (data) {
    terminal.println(data);
    terminal.println("--------end--------");
    terminal.flush();
    /* JSON Source - https://losungen.klose.cloud/api/today
    {
      "Datum": "2017-05-05T00:00:00",
      "Wtag": "Freitag", 
      "Sonntag": {},
      "Losungstext": "Du sollst dein Herz nicht verhärten und deine Hand nicht zuhalten gegenüber deinem armen Bruder.",
      "Losungsvers": "5.Mose 15,7",
      "Lehrtext": "Wenn jemand dieser Welt Güter hat und sieht seinen Bruder darben und verschließt sein Herz vor ihm, wie bleibt dann die Liebe Gottes in ihm?",
      "Lehrtextvers": "1.Johannes 3,17"
    }
    */
    
    // https://bblanchon.github.io/ArduinoJson/faq/how-to-determine-the-buffer-size/
    // https://bblanchon.github.io/ArduinoJson/assistant/
    StaticJsonBuffer<256> jsonBuffer;
	JsonObject& root = jsonBuffer.parseObject(mutableCopy);

	
	if (!root.success()) {
      Log.warn("parseObject() failed");
      return;
    }
             
    strncpy(datum       , root["Datum"       ], sizeof(datum)       );
    strncpy(wochentag   , root["Wtag"        ], sizeof(wochentag)   );
    strncpy(sonntag     , root["Sonntag"     ], sizeof(sonntag)     );
	strncpy(losungstext , root["Losungstext" ], sizeof(losungstext) );
	strncpy(losungsvers , root["Losungsvers" ], sizeof(losungsvers) );
	strncpy(lehrtext    , root["Lehrtext"    ], sizeof(lehrtext)    );
	strncpy(lehrtextvers, root["Lehrtextvers"], sizeof(lehrtextvers));

    lastDay = Time.day();
  }
  else {
    terminal.println("no JSON Records available - check the Webhook under Particle Cloud - Console - Integrations!");
  }
}

// FUNCTION TO CHECK SUMMER/WINTER-TIME ---------------------

bool isDST()
{ // Central European Summer Timer calculation
  int dayOfMonth = Time.day();
  int month = Time.month();
  int dayOfWeek = Time.weekday() - 1; // make Sunday 0 .. Saturday 6

  if (month >= 4 && month <= 9)
  { // March to September definetly DST
    return true;
  }
  else if (month < 3 || month > 10)
  { // before March or after October is definetly normal time
    return false;
  }

  // March and October need deeper examination
  boolean lastSundayOrAfter = (dayOfMonth - dayOfWeek > 24);
  if (!lastSundayOrAfter)
  { // before switching Sunday
    return (month == 10); // October DST will be true, March not
  }

  if (dayOfWeek)
  { // AFTER the switching Sunday
    return (month == 3); // for March DST is true, for October not
  }

  int secSinceMidnightUTC = Time.now() % 86400;
  boolean dayStartedAs = (month == 10); // DST in October, in March not
                                        // on switching Sunday we need to consider the time
  if (secSinceMidnightUTC >= 1 * 3600)
  { // 1:00 UTC (=2:00 CET/3:00 CEST)
    return !dayStartedAs;
  }

  return dayStartedAs;
}
Die Losungen - beam.cppC/C++
Tab 2/5
/*
===========================================================================
This is the library for Beam.

Beam is a beautiful LED matrix — features 120 LEDs that displays scrolling text, animations, or custom lighting effects.
Beam can be purchased here: http://www.hoverlabs.co

Written by Emran Mahbub and Jonathan Li for Hover Labs.
BSD license, all text above must be included in any redistribution

===========================================================================
*/
#include <Particle.h>
#include "beam.h"
#include "charactermap.h"
#include "frames.h"

/*
=================
PUBLIC FUNCTIONS
=================
*/

/*
This constructor used when multiple Beams behave like one long Beam
*/
Beam::Beam(int rstpin, int irqpin, int numberOfBeams) {
  Log.trace("Beam::Beam(int rstpin, int irqpin, int numberOfBeams)");
  _rst = rstpin;
  _irq = irqpin;

  if (numberOfBeams <= 0 || 4 <= numberOfBeams) {
    Log.warn("Number of Beams must be between 1 and 4 and not %d (default to 1 BEAMA)", numberOfBeams);
    numberOfBeams = 1;
  }
  BEAM = &BEAM_ADDRESS[0];
  activeBeams = 
  _beamCount = numberOfBeams;
  _gblMode = 1;
}

/*
This constructor used when multiple Beams behave like single Beam units
*/
Beam::Beam(int rstpin, int irqpin, uint8_t syncMode, uint8_t beamAddress) {
  Log.trace("Beam::Beam(int rstpin, int irqpin, uint8_t syncMode, uint8_t beamAddress)");
  _rst = rstpin;
  _irq = irqpin;
  _syncMode = 0;
  _beamCount = 
  activeBeams = 1;
  BEAM = NULL;
  for (unsigned int b = 0; b < sizeof(BEAM_ADDRESS); b++) {
    if (BEAM_ADDRESS[b] == beamAddress) {
      BEAM = &BEAM_ADDRESS[b];
      break;
    }
  }
  if (!BEAM) {
    BEAM = &BEAM_ADDRESS[0];
    Log.warn("%02x is not a valid Beam address (default to BEAMA %02x)", beamAddress, BEAM_ADDRESS[0]);
  }

  _gblMode = 0;
}

bool Beam::begin(TwoWire& wire) {
  Log.trace("bool Beam::begin(TwoWire& wire)");
  _wire = &wire;

  //resets beam - will clear all beams
  pinMode(_rst, OUTPUT);
  digitalWrite(_rst, LOW);
  delay(100);
  digitalWrite(_rst, HIGH);
  delay(250);

  //reset cs[]
  memset((uint8_t*)cs, 0x00, sizeof(cs));

  //reset segmentmask[]
  for (int s = 0; s < 8; s++) {
    segmentmask[s] = 0x0001 << (7 - s);
  }

  return true;
}

void Beam::initBeam() {
  Log.trace("void Beam::initBeam()");
  //initialize Beam 
  for (unsigned int b = 0; b < _beamCount; b++) {
    Log.trace("clearing BEAM[%d]", b);
    initializeBeam(BEAM[b]);
  }
}

void Beam::print(const char* text) {
  Log.trace("void Beam::print(const char* text)");
  //resets beam - will clear all beams
  pinMode(_rst, OUTPUT);
  digitalWrite(_rst, LOW);
  delay(100);
  digitalWrite(_rst, HIGH);
  delay(250);

  Log.info("Text to print: %s", text);

  initBeam();

  // Clear all frames
  memset((uint8_t*)cs, 0x00, sizeof(cs));

  for (int i = 0; i < 36; i++) {
    for (unsigned int b = 0; b < _beamCount; b++) {
      writeFrame(BEAM[b], i);
    }
  }

  int i = 0;
  const uint8_t *fontptr;
  int frame = 0;

  int asciiVal;
  int cscount = 0;
  int stringLen = strlen(text);

  while ((i < stringLen) && frame < 36) {
    // pick a character to print to Beam
    asciiVal = toupper(text[i]);
    if (32 <= asciiVal && asciiVal <= 96) {
      fontptr = &charactermap[(asciiVal - 32)][0];   //set fontptr to matching font
    }
    else {
      switch (text[i]) {
        case 0xC3: // two byte character prefix to be ignored
          i++;
          continue;
          break;
        case 0x84: // (0xC3 0x84) 'Ä'
        case 0xA4: // (0xC3 0xA4) 'ä'
          fontptr = &charactermap[65][0];
          break;
        case 0x96: // (0xC3 0x96) 'Ö'
        case 0xB6: // (0xC3 0x86) 'ö'
          fontptr = &charactermap[66][0];
          break;
        case 0x9C: // (0xC3 0x9C) 'Ü'
        case 0xBC: // (0xC3 0xBC) 'ü'
          fontptr = &charactermap[67][0];
          break;
        case 0x9F: // (0xC3 0xDF) 'ß'
          fontptr = &charactermap[68][0];
          break;
        default:
          fontptr = &charactermap[0][0];
          break;
      }
    }

    // loop through the Beam grid and place characters
    // from the character map
    Log.trace("%c = %d (0x%02x)\r\ncscolumn[] = ", text[i], asciiVal, asciiVal);
    while (cscount < 24 && *fontptr != 0xFF) {
      cscolumn[cscount] = *fontptr;
      Log.trace("0x%02x", cscolumn[cscount]);
      fontptr++;
      cscount++;
    }
    i++;  // go to next character

    if (cscount > 23) {
      // if end of grid is reached in current frame,
      // then start writing to the Beam registers
      Log.trace("--- end of frame reached ---\r\nwriting cs[]");
      for (int j = 0; j < 12; j++) {
        cs[j] = (cscolumn[j * 2]) | (cscolumn[j * 2 + 1] << 5);
        Log.trace("0x%02x", cs[j]);
      }
      Log.trace("--- end of cs[] ---");

      for (unsigned int b = 0; b < _beamCount; b++) {
        writeFrame(BEAM[b], frame + (_beamCount - b));
      }
      _lastFrameWrite = frame + _beamCount;

      for (int x = 0; x < 12; x++) {
        cs[x] = 0x00;
        cscolumn[x * 2] = 0x00;
        cscolumn[x * 2 + 1] = 0x00;
      }
      frame++;            // go to next frame
      cscount = 0;        // reset cscount

      // if a specific frame is specified, then return if that frame is done.
      //ADD THIS LATER
      //if (frameNum!=0 && frame > frameNum){
      //    return;
      //}

      if (*fontptr != 0xFF) {
        //special case if current character needs to wrap to next frame
        Log.trace("Continuing prev char cscolumn[] = ");

        while (cscount < 24 && *fontptr != 0xFF) {
          cscolumn[cscount] = *fontptr;
          Log.trace("0x%02x", cscolumn[cscount]);
          fontptr++;
          cscount++;
        }
      }
    }

    if (stringLen == i) {
      // if end of string is reached in current frame,
      // then start writing to Beam registers
      Log.trace("--- end of string reached ---\r\nwriting cs[]");
      for (int j = 0; j < 12; j++) {
        cs[j] = (cscolumn[j * 2]) | (cscolumn[j * 2 + 1] << 5);
        Log.trace("0x%02x", cs[j]);
      }
      Log.trace("--- done cs print ---");

      for (unsigned int b = 0; b < _beamCount; b++) {
        writeFrame(BEAM[b], frame + (_beamCount - b));
      }
      _lastFrameWrite = frame + _beamCount;

      for (int x = 0; x < 12; x++) {
        cs[x] = 0x00;
        cscolumn[x * 2] = 0x00;
        cscolumn[x * 2 + 1] = 0x00;
      }
    }
  }

  //defaults Beam to basic settings
  setPrintDefaults(SCROLL, 0, 6, 7, 5, 1, 0);
}

void Beam::printFrame(uint8_t frameToPrint, const char * text) {
  Log.trace("void Beam::printFrame(uint8_t frameToPrint, const char * text)");
  Log.info("Text to print: %s", text);

  int i = 0;
  const uint8_t * fontptr;
  int frame = frameToPrint;

  int asciiVal;
  int cscount = 0;
  int stringLen = strlen(text);

  while ((i < stringLen) && frame < 36) {
    // pick a character to print to Beam
    asciiVal = toupper(text[i]);
    if (32 <= asciiVal && asciiVal <= 96) {
      fontptr = &charactermap[(asciiVal - 32)][0];   //set fontptr to matching font
    }
    else {
      switch (text[i]) {
        case 0xC3: // two byte character prefix to be ignored
          i++;
          continue;
          break;
        case 0x84: // (0xC3 0x84) 'Ä'
        case 0xA4: // (0xC3 0xA4) 'ä'
          fontptr = &charactermap[65][0];
          break;
        case 0x96: // (0xC3 0x96) 'Ö'
        case 0xB6: // (0xC3 0x86) 'ö'
          fontptr = &charactermap[66][0];
          break;
        case 0x9C: // (0xC3 0x9C) 'Ü'
        case 0xBC: // (0xC3 0xBC) 'ü'
          fontptr = &charactermap[67][0];
          break;
        case 0x9F: // (0xC3 0xDF) 'ß'
          fontptr = &charactermap[68][0];
          break;
        default:
          fontptr = &charactermap[0][0];
          break;
      }
    }

    Log.trace("%c = %d (0x%02x)\r\ncscolumn[] = ", text[i], asciiVal, asciiVal);
    // loop through the Beam grid and place characters
    // from the character map
    while (cscount < 24 && *fontptr != 0xFF) {
      cscolumn[cscount] = *fontptr;
      Log.trace("0x%02x", cscolumn[cscount]);
      fontptr++;
      cscount++;
    }
    i++;  // go to next character

    if (cscount > 23) {
      // if end of grid is reached in current frame,
      // then start writing to the Beam registers

      Log.trace("--- end of frame reached ---\r\nwriting cs[]");
      for (int j = 0; j < 12; j++) {
        cs[j] = (cscolumn[j * 2]) | (cscolumn[j * 2 + 1] << 5);
        Log.trace("0x%02x", cs[j]);
      }
      Log.trace("--- end of cs[] ---");

      for (unsigned int b = 0; b < _beamCount; b++) {
        writeFrame(BEAM[b], frame);
        //_lastFrameWrite = frame;
      }

      for (int x = 0; x < 12; x++) {
        cs[x] = 0x00;
        cscolumn[x * 2] = 0x00;
        cscolumn[x * 2 + 1] = 0x00;
      }

      frame++;            // go to next frame
      cscount = 0;        // reset cscount
      _lastFrameWrite = frame;

      // if a specific frame is specified, then return if that frame is done.
      if (frameToPrint != 0 && frame > frameToPrint) {
        //defaults Beam to basic settings
        setPrintDefaults(SCROLL, 0, _lastFrameWrite, 7, 15, 1, 1);
        return;
      }
    }
  }
}

void Beam::play() {
  Log.trace("void Beam::play()");
  //start playing beams depending on scroll direction
  if (_scrollDir == LEFT) {
    sendWriteCmd(BEAM[_beamCount - 1], CTRL, SHDN, 0x03);
  }
  else {
    sendWriteCmd(BEAM[0], CTRL, SHDN, 0x03);
  }

  if (_beamCount > 1) {
    while (checkStatus() != 1) {
      delay(10);
    }
  }
}

void Beam::startNextBeam() {
  Log.trace("void Beam::startNextBeam()");
  Log.trace("_scrollDir: %d, _beamCount: %d, beamNumber: %d", _scrollDir, _beamCount, beamNumber);

  // since the original logic didn't make much sense, I assumed similar behaviour to Beam::play() might make more sense
  // see https://github.com/hoverlabs/beam_particle/issues/4
  //start playing beams depending on scroll direction
  if (_scrollDir == LEFT) {
    sendWriteCmd(BEAM[_beamCount - 1], CTRL, SHDN, 0x03);
  }
  else {
    sendWriteCmd(BEAM[0], CTRL, SHDN, 0x03);
  }
}

void Beam::setScroll(uint8_t direction, uint8_t fade) {
  Log.trace("void Beam::setScroll(uint8_t direction, uint8_t fade)");
  if (direction != RIGHT && direction != LEFT) {
    Log.warn("Select either LEFT or RIGHT for direction");
    return;
  }

  _scrollDir = direction;
  _fadeMode = fade;
  _scrollMode = 1;

  uint8_t frameData = _fadeMode << 7 | _scrollDir << 6 | 0 << 5 | _scrollMode << 4 | _frameDelay;

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, FRAMETIME, frameData);
  }
}

void Beam::setSpeed(uint8_t speed) {
  Log.trace("void Beam::setSpeed(uint8_t speed)");
  if (speed < 1 || 15 < speed) {
    Log.trace("Enter a speed between 1 and 15");
    return;
  }

  _scrollMode = (_beamMode == MOVIE) ? 0 : 1;

  _frameDelay = speed;

  uint8_t frameData = _fadeMode << 7 | _scrollDir << 6 | 0 << 5 | _scrollMode << 4 | _frameDelay;

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, FRAMETIME, frameData);
  }
}

void Beam::setLoops(uint8_t loops) {
  Log.trace("void Beam::setLoops(uint8_t loops)");
  if (loops < 1 || 7 < loops) {
    Log.warn("Enter a speed between 1 and 7");
    return;
  }

  _numLoops = loops;
  uint8_t displayData = _numLoops << 5 | 0 << 4 | 0x0B;

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, DISPLAYO, displayData);
  }
}

void Beam::setMode(uint8_t mode) {
  Log.trace("void Beam::setMode(uint8_t mode)");
  if (mode != MOVIE && mode != SCROLL) {
    Log.warn("Select either SCROLL or MOVIE for mode");
    return;
  }

  _beamMode = mode;
  uint8_t frameData = 0;

  if (mode == MOVIE) {
    frameData = 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | _frameDelay;
  }
  else if (mode == SCROLL) {
    frameData = _fadeMode << 7 | _scrollDir << 6 | 0 << 5 | _scrollMode << 4 | _frameDelay;
  }

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, FRAMETIME, frameData);
  }
}

/*
Used by global mode to check when daisy chained Beams
should be activated depending on the scroll direction.
*/
int Beam::checkStatus() {
  Log.trace("int Beam::checkStatus()");
  if ((sendReadCmd(BEAM[activeBeams - 1], CTRL, 0x0F) >> 2) == (_beamCount - activeBeams + 1)) {
    sendWriteCmd(BEAM[--activeBeams - 1], CTRL, SHDN, 0x03);
    if (activeBeams <= 1) {
      delay(10);
      activeBeams = _beamCount;
      return 1;
    }
  }
  
  return 0;
}

void Beam::draw() {
  Log.trace("void Beam::draw()");
  //resets beam - will clear all beams
  pinMode(_rst, OUTPUT);
  digitalWrite(_rst, LOW);
  delay(100);
  digitalWrite(_rst, HIGH);
  delay(250);

  initBeam();

  for (int i = 0; i < 36; ++i) {
    convertFrame(frameList[i]);
    // altered original frame counting logic: see https://github.com/hoverlabs/beam_particle/issues/6
    for (unsigned int b = 0; b < _beamCount; b++) {
      writeFrame(BEAM[b], i + (_beamCount - 1 - b));
    }
    _lastFrameWrite = i + _beamCount - 1;

    // reset cs[]
    memset((uint8_t*)cs, 0x00, sizeof(cs));
  }

  setPrintDefaults(MOVIE, 1, 20, 7, 2, 1, 0);
}

void Beam::display() {
  uint8_t pictureData = 0 << 7 | 1 << 6 | _beamCount;
  uint8_t displayData = 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0x0B;
  uint8_t currsrcData = 0;

  // change led current based on number of connected beams
  switch (_beamCount) {
    case 1:
      currsrcData = 0x20;
      break;
    case 2:
      // unexpected value: see https://github.com/hoverlabs/beam_particle/issues/5
      currsrcData = 0x15;
      break;
    case 3:
      currsrcData = 0x10;
      break;
    case 4:
      currsrcData = 0x08;
      break;
    default:
      currsrcData = 0x00;
      break;
  }

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, PIC, pictureData);
    sendWriteCmd(BEAM[b], CTRL, CURSRC, currsrcData);
    sendWriteCmd(BEAM[b], CTRL, DISPLAYO, displayData);
  }

  for (unsigned int b = 0; b < _beamCount; b++) {
    sendWriteCmd(BEAM[b], CTRL, SHDN, 0x03);
  }
}

int Beam::status() {
  int frameDone = 0;

  if (_gblMode == 0) {
    frameDone = (sendReadCmd(BEAM[0], CTRL, 0x0F) >> 2);
    Log.trace("Frame done (%d)", frameDone);
  }
  return frameDone;
}

/*
=================
PRIVATE FUNCTIONS
=================
*/

void Beam::initializeBeam(uint8_t baddr) {
  Log.trace("void Beam::initializeBeam(uint8_t baddr)");
  //set basic config on each defined beam unit
  sendWriteCmd(baddr, CTRL, CFG, 0x01);

  //set each frame to off since cs[] is reset by default 
  for (int i = 0; i < 36; i++) {
    writeFrame(baddr, i);
  }

  //set basic blink + pwm registers for each defined beam
  for (int i = 0x40; i <= 0x45; i++) {
    for (int j = 0x00; j <= 0x17; j++) {
      sendWriteCmd(baddr, i, j, 0x00);
    }
    for (int k = 0x18; k <= 0x9b; k++) {
      sendWriteCmd(baddr, i, k, 0xFF);
    }
  }
}

void Beam::setPrintDefaults(uint8_t mode, uint8_t startFrame, uint8_t numFrames, uint8_t numLoops, uint8_t frameDelay, uint8_t scrollDir, uint8_t fadeMode) {
  Log.trace("void Beam::setPrintDefaults(uint8_t mode, uint8_t startFrame, uint8_t numFrames, uint8_t numLoops, uint8_t frameDelay, uint8_t scrollDir, uint8_t fadeMode)");
  _scrollMode = 1;
  _scrollDir = scrollDir;
  _fadeMode = fadeMode;
  _frameDelay = frameDelay;
  _beamMode = mode;
  _numLoops = numLoops;

  if (mode == MOVIE || mode == SCROLL) {
    //make sure startFrame between 0 and 35
    //make sure numFrames between 2 and 36
    //make sure frameDelay between 0 and 1111
    //make sure numLoops between 000 and 111

    uint8_t movieData = 0 << 7 | 1 << 6 | startFrame;
    uint8_t moviemodeData = 0 << 7 | 0 << 6 | _lastFrameWrite;
    uint8_t frameData = 0;
    //uint8_t syncData = 0;

    switch (mode) {
      case MOVIE:
        frameData = 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | frameDelay;
        break;
      case SCROLL:
        frameData = fadeMode << 7 | scrollDir << 6 | 0 << 5 | _scrollMode << 4 | frameDelay;
        break;
    }

    uint8_t displayData = _numLoops << 5 | 0 << 4 | 0x0B;
    //uint8_t irqmaskData = 0xFF;
    //uint8_t irqframedefData = 0x03;
    uint8_t currsrcData = 0;

    // change led current based on number of connected beams
    if (_beamCount == 4) {
      currsrcData = 0x08;
    }
    else if (_beamCount == 3) {
      currsrcData = 0x10;
    }
    else if (_beamCount == 2) {
      currsrcData = 0x20;
    }
    else if (_beamCount == 1) {
      currsrcData = 0x20;
    }
    else {
      currsrcData = 0x15;
    }

    if (_scrollDir == LEFT) {
      for (unsigned int b = 0; b < _beamCount; b++) {
          
        sendWriteCmd(BEAM[b], CTRL, MOV, movieData);
        sendWriteCmd(BEAM[b], CTRL, MOVMODE, moviemodeData);
        sendWriteCmd(BEAM[b], CTRL, CURSRC, currsrcData);
        sendWriteCmd(BEAM[b], CTRL, FRAMETIME, frameData);
        sendWriteCmd(BEAM[b], CTRL, DISPLAYO, displayData);
        if (b != 3)  // for some reason not for BEAMD (???)
          sendWriteCmd(BEAM[b], CTRL, SHDN, 0x02);
      }
    }
    else {
      //NEED TO MODIFY  FOR RIGHT OR LEFT SCROLL//
    }

    if (_gblMode == 1 && _beamCount > 1) {
      /* define clk sync in/out settings based on left/right scrolling direction */
      if (_scrollDir == LEFT) {
        sendWriteCmd(BEAM[_beamCount - 1], CTRL, CLKSYNC, 0x02);
        for (int b = 0; b < _beamCount - 1; b++) {
          sendWriteCmd(BEAM[b], CTRL, CLKSYNC, 0x01);
        }
      }
      else {
        sendWriteCmd(BEAM[0], CTRL, CLKSYNC, 0x02);
        for (unsigned int b = 1; b < _beamCount; b++) {
          sendWriteCmd(BEAM[b], CTRL, CLKSYNC, 0x01);
        }
      }
    }
    else {
      // ToDo
    }
  }
}

unsigned int Beam::setSyncTimer() {
  Log.trace("unsigned int Beam::setSyncTimer()");
  if (1 <= _frameDelay && _frameDelay <= 15)
    return _frameDelay * 32.5;

  return 1000;
}

void Beam::writeFrame(uint8_t addr, uint8_t f) {
  Log.trace("void Beam::writeFrame(uint8_t addr, uint8_t f)");
  uint8_t p = f;
  Log.trace("writing frame %c (0x%02x)", p, p);
  int data = 0;
  for (int j = 0x00; j <= 0x0B; j++) {
    sendWriteCmd(addr, p + 1, 2 * j, cs[data] & 0xFF);          // i = frame address, 2*j = frame register address (even numbers) then first data byte
    sendWriteCmd(addr, p + 1, 2 * j + 1, (cs[data] & 0x300) >> 8);    // i = frame address, 2*j+1 = frame register address (odd numbers) then second data byte
    data++;
  }
  Log.trace("Done writing frame");
}

void Beam::convertFrame(const uint8_t * currentFrame) {
  Log.trace("void Beam::convertFrame(const uint8_t * currentFrame)");
  int i = 0;

  //CS0 to CS3
  int n = 0;
  for (int y = 10; y > 0; --y) {
    i = (y < 6) ? 1 : 0;
    cs[0] |= (((uint16_t)(*(currentFrame + n) & segmentmask[0 + i]) << (3 + i)) >> y);
    cs[1] |= (((uint16_t)(*(currentFrame + n) & segmentmask[2 + i]) << (5 + i)) >> y);
    cs[2] |= (((uint16_t)(*(currentFrame + n) & segmentmask[4 + i]) << (7 + i)) >> y);
    cs[3] |= (((uint16_t)(*(currentFrame + n) & segmentmask[6 + i]) << (9 + i)) >> y);
    n += 3;

    if (n > 12) {
      n = 0;
    }
  }

  //CS4 to CS7
  n = 1;
  for (int y = 10; y > 0; --y) {
    i = (y < 6) ? 1 : 0;
    cs[4] |= (((uint16_t)(*(currentFrame + n) & segmentmask[0 + i]) << (3 + i)) >> y);
    cs[5] |= (((uint16_t)(*(currentFrame + n) & segmentmask[2 + i]) << (5 + i)) >> y);
    cs[6] |= (((uint16_t)(*(currentFrame + n) & segmentmask[4 + i]) << (7 + i)) >> y);
    cs[7] |= (((uint16_t)(*(currentFrame + n) & segmentmask[6 + i]) << (9 + i)) >> y);
    n += 3;

    if (n > 13) {
      n = 1;
    }
  }

  //CS8 - CS11
  n = 2;
  for (int y = 10; y > 0; --y) {
    i = (y < 6) ? 1 : 0;
    cs[8] |= (((uint16_t)(*(currentFrame + n) & segmentmask[0 + i]) << (3 + i)) >> y);
    cs[9] |= (((uint16_t)(*(currentFrame + n) & segmentmask[2 + i]) << (5 + i)) >> y);
    cs[10] |= (((uint16_t)(*(currentFrame + n) & segmentmask[4 + i]) << (7 + i)) >> y);
    cs[11] |= (((uint16_t)(*(currentFrame + n) & segmentmask[6 + i]) << (9 + i)) >> y);
    n += 3;

    if (n > 14) {
      n = 2;
    }
  }
}

void Beam::sendWriteCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg, uint8_t subregdata) {
  //Log.trace("void Beam::sendWriteCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg, uint8_t subregdata)");
  static int errCount = 0;
  if (!i2cwrite(addr, REGSEL, ramsection)) {
    i2cwrite(addr, subreg, subregdata);
    errCount = 0;
  }
  else {
    Log.warn("Beam not found: 0x%02x (%d)", addr, _beamCount);
    if (errCount++ > 50) _wire->reset();
  }
}

uint8_t Beam::sendReadCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg) {
  //Log.trace("uint8_t Beam::sendReadCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg)");
  i2cwrite(addr, REGSEL, ramsection);

  _wire->beginTransmission(addr);
  _wire->write(subreg);
  _wire->endTransmission();

  _wire->requestFrom(addr, (uint8_t)1);
    // wait up to 250ms for data  
  for (uint32_t _ms = millis(); !_wire->available() && millis() - _ms < 250; Particle.process());
  if (_wire->available()) return _wire->read();
  else _wire->reset();
  return 0;
}

uint8_t Beam::i2cwrite(uint8_t address, uint8_t cmdbyte, uint8_t databyte) { 
  //Log.trace("uint8_t Beam::i2cwrite(uint8_t address, uint8_t cmdbyte, uint8_t databyte)");
  _wire->beginTransmission(address);
  _wire->write(cmdbyte);
  _wire->write(databyte);
  return (_wire->endTransmission());
}
Die Losungen - beam.hC/C++
Tab 3/5
#pragma once
/*
===========================================================================
This is the library for Beam.

Beam is a beautiful LED matrix — features 120 LEDs that displays scrolling text, animations, or custom lighting effects.
Beam can be purchased here: http://www.hoverlabs.co

Written by Emran Mahbub and Jonathan Li for Hover Labs.
BSD license, all text above must be included in any redistribution

===========================================================================
*/
#define MAXFRAME 36
#define SPACE     3
#define KERNING   1


const uint8_t BEAM_ADDRESS[] = {0x36, 0x34, 0x30, 0x37};
#define BEAMA BEAM_ADDRESS[0]
#define BEAMB BEAM_ADDRESS[1]
#define BEAMC BEAM_ADDRESS[2]
#define BEAMD BEAM_ADDRESS[3]

//Sub Register address
enum BEAM_REGISTER {
  PIC       = 0x00,
  MOV       = 0x01,
  MOVMODE   = 0x02,
  FRAMETIME = 0x03,
  DISPLAYO  = 0x04,
  CURSRC    = 0x05,
  CFG       = 0x06,
  IRQMASK   = 0x07,
  IRQFRAME  = 0x08,
  SHDN      = 0x09,
  CLKSYNC   = 0x0B,
  //RAM section address
  CTRL      = 0xC0,
  REGSEL    = 0xFD,
};

//User modes
enum BEAM_MODE {
  PICTURE   = 0x01,
  MOVIE     = 0x02,
  SCROLL    = 0x03,
  FADEOFF   = 0x00,
  FADEON    = 0x01,
};

enum BEAM_ORIENTATION {
  RIGHT     = 0,
  LEFT      = 1,
};

class Beam {
public:
  Beam(int rstpin, int irqpin, int numberOfBeams);
  Beam(int rstpin, int irqpin, uint8_t syncMode, uint8_t beamAddress);
  bool begin(TwoWire& wire = Wire);
  void initBeam();
  void print(const char* text);
  void printFrame(uint8_t frameToPrint, const char * text);
  void play();
  void display();
  void draw();
  void setScroll(uint8_t direction, uint8_t fade);
  void setSpeed(uint8_t speed);
  void setLoops(uint8_t loops);
  void setMode(uint8_t mode);
  volatile int beamNumber;
  int checkStatus();
  int status();

private:
  const uint8_t *BEAM;
  uint16_t cs[12];
  uint16_t segmentmask[8];
  uint8_t  cscolumn[25];
  uint8_t  activeBeams;
  uint8_t  _gblMode;
  uint8_t  _syncMode;
  uint8_t  _lastFrameWrite;
  uint8_t  _scrollMode;
  uint8_t  _scrollDir;
  uint8_t  _fadeMode;
  uint8_t  _frameDelay;
  uint8_t  _beamMode;
  uint8_t  _numLoops;
  uint8_t  _beamCount;
  int      _rst;
  int      _irq;
  TwoWire *_wire;
  Timer   *_syncTimer;

  void startNextBeam();
  void initializeBeam(uint8_t b);
  void setPrintDefaults(uint8_t mode, uint8_t startFrame, uint8_t numFrames, uint8_t numLoops, uint8_t frameDelay, uint8_t scrollDir, uint8_t fadeMode);
  void writeFrame(uint8_t addr, uint8_t f);
  void convertFrame(const uint8_t * currentFrame);
  unsigned int setSyncTimer();
  void sendWriteCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg, uint8_t subregdata);
  uint8_t sendReadCmd(uint8_t addr, uint8_t ramsection, uint8_t subreg);
  uint8_t i2cwrite(uint8_t address, uint8_t cmdbyte, uint8_t databyte);
};
Die Losungen - charactermap.hC/C++
Tab 4/5
#pragma once
/*
===========================================================================    

  This is the library for Beam. 
  
  Beam is a beautiful LED matrix — features 120 LEDs that displays scrolling text, animations, or custom lighting effects. 
  Beam can be purchased here: http://www.hoverlabs.co
  
  Written by Emran Mahbub and Jonathan Li for Hover Labs.  
  BSD license, all text above must be included in any redistribution
  
===========================================================================
*/ 
#include <Particle.h>

const uint8_t charactermap[69][7] = {              
{0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      //  0 SPACE
{0x17,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      //  1 !
{0x03,0x00,0x03,0x00,0xFF,0x00,0xFF},      //  2 "
{0x0A,0x1F,0x0A,0x1F,0x0A,0x00,0xFF},      //  3 #
{0x17,0x15,0x1F,0x15,0x1D,0x00,0xFF},      //  4 $
{0x12,0x08,0x04,0x12,0x00,0xFF,0xFF},      //  5 %
{0x0A,0x15,0x0E,0x10,0x00,0xFF,0xFF},      //  6 &
{0x03,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      //  7 '
{0x0E,0x11,0x00,0xFF,0xFF,0xFF,0xFF},      //  8 (
{0x11,0x0E,0x00,0xFF,0xFF,0xFF,0xFF},      //  9 )
{0x05,0x02,0x05,0x00,0xFF,0xFF,0xFF},      // 10 *
{0x08,0x1C,0x08,0x00,0xFF,0xFF,0xFF},      // 11 +
{0x10,0x08,0x00,0xFF,0xFF,0xFF,0xFF},      // 12 ,
{0x04,0x04,0x00,0xFF,0xFF,0xFF,0xFF},      // 13 -
{0x10,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      // 14 .
{0x18,0x0E,0x03,0x00,0xFF,0xFF,0xFF},      // 15 /
{0x1F,0x11,0x1F,0x00,0xFF,0xFF,0xFF},      // 16 0
{0x02,0x1F,0x00,0xFF,0xFF,0xFF,0xFF},      // 17 1
{0x1D,0x15,0x17,0x00,0xFF,0xFF,0xFF},      // 18 2
{0x11,0x15,0x1F,0x00,0xFF,0xFF,0xFF},      // 19 3
{0x07,0x04,0x1F,0x00,0xFF,0xFF,0xFF},      // 20 4
{0x17,0x15,0x1D,0x00,0xFF,0xFF,0xFF},      // 21 5
{0x1F,0x15,0x1D,0x00,0xFF,0xFF,0xFF},      // 22 6
{0x01,0x1D,0x03,0x00,0xFF,0xFF,0xFF},      // 23 7
{0x1F,0x15,0x1F,0x00,0xFF,0xFF,0xFF},      // 24 8
{0x17,0x15,0x1F,0x00,0xFF,0xFF,0xFF},      // 25 9
{0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      // 26 :
{0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF},      // 27 ;
{0x04,0x0A,0x11,0x00,0xFF,0xFF,0xFF},      // 28 <
{0x0A,0x0A,0x0A,0x00,0xFF,0xFF,0xFF},      // 29 =
{0x11,0x0A,0x04,0x00,0xFF,0xFF,0xFF},      // 30 >
{0x01,0x15,0x07,0x00,0xFF,0xFF,0xFF},      // 31 ?
{0x1F,0x11,0x1D,0x15,0x1F,0x00,0xFF},      // 32 @
{0x1E,0x05,0x05,0x1E,0x00,0xFF,0xFF},      // 33 A
{0x1F,0x15,0x15,0x0A,0x00,0xFF,0xFF},      // 34 B
{0x0E,0x11,0x11,0x0A,0x00,0xFF,0xFF},      // 35 C
{0x1F,0x11,0x11,0x0E,0x00,0xFF,0xFF},      // 36 D
{0x1F,0x15,0x15,0x11,0x00,0xFF,0xFF},      // 37 E
//{0x1F,0x15,0x15,0x00,0xFF,0xFF,0xFF},      // 37 E narrow
{0x1F,0x05,0x05,0x00,0xFF,0xFF,0xFF},      // 38 F
{0x0E,0x11,0x15,0x1D,0x00,0xFF,0xFF},      // 39 G
{0x1F,0x04,0x04,0x1F,0x00,0xFF,0xFF},      // 40 H
{0x11,0x1F,0x11,0x00,0xFF,0xFF,0xFF},      // 41 I
{0x18,0x10,0x1F,0x00,0xFF,0xFF,0xFF},      // 42 J
{0x1F,0x04,0x1B,0x00,0xFF,0xFF,0xFF},      // 43 K
{0x1F,0x10,0x10,0x00,0xFF,0xFF,0xFF},      // 44 L
{0x1F,0x02,0x04,0x02,0x1F,0x00,0xFF},      // 45 M
{0x1F,0x02,0x04,0x08,0x1F,0x00,0xFF},      // 46 N
{0x0E,0x11,0x11,0x11,0x0E,0x00,0xFF},      // 47 O
{0x1F,0x05,0x05,0x02,0x00,0xFF,0xFF},      // 48 P
{0x0E,0x11,0x15,0x09,0x16,0x00,0xFF},      // 49 Q
{0x1F,0x05,0x0D,0x12,0x00,0xFF,0xFF},      // 50 R
{0x12,0x15,0x15,0x09,0x00,0xFF,0xFF},      // 51 S
{0x01,0x1F,0x01,0x00,0xFF,0xFF,0xFF},      // 52 T
{0x0F,0x10,0x10,0x0F,0x00,0xFF,0xFF},      // 53 U
{0x07,0x08,0x10,0x08,0x07,0x00,0xFF},      // 54 V
{0x0F,0x10,0x0C,0x10,0x0F,0x00,0xFF},      // 55 W
{0x11,0x0A,0x04,0x0A,0x11,0x00,0xFF},      // 56 X
{0x01,0x02,0x1C,0x02,0x01,0x00,0xFF},      // 57 Y
{0x11,0x19,0x15,0x13,0x11,0x00,0xFF},      // 58 Z
{0x1F,0x11,0x00,0xFF,0xFF,0xFF,0xFF},      // 59 [
{0x03,0x0E,0x18,0x00,0xFF,0xFF,0xFF},      // 60 /
{0x11,0x1F,0x00,0x00,0xFF,0xFF,0xFF},      // 61 ]
{0x06,0x0E,0x1C,0x0E,0x06,0x00,0xFF},      // 62 ^
{0x10,0x10,0x10,0x00,0xFF,0xFF,0xFF},      // 63 _
{0x01,0x02,0x00,0xFF,0xFF,0xFF,0xFF},      // 64 '
//{0x1F,0x05,0x05,0x1F,0x00,0xFF,0xFF},      // 65 A -> Ä
{0x1D,0x0A,0x0A,0x1D,0x00,0xFF,0xFF},      // 65 Ä added
//{0x0E,0x11,0x11,0x11,0x0E,0x00,0xFF},      // 66 O -> Ö
{0x0D,0x12,0x12,0x0D,0x00,0xFF,0xFF},      // 66 Ö added
//{0x1F,0x10,0x10,0x1F,0x00,0xFF,0xFF},      // 67 U -> Ü
{0x0D,0x10,0x10,0x0D,0x00,0xFF,0xFF},      // 67 Ü added
//{0x17,0x15,0x15,0x1D,0x00,0xFF,0xFF},      // 68 S -> ß
{0x1E,0x15,0x17,0x0D,0x00,0xFF,0xFF},      // 68 ß added
};
Die Losungen - frames.hC/C++
Tab 5/5
#pragma once
/*
===========================================================================    
  This is the library for Beam. 
  
  Beam is a beautiful LED matrix — features 120 LEDs that displays scrolling text, animations, or custom lighting effects. 
  Beam can be purchased here: http://www.hoverlabs.co
  
  Written by Emran Mahbub and Jonathan Li for Hover Labs.  
  BSD license, all text above must be included in any redistribution
  
===========================================================================
*/ 

const uint8_t frameList[MAXFRAME][15] = {
{                    //Frame 0
  0b00000000, 0b00000000, 0b00000000,     
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
},
{                    //Frame 1
  0b10000000, 0b00000000, 0b00000001,     
  0b10000000, 0b00000000, 0b00000001,
  0b10000000, 0b00000000, 0b00000001,
  0b10000000, 0b00000000, 0b00000001,
  0b10000000, 0b00000000, 0b00000001,
},
{                    //Frame 2
  0b11000000, 0b00000000, 0b00000011,     
  0b11000000, 0b00000000, 0b00000011,
  0b11000000, 0b00000000, 0b00000011,
  0b11000000, 0b00000000, 0b00000011,
  0b11000000, 0b00000000, 0b00000011,
},
{                    //Frame 3
  0b01100000, 0b00000000, 0b00000110,     
  0b01100000, 0b00000000, 0b00000110,
  0b01100000, 0b00000000, 0b00000110,
  0b01100000, 0b00000000, 0b00000110,
  0b01100000, 0b00000000, 0b00000110,
},
{                    //Frame 4
  0b00110000, 0b00000000, 0b00001100,     
  0b00110000, 0b00000000, 0b00001100,
  0b00110000, 0b00000000, 0b00001100,
  0b00110000, 0b00000000, 0b00001100,
  0b00110000, 0b00000000, 0b00001100,
},
{                    //Frame 5
  0b00011000, 0b00000000, 0b00011000,     
  0b00011000, 0b00000000, 0b00011000,
  0b00011000, 0b00000000, 0b00011000,
  0b00011000, 0b00000000, 0b00011000,
  0b00011000, 0b00000000, 0b00011000,
},
{                    //Frame 6
  0b00001100, 0b00000000, 0b00110000,     
  0b00001100, 0b00000000, 0b00110000,
  0b00001100, 0b00000000, 0b00110000,
  0b00001100, 0b00000000, 0b00110000,
  0b00001100, 0b00000000, 0b00110000,
},
{                    //Frame 7
  0b00000110, 0b00000000, 0b01100000,     
  0b00000110, 0b00000000, 0b01100000,
  0b00000110, 0b00000000, 0b01100000,
  0b00000110, 0b00000000, 0b01100000,
  0b00000110, 0b00000000, 0b01100000,
},
{                    //Frame 8
  0b00000011, 0b00000000, 0b11000000,     
  0b00000011, 0b00000000, 0b11000000,
  0b00000011, 0b00000000, 0b11000000,
  0b00000011, 0b00000000, 0b11000000,
  0b00000011, 0b00000000, 0b11000000,
},
{                    //Frame 9
  0b00000011, 0b11000011, 0b11000000,
  0b00000011, 0b11000011, 0b11000000,
  0b00000011, 0b11000011, 0b11000000,
  0b00000011, 0b11000011, 0b11000000,
  0b00000011, 0b11000011, 0b11000000,
},
{                    //Frame 10
  0b00000000, 0b00111100, 0b00000000,   
  0b00000000, 0b00111100, 0b00000000,
  0b00000000, 0b00111100, 0b00000000,
  0b00000000, 0b00111100, 0b00000000,
  0b00000000, 0b00111100, 0b00000000,
},
{                    //Frame 11
  0b00000000, 0b00011000, 0b00000000,     
  0b00000000, 0b00011000, 0b00000000,
  0b00000000, 0b00011000, 0b00000000,
  0b00000000, 0b00011000, 0b00000000,
  0b00000000, 0b00011000, 0b00000000,
},
{                    //Frame 12
  0b00000000, 0b00010000, 0b00000000,     
  0b00000000, 0b00101000, 0b00000000,
  0b00000000, 0b01000100, 0b00000000,
  0b00000000, 0b00101000, 0b00000000,
  0b00000000, 0b00010000, 0b00000000,
},
{                    //Frame 13
  0b00000000, 0b00101000, 0b00000000,     
  0b00000000, 0b01000100, 0b00000000,
  0b00000000, 0b10000010, 0b00000000,
  0b00000000, 0b01000100, 0b00000000,
  0b00000000, 0b00101000, 0b00000000,
},
{                    //Frame 14
  0b00000000, 0b01000010, 0b00000000,     
  0b00000000, 0b10000001, 0b00000000,
  0b00000001, 0b00000000, 0b10000000,
  0b00000000, 0b10000001, 0b00000000,
  0b00000000, 0b01000010, 0b00000000,
},
{                    //Frame 15
  0b00000000, 0b01000010, 0b00000000,     
  0b00000000, 0b10000001, 0b00000000,
  0b00000001, 0b00000000, 0b10000000,
  0b00000000, 0b10000001, 0b00000000,
  0b00000000, 0b01000010, 0b00000000,
},
{                    //Frame 16
  0b00000000, 0b11000011, 0b00000000,     
  0b00000001, 0b10000001, 0b10000000,
  0b00000011, 0b00000000, 0b11000000,
  0b00000001, 0b10000001, 0b10000000,
  0b00000000, 0b11000011, 0b00000000,
},
{                    //Frame 17
  0b00000011, 0b00000000, 0b11000000,     
  0b00000110, 0b00000000, 0b01100000,
  0b00001100, 0b00000000, 0b00110000,
  0b00000110, 0b00000000, 0b01100000,
  0b00000011, 0b00000000, 0b11000000,
},
{                    //Frame 18
  0b00000110, 0b00000000, 0b01100000,     
  0b00001100, 0b00000000, 0b00110000,
  0b00011000, 0b00000000, 0b00011000,
  0b00001100, 0b00000000, 0b00110000,
  0b00000110, 0b00000000, 0b01100000,
},
{                    //Frame 19
  0b00001100, 0b00000000, 0b00110000,     
  0b00011000, 0b00000000, 0b00011000,
  0b00110000, 0b00000000, 0b00001100,
  0b00011000, 0b00000000, 0b00011000,
  0b00001100, 0b00000000, 0b00110000,
},
{                    //Frame 20
  0b00011000, 0b00000000, 0b00011000,     
  0b00110000, 0b00000000, 0b00001100,
  0b01100000, 0b00000000, 0b00000110,
  0b00110000, 0b00000000, 0b00001100,
  0b00011000, 0b00000000, 0b00011000,
},
{                    //Frame 21
  0b00110000, 0b00000000, 0b00001100,     
  0b01100000, 0b00000000, 0b00000110,
  0b11000000, 0b00000000, 0b00000011,
  0b01100000, 0b00000000, 0b00000110,
  0b00110000, 0b00000000, 0b00001100,
},
{                    //Frame 22
  0b11100111, 0b10111101, 0b00010000,     
  0b10010100, 0b00100101, 0b10110000,
  0b11100111, 0b10111101, 0b01010000,
  0b10010100, 0b00100101, 0b00010000,
  0b11100111, 0b10100101, 0b00010000,
},
{                    //Frame 23
  0b00011000, 0b01000010, 0b11101111,     
  0b01101011, 0b11011010, 0b01001111,
  0b00011000, 0b01000010, 0b10101111,
  0b01101011, 0b11011010, 0b11101111,
  0b00011000, 0b01011010, 0b11101111,
},
{                    //Frame 24
  0b11100111, 0b10111101, 0b00010000,    
  0b10010100, 0b10100101, 0b10110000,
  0b11100111, 0b10111101, 0b01010000,
  0b10010100, 0b10100101, 0b00010000,
  0b11100111, 0b10100101, 0b00010000,
},
{                    //Frame 25
  0b00011000, 0b01000010, 0b11101111,     
  0b01101011, 0b11011010, 0b01001111,
  0b00011000, 0b01000010, 0b10101111,
  0b01101011, 0b11011010, 0b11101111,
  0b00011000, 0b01011010, 0b11101111,
},
{                    //Frame 26
  0b11100111, 0b10111101, 0b00010000,     
  0b10010100, 0b10100101, 0b10110000,
  0b11100111, 0b10111101, 0b01010000,
  0b10010100, 0b10100101, 0b00010000,
  0b11100111, 0b10100101, 0b00010000,
},
{                    //Frame 27
  0b00011000, 0b01000010, 0b11101111,     
  0b01101011, 0b11011010, 0b01001111,
  0b00011000, 0b01000010, 0b10101111,
  0b01101011, 0b11011010, 0b11101111,
  0b00011000, 0b01011010, 0b11101111,
},
{                    //Frame 28
  0b11100111, 0b10111101, 0b00010000,     
  0b10010100, 0b10100101, 0b10110000,
  0b11100111, 0b10111101, 0b01010000,
  0b10010100, 0b10100101, 0b00010000,
  0b11100111, 0b10100101, 0b00010000,
},
{                    //Frame 29
  0b00011000, 0b01000010, 0b11101111,     
  0b01101011, 0b11011010, 0b01001111,
  0b00011000, 0b01000010, 0b10101111,
  0b01101011, 0b11011010, 0b11101111,
  0b00011000, 0b01011010, 0b11101111,
},
{                    //Frame 30
  0b11100111, 0b10111101, 0b00010000,     
  0b10010100, 0b10100101, 0b10110000,
  0b11100111, 0b10111101, 0b01010000,
  0b10010100, 0b10100101, 0b00010000,
  0b11100111, 0b10100101, 0b00010000,
},
{                    //Frame 31
  0b11111111, 0b11111111, 0b11111111,     
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b11111111, 0b11111111, 0b11111111,
},
{                    //Frame 32
  0b00000000, 0b00000000, 0b00000000,     
  0b11111111, 0b11111111, 0b11111111,
  0b00000000, 0b00000000, 0b00000000,
  0b11111111, 0b11111111, 0b11111111,
  0b00000000, 0b00000000, 0b00000000,
},
{                    //Frame 33
  0b00000000, 0b00000000, 0b00000000,     
  0b00000000, 0b00000000, 0b00000000,
  0b11111111, 0b11111111, 0b11111111,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
},
{                    //Frame 34
  0b00000000, 0b00000000, 0b00000000,     
  0b00000000, 0b00000000, 0b00000000,
  0b00011111, 0b11111111, 0b11111000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
},
{                    //Frame 35
  0b00000000, 0b00000000, 0b00000000,     
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000,
},
};
Die Losungen - every day a new bible verse

Credits

Img 6554 3ywwumwxbh
Ingo Lohs

I am well over 40 years and come from the middle of Germany. You can contact me also in German. Donation for projects: paypal.me/ingolohs

Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Particle Photon Based Security System with Alerting
Intermediate
  • 1,345
  • 20

Full instructions

Be alerted to any door or window opening and closing in your house on your smart phone.

Happy Plant Notifier
Intermediate
  • 290
  • 5

Full instructions

Get a text or call if your plant is getting too dry, along with a nice LCD display giving information regarding your plant's health.

My Guardian for the Workshop
Intermediate
  • 202
  • 4

Full instructions

Device will send emails if the door or window has been opened, and will monitor the temperature and humidity of the place.

Smart and Safe Outdoor Plant Watering System
Intermediate
  • 2,526
  • 18

Monitors soil moisture and weather forecasts to give plants just the water they need. Safe garden hose hookup for season long watering.

Christmas Gift Box
Intermediate
  • 3,684
  • 595

Full instructions

Christmas Gift Box plays music and sends an email when it is opened.

Carbon Fiber Vacuum Chamber
Intermediate
  • 3,035
  • 94

Full instructions

Our project is a carbon fiber vacuum chamber that is monitored by multiple particle photons and various sensors.

Add projectSign up / Login