MajicDesigns / MD_Parola

Library for modular scrolling LED matrix text displays
GNU Lesser General Public License v2.1
428 stars 135 forks source link

ESP8266 + Parola_Display code #84

Closed CCERocks closed 3 years ago

CCERocks commented 3 years ago

Hi, i seem cant get this code merge together... maybe in the loop or in setup?

Parola_Scrolling_ESP8266 + Parola_Display

how to change this code

sprintf(curMessage, "%03d:%03d:%03d:%03d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);

to this ?

sprintf(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);

currently im using this code & it work to display the text but would not updated to curMessage from the web form.

P.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);

or maybe need to change from curText to curMessage in this loop ?

` if (P.displayAnimate()) // animates and returns true when an animation is completed { // Set the display for the next string. curText = (curText + 1) % ARRAY_SIZE(pc); P.setTextBuffer(pc[curText]);

// When we have gone back to the first string, set a new exit effect
// and when we have done all those set a new entry effect.
if (curText == 0)
{
  outFX = (outFX + 1) % ARRAY_SIZE(effect);
  if (outFX == 0)
  {
    inFX = (inFX + 1) % ARRAY_SIZE(effect);
    if (inFX == 0)
      P.setInvert(!P.getInvert());
  }

  P.setTextEffect(effect[inFX], effect[outFX]);
}
if (newMessageAvailable)
{
  strcpy(curMessage, newMessage);
  newMessageAvailable = false;
}
P.displayReset();

}`

well i need the button reset in the HTML too.

thanks

