#include "lib.h"
#include <EEPROM.h>
#define STATE_NORMAL 0
#define STATE_SHORT 1
#define STATE_LONG 2
static const byte BUTTON_PIN = 21;
volatile int resultButton = 0; // global value set by checkButton()
const int MATRIX_SIZE = 8;
const int anodePins[MATRIX_SIZE] = {2, 3, 4, 5, 6, 7, 8, 9 };
const int cathodePins[MATRIX_SIZE] = {22, 23, 24, 25, 26, 27, 28, 29};
volatile bool isRightToLeft = false;
int address = 0;
int x = 0;
int indexDisplay[50];
int length = 0;
String prevStr;
String currStr;
const int debounceDelay = 10;
int count = 0;
int mode = 0;
int speedMode = 0;
int time = 0;
void setup() {
Serial.begin(115200);
for (int i = 0; i < MATRIX_SIZE; i++) {
pinMode(anodePins[i], OUTPUT);
digitalWrite(anodePins[i], LOW);
}
for (int i = 0; i < MATRIX_SIZE; i++) {
pinMode(cathodePins[i], OUTPUT);
digitalWrite(cathodePins[i], HIGH);
}
readIndexDisplayFromEEPROM();
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, CHANGE);
}
void readIndexDisplayFromEEPROM() {
int addr = 0;
Serial.println("Reset Power");
while (EEPROM.read(addr) != 255) {
indexDisplay[addr] = EEPROM.read(addr);
addr++;
}
if (addr > 0 ) {
length = addr - 1;
}
isRightToLeft = EEPROM.read(200);
if (EEPROM.read(201) != 255) {
speedMode = EEPROM.read(201);
}
}
void loop() {
switch (resultButton) {
case STATE_NORMAL: {
break;
}
case STATE_SHORT: {
if (mode == 0)
{
isRightToLeft = !isRightToLeft;
Serial.println("Changed scrolling direction!");
EEPROM.write(200,isRightToLeft);
}
else if (mode == 1)
{
if (speedMode == 2) {
speedMode = 0;
} else {
speedMode++;
}
Serial.print("Change speed mode to: ");
Serial.println(speedMode);
EEPROM.write(201,speedMode);
}
resultButton = STATE_NORMAL;
break;
}
case STATE_LONG: {
if (mode == 1) {
mode = 0;
} else {
mode++;
}
if (mode == 0) {
Serial.println("Scrolling Direction Change Mode");
} else if (mode == 1) {
Serial.println("Speed Change Mode");
}
resultButton = STATE_NORMAL;
break;
}
}
Serial.println("Input please: ");
String currStr = Serial.readString();
if (currStr != prevStr && currStr != "") {
char input[] = "";
length = currStr.length();
currStr.toCharArray(input,length);
convertStringToAlphaIndex(input, length);
if (!isRightToLeft) {
x = -6 * length; // for scrolling right
}
else if (isRightToLeft) {
x = 0; // for scrolling left
}
}
processTextOnLEDMatrix();
prevStr = currStr;
}
//check input in the range so we can detect the unknown character
void convertStringToAlphaIndex(char input[], int length) {
for (int i = 0; i < length; i++) {
int asciiValue = (int) input[i];
int alphaOrder = asciiValue - 64;
if (65 <= asciiValue && asciiValue <= 90) {
indexDisplay[i] = alphaOrder;
EEPROM.write(i,alphaOrder);
}
else if (97 <= asciiValue && asciiValue <= 122) {
alphaOrder -= 32;
indexDisplay[i] = alphaOrder;
EEPROM.write(i,alphaOrder);
}
else {
indexDisplay[i] = 0;
EEPROM.write(i,alphaOrder);
}
}
}
void processTextOnLEDMatrix() {
int endIndex = -(length)*6-3;
//scrolling left
if (isRightToLeft) {
while (x != endIndex) {
displayText();
switch(speedMode) {
case 0:
delay(150);
break;
case 1:
delay(115);
break;
case 2:
delay(90);
break;
}
x--;
}
x = 7;
} else {
//scrolling right
while (x != 7) {
displayText();
switch(speedMode) {
case 0:
delay(150);
break;
case 1:
delay(115);
break;
case 2:
delay(90);
break;
}
x++;
}
x = endIndex;
}
}
void displayText() {
for (int y = 0; y < LETTER_SIZE_Y; y++) {
for (int i = 0; i < MATRIX_SIZE; i++) {
pinMode(anodePins[i], OUTPUT);
digitalWrite(anodePins[i], LOW);
}
for (int i = 0; i < MATRIX_SIZE; i++) {
pinMode(cathodePins[i], OUTPUT);
digitalWrite(cathodePins[i], HIGH);
}
for (int k = 0; k < length; k++) {
displayLetter(indexDisplay[k],k,y);
}
digitalWrite(22 + y, LOW);
delay(1);
digitalWrite(22 + y, HIGH);
}
}
//the parameter for the function: x
// ii (order of the letter in the displayed text
// letterIndex (order of letter in the array)
// y
void displayLetter(int letterIndex, int ii, int y) {
if (-4 - 6 * ii + 11 >= x && x >= -4 - 6 * ii) {
digitalWrite(x + 1 + 6 * ii, LOW);
digitalWrite(x + 2 + 6 * ii, library_display[letterIndex][y][0]);
digitalWrite(x + 3 + 6 * ii, library_display[letterIndex][y][1]);
digitalWrite(x + 4 + 6 * ii, library_display[letterIndex][y][2]);
digitalWrite(x + 5 + 6 * ii, library_display[letterIndex][y][3]);
digitalWrite(x + 6 + 6 * ii, library_display[letterIndex][y][4]);
}
}
void checkButton() {
/*
* This function implements software debouncing for a two-state button.
* It responds to a short press and a long press and identifies between
* the two states. Your sketch can continue processing while the button
* function is driven by pin changes.
*/
const unsigned long LONG_DELTA = 1000ul; // hold seconds for a long press
const unsigned long DEBOUNCE_DELTA = 30ul; // debounce time
static int lastButtonStatus = HIGH; // HIGH indicates the button is NOT pressed
int buttonStatus; // button atate Pressed/LOW; Open/HIGH
static unsigned long longTime = 0ul, shortTime = 0ul; // future times to determine is button has been poressed a short or long time
boolean Released = true, Transition = false; // various button states
boolean timeoutShort = false, timeoutLong = false; // flags for the state of the presses
buttonStatus = digitalRead(BUTTON_PIN); // read the button state on the pin "BUTTON_PIN"
timeoutShort = (millis() > shortTime); // calculate the current time states for the button presses
timeoutLong = (millis() > longTime);
if (buttonStatus != lastButtonStatus) { // reset the timeouts if the button state changed
shortTime = millis() + DEBOUNCE_DELTA;
longTime = millis() + LONG_DELTA;
}
Transition = (buttonStatus != lastButtonStatus); // has the button changed state
Released = (Transition && (buttonStatus == HIGH)); // for input pullup circuit
lastButtonStatus = buttonStatus; // save the button status
if ( ! Transition) { //without a transition, there's no change in input
// if there has not been a transition, don't change the previous result
resultButton = STATE_NORMAL | resultButton;
return;
}
if (timeoutLong && Released) { // long timeout has occurred and the button was just released
resultButton = STATE_LONG | resultButton; // ensure the button result reflects a long press
} else if (timeoutShort && Released) { // short timeout has occurred (and not long timeout) and button was just released
resultButton = STATE_SHORT | resultButton; // ensure the button result reflects a short press
} else { // else there is no change in status, return the normal state
resultButton = STATE_NORMAL | resultButton; // with no change in status, ensure no change in button status
}
}