`// Use the Parola library to scroll text on the display // // Demonstrates receiving and displaying text received from a web interface. // // User can enter text through a web browser and this will display as a // scrolling message on the display. Some parameters for the text can also // be controlled from the web page. // // IP address for the ESP8266 is displayed on the scrolling display // after startup initialization and connection to the WiFi network. // // Connections for ESP8266 hardware SPI are: // Vcc 3v3 LED matrices seem to work at 3.3V // GND GND GND // DIN D7 HSPID or HMOSI // CS or LD D8 HSPICS or HCS // CLK D5 CLK or HCLK // // MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX //

include

include

include

include

// Turn on debug statements to the serial output

define DEBUG 0

if DEBUG

define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }

define PRINTS(x) Serial.print(F(x))

define PRINTX(x) Serial.println(x, HEX)

else

define PRINT(s, x)

define PRINTS(x)

define PRINTX(x)

endif

// Define the number of devices we have in the chain and the hardware interface // NOTE: These pin numbers are for ESO8266 hardware SPI and will probably not // work with your hardware and may need to be adapted

define HARDWARE_TYPE MD_MAX72XX::FC16_HW

define MAX_DEVICES 12

define CLK_PIN D5 // or SCK

define DATA_PIN D7 // or MOSI

define CS_PIN D8 // or SS

// HARDWARE SPI MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // SOFTWARE SPI //MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// WiFi login parameters - network name and password const char ssid = "CABot"; const char password = "HelloCoVid";

// WiFi Server object and parameters WiFiServer server(80);

// Starting Parameters uint8_t frameDelay = 25; // default frame delay value textEffect_t Effect = PA_SPRITE; textPosition_t just = PA_CENTER;

define SPEED_TIME 25

define PAUSE_TIME 2000

// Global variables uint8_t curText; const char *pc[] = { "RUBY", "AMETHYST", "JADE", "FLUORITE", "TIGER_EYES", "TURQUOISE", "LAVA STONE", };

uint8_t inFX, outFX; textEffect_t effect[] = { PA_PRINT, // PA_SCAN_HORIZ, // PA_SCROLL_LEFT, // PA_WIPE, // PA_SCROLL_UP_LEFT, PA_SCROLL_UP, PA_OPENING_CURSOR, PA_GROW_UP, // PA_MESH, // PA_SCROLL_UP_RIGHT, PA_BLINDS, PA_CLOSING, PA_RANDOM, PA_GROW_DOWN, // PA_SCAN_VERT, PA_SCROLL_DOWN_LEFT, PA_WIPE_CURSOR, PA_DISSOLVE, PA_OPENING, PA_CLOSING_CURSOR, PA_SCROLL_DOWN_RIGHT, PA_SCROLL_RIGHT, // PA_SLICE, PA_SCROLL_DOWN, PA_SPRITE, };

//// Effect Bundle //struct sCatalog //{ // textEffect_t Effect; // text effect to display // const char psz; // text string nul terminated // uint16_t speed; // speed multiplier of library default // uint16_t pause; // pause multiplier for library default //}; // //struct sMesgEffect //{ // textEffect_t Effect; // text effect to display //// const char psz; // text string nul terminated //// const char * newMessage; // uint16_t speed; // speed multiplier of library default // uint16_t pause; // pause multiplier for library default //}; // //sMesgEffect msglog[] = //{ // { PA_SCAN_HORIZ, 1, 5 }, //}; // //sCatalog catalog[] = //{ // { PA_SCAN_HORIZ, "KLSTREETARTIST", 1, 5 }, //#if ENA_SPRITE // { PA_SPRITE, "IG BATUIKATEPI", 1, 5 }, //#endif // { PA_FADE, "ALL ORIGINAL STONE", 1, 5 }, // { PA_SCROLL_UP, "RUBY", 1, 5 }, // { PA_SCROLL_DOWN, "AMETHYST", 1, 5 }, // { PA_SCROLL_UP, "JADE", 1, 5 }, // { PA_SCROLL_DOWN, "FLUORITE", 1, 5 }, // { PA_SCROLL_UP, "TIGER_EYES", 1, 5 }, // { PA_SCROLL_DOWN, "TURQUOISE", 1, 5 }, // { PA_SCROLL_UP, "LAVA STONE", 1, 5 }, // { PA_SCROLL_DOWN, "METEOROID", 1, 5 }, // { PA_SCROLL_UP, "CRYSTAL", 1, 5 }, // { PA_SCROLL_DOWN, "ROSE QUARTZ", 1, 5 }, //#if ENA_SPRITE // { PA_SPRITE, "IG PUTRA PELUKIS", 1, 5 }, //#endif // { PA_SCAN_HORIZ, "IG BATUIKATEPI", 1, 5 }, // { PA_FADE, "ALL ORIGINAL STONE", 1, 5 }, // { PA_SCAN_HORIZ, "IG BATUIKATEPI", 1, 5 }, // { PA_SCAN_HORIZ, "KLSTREETARTIST", 1, 5 }, //};

// Sprite Definitions const uint8_t F_PMAN1 = 6; const uint8_t W_PMAN1 = 8; static const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation { 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, };

const uint8_t F_PMAN2 = 6; const uint8_t W_PMAN2 = 18; static const uint8_t PROGMEM pacman2[F_PMAN2 * W_PMAN2] = // ghost pursued by a pacman { 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, };

// Global message buffers shared by Wifi and Scrolling functions

define BUF_SIZE 512

char curMessage[BUF_SIZE]; char newMessage[BUF_SIZE]; bool newMessageAvailable = false;

const char WebResponse[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";

const char WebPage[] = "<!DOCTYPE html>" \ "" \ "" \ "LED Dot Ticker" \

"" \ "" \

"" \ "

MD_Parola set message

" \

"<form id=\"data_form\" name=\"frmText\">" \ "" \ "

" \ "<input type = \"radio\" name = \"Invert\" value = \"0\" checked> Normal" \ "<input type = \"radio\" name = \"Invert\" value = \"1\"> Inverse" \ "
" \ "<input type = \"radio\" name = \"ScrollType\" value = \"L\" checked> Left Scroll" \ "<input type = \"radio\" name = \"ScrollType\" value = \"R\"> Right Scroll" \ "
" \ "<input type = \"radio\" name = \"EffectType\" value = \"Fade\"> Fade" \ "<input type = \"radio\" name = \"EffectType\" value = \"Scan\"> Scan" \ "

" \ "

const char *err2Str(wl_status_t code) { switch (code) { case WL_IDLE_STATUS: return("IDLE"); break; // WiFi is in process of changing between statuses case WL_NO_SSID_AVAIL: return("NO_SSID_AVAIL"); break; // case configured SSID cannot be reached case WL_CONNECTED: return("CONNECTED"); break; // successful connection is established case WL_CONNECT_FAILED: return("CONNECT_FAILED"); break; // password is incorrect case WL_DISCONNECTED: return("CONNECT_FAILED"); break; // module is not configured in station mode default: return("??"); } }

uint8_t htoi(char c) { c = toupper(c); if ((c >= '0') && (c <= '9')) return(c - '0'); if ((c >= 'A') && (c <= 'F')) return(c - 'A' + 0xa); return(0); }

void getData(char szMesg, uint16_t len) // Message may contain data for: // New text (/&MSG=) // Scroll direction (/&SD=) // Invert (/&I=) // Speed (/&SP=) { char pStart, *pEnd; // pointer to start and end of text

// check text message pStart = strstr(szMesg, "/&MSG="); if (pStart != NULL) { char *psz = newMessage;

pStart += 6;  // skip to start of data
pEnd = strstr(pStart, "/&");

if (pEnd != NULL)
{
  while (pStart != pEnd)
  {
    if ((*pStart == '%') && isdigit(*(pStart + 1)))
    {
      // replace %xx hex code with the ASCII character
      char c = 0;
      pStart++;
      c += (htoi(*pStart++) << 4);
      c += htoi(*pStart++);
      *psz++ = c;
    }
    else
      *psz++ = *pStart++;
  }

  *psz = '\0'; // terminate the string
  newMessageAvailable = (strlen(newMessage) != 0);
  PRINT("\nNew Msg: ", newMessage);
}

}

// check effect

pStart = strstr(szMesg, "/&EFX="); if (pStart != NULL) { pStart += 5; // skip to start of data

PRINT("\nEffect ", *pStart);
Effect = (*pStart == 'FX' ? PA_FADE : PA_FADE);
P.setTextEffect(Effect, Effect);
P.displayReset();

}

// check scroll direction pStart = strstr(szMesg, "/&SD="); if (pStart != NULL) { pStart += 5; // skip to start of data

PRINT("\nScroll direction: ", *pStart);
Effect = (*pStart == 'R' ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(Effect, Effect);
P.displayReset();

}

// check invert pStart = strstr(szMesg, "/&I="); if (pStart != NULL) { pStart += 4; // skip to start of data

PRINT("\nInvert mode: ", *pStart);
P.setInvert(*pStart == '1');

}

// check speed pStart = strstr(szMesg, "/&SP="); if (pStart != NULL) { pStart += 5; // skip to start of data

int16_t speed = atoi(pStart);
PRINT("\nSpeed: ", P.getSpeed());
P.setSpeed(speed);
frameDelay = speed;

} }

void handleWiFi(void) { static enum { S_IDLE, S_WAIT_CONN, S_READ, S_EXTRACT, S_RESPONSE, S_DISCONN } state = S_IDLE; static char szBuf[1024]; static uint16_t idxBuf = 0; static WiFiClient client; static uint32_t timeStart;

switch (state) { case S_IDLE: // initialise PRINTS("\nS_IDLE"); idxBuf = 0; state = S_WAIT_CONN; break;

case S_WAIT_CONN: // waiting for connection { client = server.available(); if (!client) break; if (!client.connected()) break;

if DEBUG

char szTxt[20];
sprintf(szTxt, "%03d:%03d:%03d:%03d", client.remoteIP()[0], client.remoteIP()[1], client.remoteIP()[2], client.remoteIP()[3]);
PRINT("\nNew client @ ", szTxt);

endif

timeStart = millis();
state = S_READ;

} break;

case S_READ: // get the first line of data PRINTS("\nS_READ ");

while (client.available())
{
  char c = client.read();

  if ((c == '\r') || (c == '\n'))
  {
    szBuf[idxBuf] = '\0';
    client.flush();
    PRINT("\nRecv: ", szBuf);
    state = S_EXTRACT;
  }
  else
    szBuf[idxBuf++] = (char)c;
}
if (millis() - timeStart > 1000)
{
  PRINTS("\nWait timeout");
  state = S_DISCONN;
}
break;

case S_EXTRACT: // extract data PRINTS("\nS_EXTRACT"); // Extract the string from the message if there is one getData(szBuf, BUF_SIZE); state = S_RESPONSE; break;

case S_RESPONSE: // send the response to the client PRINTS("\nS_RESPONSE"); // Return the response to the client (web page) client.print(WebResponse); client.print(WebPage); state = S_DISCONN; break;

case S_DISCONN: // disconnect client PRINTS("\nS_DISCONN"); client.flush(); client.stop(); state = S_IDLE; break;

default: state = S_IDLE; } }

void setup() { Serial.begin(57600); PRINTS("\n[MD_Parola WiFi Message Display]\nType a message for the scrolling display from your internet browser");

P.begin(); P.displayClear(); P.displaySuspend(false);

P.displayScroll(curMessage, PA_LEFT, Effect, frameDelay);

curMessage[0] = newMessage[0] = '\0';

if ENA_SPRITE

P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);

endif

// for (uint8_t i=0; i<ARRAY_SIZE(catalog); i++) // { // catalog[i].speed = P.getSpeed(); // catalog[i].pause = 500; // }

// Connect to and initialise WiFi network PRINT("\nConnecting to ", ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) { PRINT("\n", err2Str(WiFi.status())); delay(500); } PRINTS("\nWiFi connected");

// Start the server server.begin(); PRINTS("\nServer started");

P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);

static textPosition_t just = PA_CENTER; static uint8_t i = 0; // text effect index

P.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);
// Set up first message as the IP address // sprintf(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]); // sprintf(curMessage); // i++;

PRINT("\nAssigned IP ", curMessage); }

void loop() { static textPosition_t just = PA_CENTER; static uint8_t i = 0; // text effect index

if (P.displayAnimate()) // animates and returns true when an animation is completed { // Set the display for the next string. curText = (curText + 1) % ARRAY_SIZE(pc); P.setTextBuffer(pc[curText]);

// When we have gone back to the first string, set a new exit effect
// and when we have done all those set a new entry effect.
if (curText == 0)
{
  outFX = (outFX + 1) % ARRAY_SIZE(effect);
  if (outFX == 0)
  {
    inFX = (inFX + 1) % ARRAY_SIZE(effect);
    if (inFX == 0)
      P.setInvert(!P.getInvert());
  }

  P.setTextEffect(effect[inFX], effect[outFX]);
}
if (newMessageAvailable)
{
  strcpy(curMessage, newMessage);
  newMessageAvailable = false;
}
P.displayReset();

}

handleWiFi(); }`

MajicDesigns commented 3 years ago

'or maybe need to change from curText to curMessage in this loop

Yes.

CCERocks commented 3 years ago

Hi, i do success to intergrate the ESP8266 with Parola Display (for starting intro will use all the effect) but couldnt reset it yet from web command..

`// Use the Parola library to scroll text on the display // // Demonstrates receiving and displaying text received from a web interface. // // User can enter text through a web browser and this will display as a // scrolling message on the display. Some parameters for the text can also // be controlled from the web page. // // IP address for the ESP8266 is displayed on the scrolling display // after startup initialization and connection to the WiFi network. // // Connections for ESP8266 hardware SPI are: // Vcc 3v3 LED matrices seem to work at 3.3V // GND GND GND // DIN D7 HSPID or HMOSI // CS or LD D8 HSPICS or HCS // CLK D5 CLK or HCLK // // MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX //

include

include

include

include

// Turn on debug statements to the serial output

define DEBUG 0

if DEBUG

define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }

define PRINTS(x) Serial.print(F(x))

define PRINTX(x) Serial.println(x, HEX)

else

define PRINT(s, x)

define PRINTS(x)

define PRINTX(x)

endif

// Define the number of devices we have in the chain and the hardware interface // NOTE: These pin numbers are for ESO8266 hardware SPI and will probably not // work with your hardware and may need to be adapted

define HARDWARE_TYPE MD_MAX72XX::FC16_HW

define MAX_DEVICES 12

define CLK_PIN D5 // or SCK

define DATA_PIN D7 // or MOSI

define CS_PIN D8 // or SS

// HARDWARE SPI MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // SOFTWARE SPI //MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// WiFi login parameters - network name and password const char ssid = "CABot"; const char password = "HelloCoVid";

// WiFi Server object and parameters WiFiServer server(80);

// Starting Parameters uint8_t frameDelay = 25; // default frame delay value textEffect_t Effect = PA_SPRITE; textPosition_t just = PA_CENTER;

define SPEED_TIME 25

define PAUSE_TIME 2000

// Global variables uint8_t curText; const char *pc[] = { "RUBY", "AMETHYST", "JADE", "FLUORITE", "TIGER_EYES", "TURQUOISE", "LAVA STONE", "METEOROID", "CRYSTAL", "ROSE QUARTZ", "FLUORITE", "TIGER_EYES", };

uint8_t inFX, outFX; textEffect_t effect[] = { // PA_PRINT, // PA_SCAN_HORIZ, // PA_SCROLL_LEFT, // PA_WIPE, // PA_SCROLL_UP_LEFT, PA_SCROLL_UP, PA_OPENING_CURSOR, PA_GROW_UP, // PA_MESH, // PA_SCROLL_UP_RIGHT, PA_BLINDS, PA_CLOSING, PA_RANDOM, PA_GROW_DOWN, // PA_SCAN_VERT, PA_SCROLL_DOWN_LEFT, PA_WIPE_CURSOR, PA_DISSOLVE, PA_OPENING, PA_CLOSING_CURSOR, PA_SCROLL_DOWN_RIGHT, PA_SCROLL_RIGHT, // PA_SLICE, PA_SCROLL_DOWN, PA_SPRITE, };

// Sprite Definitions const uint8_t F_PMAN1 = 6; const uint8_t W_PMAN1 = 8; static const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation { 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, };

const uint8_t F_PMAN2 = 6; const uint8_t W_PMAN2 = 18; static const uint8_t PROGMEM pacman2[F_PMAN2 * W_PMAN2] = // ghost pursued by a pacman { 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, };

// Global message buffers shared by Wifi and Scrolling functions

define BUF_SIZE 512

char curMessage[BUF_SIZE]; char newMessage[BUF_SIZE]; bool newMessageAvailable = false;

const char WebResponse[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";

const char WebPage[] = "<!DOCTYPE html>" \ "" \ "" \ "LED Dot Ticker" \ "" \ "" \ "" \

"" \ "

" \

"<form id=\"data_form\" name=\"frmText\">" \ "" \ "

" \ "<input type = \"radio\" name = \"Invert\" value = \"0\" > Normal" \ "<input type = \"radio\" name = \"Invert\" value = \"1\"> Inverse" \ "
" \ "<input type = \"radio\" name = \"ScrollType\" value = \"L\" > Left Scroll" \ "<input type = \"radio\" name = \"ScrollType\" value = \"R\"> Right Scroll" \ "
" \ "<input type = \"radio\" name = \"EffectType\" value = \"Fade\"> Fade" \ "<input type = \"radio\" name = \"EffectType\" value = \"Scan\"> Scan" \ "

" \ "

const char *err2Str(wl_status_t code) { switch (code) { case WL_IDLE_STATUS: return("IDLE"); break; // WiFi is in process of changing between statuses case WL_NO_SSID_AVAIL: return("NO_SSID_AVAIL"); break; // case configured SSID cannot be reached case WL_CONNECTED: return("CONNECTED"); break; // successful connection is established case WL_CONNECT_FAILED: return("CONNECT_FAILED"); break; // password is incorrect case WL_DISCONNECTED: return("CONNECT_FAILED"); break; // module is not configured in station mode default: return("??"); } }

uint8_t htoi(char c) { c = toupper(c); if ((c >= '0') && (c <= '9')) return(c - '0'); if ((c >= 'A') && (c <= 'F')) return(c - 'A' + 0xa); return(0); }

void getData(char szMesg, uint16_t len) // Message may contain data for: // New text (/&MSG=) // Scroll direction (/&SD=) // Invert (/&I=) // Speed (/&SP=) { char pStart, *pEnd; // pointer to start and end of text

// check text message pStart = strstr(szMesg, "/&MSG="); if (pStart != NULL) { char *psz = newMessage;

pStart += 6;  // skip to start of data
pEnd = strstr(pStart, "/&");

if (pEnd != NULL)
{
  while (pStart != pEnd)
  {
    if ((*pStart == '%') && isdigit(*(pStart + 1)))
    {
      // replace %xx hex code with the ASCII character
      char c = 0;
      pStart++;
      c += (htoi(*pStart++) << 4);
      c += htoi(*pStart++);
      *psz++ = c;
    }
    else
      *psz++ = *pStart++;
  }

  *psz = '\0'; // terminate the string
  newMessageAvailable = (strlen(newMessage) != 0);
  PRINT("\nNew Msg: ", newMessage);
}

}

// check effect

pStart = strstr(szMesg, "/&EFX="); if (pStart != NULL) { pStart += 5; // skip to start of data

PRINT("\nEffect ", *pStart);
Effect = (*pStart == 'FX' ? PA_FADE : PA_FADE);
P.setTextEffect(Effect, Effect);
P.displayReset();

}

// check scroll direction pStart = strstr(szMesg, "/&SD="); if (pStart != NULL) { pStart += 5; // skip to start of data

PRINT("\nScroll direction: ", *pStart);
Effect = (*pStart == 'R' ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(Effect, Effect);
P.displayReset();

}

// check invert pStart = strstr(szMesg, "/&I="); if (pStart != NULL) { pStart += 4; // skip to start of data

PRINT("\nInvert mode: ", *pStart);
P.setInvert(*pStart == '1');

}

// check speed pStart = strstr(szMesg, "/&SP="); if (pStart != NULL) { pStart += 5; // skip to start of data

int16_t speed = atoi(pStart);
PRINT("\nSpeed: ", P.getSpeed());
P.setSpeed(speed);
frameDelay = speed;

} }

void handleWiFi(void) { static enum { S_IDLE, S_WAIT_CONN, S_READ, S_EXTRACT, S_RESPONSE, S_DISCONN } state = S_IDLE; static char szBuf[1024]; static uint16_t idxBuf = 0; static WiFiClient client; static uint32_t timeStart;

switch (state) { case S_IDLE: // initialise PRINTS("\nS_IDLE"); idxBuf = 0; state = S_WAIT_CONN; break;

case S_WAIT_CONN: // waiting for connection { client = server.available(); if (!client) break; if (!client.connected()) break;

if DEBUG

char szTxt[20];
sprintf(szTxt, "%03d:%03d:%03d:%03d", client.remoteIP()[0], client.remoteIP()[1], client.remoteIP()[2], client.remoteIP()[3]);
PRINT("\nNew client @ ", szTxt);

endif

timeStart = millis();
state = S_READ;

} break;

case S_READ: // get the first line of data PRINTS("\nS_READ ");

while (client.available())
{
  char c = client.read();

  if ((c == '\r') || (c == '\n'))
  {
    szBuf[idxBuf] = '\0';
    client.flush();
    PRINT("\nRecv: ", szBuf);
    state = S_EXTRACT;
  }
  else
    szBuf[idxBuf++] = (char)c;
}
if (millis() - timeStart > 1000)
{
  PRINTS("\nWait timeout");
  state = S_DISCONN;
}
break;

case S_EXTRACT: // extract data PRINTS("\nS_EXTRACT"); // Extract the string from the message if there is one getData(szBuf, BUF_SIZE); state = S_RESPONSE; break;

case S_RESPONSE: // send the response to the client PRINTS("\nS_RESPONSE"); // Return the response to the client (web page) client.print(WebResponse); client.print(WebPage); state = S_DISCONN; break;

case S_DISCONN: // disconnect client PRINTS("\nS_DISCONN"); client.flush(); client.stop(); state = S_IDLE; break;

default: state = S_IDLE; } }

void setup() { Serial.begin(57600); PRINTS("\n[MD_Parola WiFi Message Display]\nType a message for the scrolling display from your internet browser");

P.begin(); P.displayClear(); P.displaySuspend(false);

P.displayScroll(curMessage, PA_LEFT, Effect, frameDelay);

curMessage[0] = newMessage[0] = '\0';

if ENA_SPRITE

P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);

endif

// Connect to and initialise WiFi network PRINT("\nConnecting to ", ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) { PRINT("\n", err2Str(WiFi.status())); delay(500); } PRINTS("\nWiFi connected");

// Start the server server.begin(); PRINTS("\nServer started");

static textPosition_t just = PA_CENTER; static uint8_t i = 0; // text effect index

// Set up first message as the IP address sprintf(curMessage, "%03d:%03d:%03d:%03d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);

P.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);

// sprintf(curMessage); // i++;

PRINT("\nAssigned IP ", curMessage); }

void loop() { static textPosition_t just = PA_CENTER; static uint8_t i = 0; // text effect index

if (P.displayAnimate()) // animates and returns true when an animation is completed { // Set the display for the next string. curText = (curText + 1) % ARRAY_SIZE(pc); P.setTextBuffer(pc[curText]);

// When we have gone back to the first string, set a new exit effect
// and when we have done all those set a new entry effect.
if (newMessage <= 0)
{
  P.setTextBuffer(pc[curText]);
  P.displayReset();
  P.displayClear();
  outFX = (outFX + 1) % ARRAY_SIZE(effect);
  if (outFX == 0)
  {
    inFX = (inFX + 1) % ARRAY_SIZE(effect);
    if (inFX == 0)
      P.setInvert(!P.getInvert());
  }

  P.setTextEffect(effect[inFX], effect[outFX]);

  P.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);
}
if (newMessageAvailable)
{
  P.setTextBuffer(curMessage);
  strcpy(curMessage, newMessage);
  newMessageAvailable = true;
}
P.displayReset();

}

handleWiFi(); }`