ArcheryClock-Arduino/ArcheryClockMEGA02_1.ino

315 lines
12 KiB
C++

//Copyright (C) 2010-2014 Henk Jegers
//Copyright (C) 2019 giuliof (GOLEM)
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//for questions email to info@archeryclock.com
// version MEGA01 Initial version
// version MEGA01_1 Adding robustness for receiving ABCD detailes which is implemented in AC 232. Using the ABCD details information is not yet implemented in MEGA01_1 Needs archeryclock version 2320 or newer.
// version MEGA01_2 Added end number information. Needs Archeryclock2401 or newer. (older archeryclock versions don't sent the end number information to arduine)
// version MEGA02_1 Changes because of a change in protocoll for AC 241 (nr of archers and E and F shooters) and added functionality: emergency stop, add archers E and F. Changes for signal robustness. (0 (0000) is sent as 12 (1100) to prevent decoding issues when 3 times 0 is sent (000000000000)
#include "utils.h"
String inputString;
int serialvalue;
int statevalue; //received data for state details.
int trafficvalue; //received data for traffic lights, and ABCD lights
int leftcountvalue; //received data for left countdown.
int rightcountvalue; //received data for rightcountdown.
// int abcdvalue; //received data for abcd details
int endnrvalue; //received data for end nr
// int buttonvalue;
// int remember1;
// int loop1;
int blinkk;
int blinkkk;
int blinkl;
int blinkr;
int rightdigit; //value of left digit (0..10 (10 means dashes))
int middigit; //value of middle digit (0..10 (10 means dashes))
int leftdigit; //value of light digit (0..10 (10 means dashes))
bool dots = false;
// int lefend; //value of left digit to indicate end nr (0..9 or 15 (15 means P to indicate practise end))
// int midend; //value of middle digit to indicate end nr (0..9)
// int rigend; //value of middle digit to indicate end nr (0..9)
// int comend; //value of combined left and middle digit. In case of practise end the P from the left digit should be projected. else the middle digit (0..9 or 15 (15 means P to indicate practise end))
#define DOTS_bm _BV(7)
#define ABCD_PORT A
#define LEFTDIGIT_PORT K
#define MIDDIGIT_PORT L
#define RIGHTDIGIT_PORT C
#define TRAFLIGHT_PORT F
#define HORNP_PIN 7
#define REDP_PIN 6
#define ORANGEP_PIN 5
#define GREENP_PIN 4
#define notA_PIN 78
#define notB_PIN 77
#define notC_PIN 76
#define notD_PIN 75
#define A_PIN 74
#define B_PIN 73
#define C_PIN 72
#define D_PIN 71
#define LR_PIN 9
#define MUTE_PIN 8
const int segment[16] = {0x03f, 0x006, 0x05b, 0x04f, 0x066, 0x06d, 0x07d, 0x007, 0x07f, 0x06f, 0x040, 0x000, 0x03f, 0x000, 0x000, 0x073}; //0,1,2,3,4,5,6,7,8,9,-, , , , ,P
void setup()
{
pinMode(LR_PIN, INPUT_PULLUP);
pinMode(MUTE_PIN, INPUT_PULLUP);
CATDDR(ABCD_PORT) = 0xFF;
CATDDR(LEFTDIGIT_PORT) = 0xFF;
CATDDR(MIDDIGIT_PORT) = 0xFF;
CATDDR(RIGHTDIGIT_PORT) = 0xFF;
CATDDR(TRAFLIGHT_PORT) = 0xFF;
pinMode(REDP_PIN, OUTPUT);
pinMode(ORANGEP_PIN, OUTPUT);
pinMode(GREENP_PIN, OUTPUT);
pinMode(HORNP_PIN, OUTPUT);
// buttonvalue = 0;
// remember1 = 0;
// loop1 = 0;
blinkk = 0;
blinkkk = 0;
blinkl = 0;
blinkr = 0;
rightcountvalue = 0xAAA0;
leftcountvalue = 0xAAA0;
serialvalue = 0x0000;
Serial.begin(9600); // Debug UART
Serial1.begin(9600); // Debug UART
Serial.println("Arduino Serial Link");
Serial.println("connected!");
}
void loop()
{
inputString = ""; // Clear inputString
// A command is received
if (Serial1.available())
{
// Parse all (because is splitted in multiple bytes -- 2 bytes)
while ((Serial1.available()))
{
char digit = Serial1.read(); // Read serial buffer
if (digit != '\n')
{
inputString += digit;
}; // Add new character to the string inputString
delay(2); // Let the serial buffer catch its breath.
serialvalue = inputString.toInt();
};
// Now decode command and apply to the panel
// Refer to documentation for command structure
if ((serialvalue & 0x01) && not(serialvalue & 0x06))
{
trafficvalue = serialvalue;
}; //traficlights
// if((serialvalue&0x03) && not(serialvalue&0x0C)){ abcdvalue=serialvalue;}; //ABCD details
if ((serialvalue & 0x01) && (serialvalue & 0x02) && (serialvalue & 0x04) && not(serialvalue & 0x08))
{
endnrvalue = serialvalue;
}; //endnr info
if ((serialvalue & 0x01) && (serialvalue & 0x02) && (serialvalue & 0x04) && (serialvalue & 0x08))
{
statevalue = serialvalue;
}; //state info
if ((not(serialvalue & 0x01)) && ((serialvalue & 0x02) or (serialvalue & 0x04)))
{
rightcountvalue = serialvalue;
}; //determine the digits value of the rightside
if ((not(serialvalue & 0x01)) && ((not(serialvalue & 0x02)) or (serialvalue & 0x04)))
{
leftcountvalue = serialvalue;
}; //determine the digits value of the leftside
};
// (hypothesis) blink algorithm for not{A,B,C,D}
if (blinkk == 0)
{
blinkk = 300;
}
else
{
blinkk--;
};
if (blinkkk == 0)
{
blinkkk = 2400;
}
else
{
blinkkk--;
};
if (blinkkk > 1200)
{
blinkr = 0;
blinkl = ((blinkk > 200) ? HIGH : LOW);
}
else
{
blinkr = ((blinkk > 200) ? HIGH : LOW);
blinkl = 0;
};
// Set ABCD(EF)
digitalWrite(A_PIN, (trafficvalue & 0x0400) ? HIGH : LOW); //A
digitalWrite(B_PIN, (trafficvalue & 0x0800) ? HIGH : LOW); //B
digitalWrite(C_PIN, (trafficvalue & 0x1000) ? HIGH : LOW); //C
digitalWrite(D_PIN, (trafficvalue & 0x2000) ? HIGH : LOW); //D
// EF not implemented in this hardware
// Set Horn
if (digitalRead(MUTE_PIN)) { // buzzer yes/no switch
digitalWrite(HORNP_PIN, (trafficvalue & 0x0008) ? HIGH : LOW);
}
else { // Stay silenced
digitalWrite(HORNP_PIN, LOW);
}
// Set not{A,B,C,D,(E,F)}
if ((((statevalue >> 4) & B00000111) != 6) ? HIGH : LOW)
{
digitalWrite(notA_PIN, (((((statevalue >> 13) & B00000111) < 1) ? LOW : HIGH) and (not(trafficvalue & 0x0400) ? HIGH : LOW))); //notA. Is on if Archer A exist but it is not his/her turn to shoot
digitalWrite(notB_PIN, (((((statevalue >> 13) & B00000111) < 1) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 4) ? LOW : HIGH) and (not(trafficvalue & 0x0800) ? HIGH : LOW))); //notB. Is on if Archer B exist but it is not his/her turn to shoot
digitalWrite(notC_PIN, (((((statevalue >> 13) & B00000111) < 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 4) ? LOW : HIGH) and (not(trafficvalue & 0x1000) ? HIGH : LOW))); //notC. Is on if Archer C exist but it is not his/her turn to shoot
digitalWrite(notD_PIN, (((((statevalue >> 13) & B00000111) < 3) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 4) ? LOW : HIGH) and (not(trafficvalue & 0x2000) ? HIGH : LOW))); //notD. Is on if Archer D exist but it is not his/her turn to shoot
// EF not implemented in this hardware
/*
digitalWrite(8, (((((statevalue >> 13) & B00000111) < 4) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 4) ? LOW : HIGH) and (not(trafficvalue & 0x4000) ? HIGH : LOW))); //notE. Is on if Archer E exist but it is not his/her turn to shoot
digitalWrite(9, (((((statevalue >> 13) & B00000111) < 5) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 2) ? LOW : HIGH) and ((((statevalue >> 7) & B00000111) == 4) ? LOW : HIGH) and (not(trafficvalue & 0x8000) ? HIGH : LOW))); //notF. Is on if Archer F exist but it is not his/her turn to shoot
*/
}
else
{
digitalWrite(notA_PIN, (blinkl));
digitalWrite(notB_PIN, (blinkl));
digitalWrite(notC_PIN, (blinkr));
digitalWrite(notD_PIN, (blinkr));
// EF not implemented in this hardware
/*
digitalWrite(8, (blinkl));
digitalWrite(9, (blinkl));
*/
};
// Set Traffic lights and digits, depending on side switch
if (digitalRead(LR_PIN)) // left side (default)
{
//Trafic lights:
digitalWrite(GREENP_PIN, (trafficvalue & 0x0080) ? HIGH : LOW); //green left side
digitalWrite(ORANGEP_PIN, (trafficvalue & 0x0100) ? HIGH : LOW); //orange left side
digitalWrite(REDP_PIN, (trafficvalue & 0x0200) ? HIGH : LOW); //red left side
rightdigit = ((leftcountvalue >> 4) & B00001111);
middigit = ((leftcountvalue >> 8) & B00001111);
leftdigit = ((leftcountvalue >> 12) & B00001111);
//digits dots
dots = ((leftcountvalue & 0x0008) ? HIGH : LOW) and ((segment[leftdigit] == 0x040) ? LOW : HIGH);
}
else //left side
{
//Trafic lights:
digitalWrite(GREENP_PIN, (trafficvalue & 0x0010) ? HIGH : LOW); //green right side
digitalWrite(ORANGEP_PIN, (trafficvalue & 0x0020) ? HIGH : LOW); //orange right side
digitalWrite(REDP_PIN, (trafficvalue & 0x0040) ? HIGH : LOW); //red right side
rightdigit = ((rightcountvalue >> 4) & B00001111);
middigit = ((rightcountvalue >> 8) & B00001111);
leftdigit = ((rightcountvalue >> 12) & B00001111);
//digits dots
dots = ((rightcountvalue & 0x0008) ? HIGH : LOW) and ((segment[leftdigit] == 0x040) ? LOW : HIGH);
};
// Apply selected segments
CATPORT(LEFTDIGIT_PORT) = segment[leftdigit] | (dots ? DOTS_bm : 0);
CATPORT(MIDDIGIT_PORT) = segment[middigit];
CATPORT(RIGHTDIGIT_PORT) = segment[rightdigit];
// This feature is not implemented in this hardware
/*
lefend = ((endnrvalue >> 4) & B00001111);
midend = ((endnrvalue >> 8) & B00001111);
rigend = ((endnrvalue >> 12) & B00001111);
if (lefend == 15)
{
comend = lefend;
}
else
{
comend = midend;
};
digitalWrite(24, ((segment[comend] & 0x001)) ? HIGH : LOW); //left combined end digit segment A
digitalWrite(26, ((segment[comend] & 0x002)) ? HIGH : LOW); //left combined end digit segment B
digitalWrite(28, ((segment[comend] & 0x004)) ? HIGH : LOW); //left combined end digit segment C
digitalWrite(30, ((segment[comend] & 0x008)) ? HIGH : LOW); //left combined end digit segment D
digitalWrite(32, ((segment[comend] & 0x010)) ? HIGH : LOW); //left combined end digit segment E
digitalWrite(34, ((segment[comend] & 0x020)) ? HIGH : LOW); //left combined end digit segment F
digitalWrite(36, ((segment[comend] & 0x040)) ? HIGH : LOW); //left combined end digit segment G
digitalWrite(40, ((segment[rigend] & 0x001)) ? HIGH : LOW); //right end digit segment A
digitalWrite(42, ((segment[rigend] & 0x002)) ? HIGH : LOW); //right end digit segment B
digitalWrite(44, ((segment[rigend] & 0x004)) ? HIGH : LOW); //right end digit segment C
digitalWrite(46, ((segment[rigend] & 0x008)) ? HIGH : LOW); //right end digit segment D
digitalWrite(48, ((segment[rigend] & 0x010)) ? HIGH : LOW); //right end digit segment E
digitalWrite(50, ((segment[rigend] & 0x020)) ? HIGH : LOW); //right end digit segment F
digitalWrite(52, ((segment[rigend] & 0x040)) ? HIGH : LOW); //right end digit segment G
*/
// This feature is not implemented in this hardware
/*
//Read buttons
buttonvalue = 0;
// if (digitalRead(A4)){buttonvalue=5;};
// if (digitalRead(A3)){buttonvalue=4;};
// if (digitalRead(A0)){buttonvalue=1;}; //next
// if (digitalRead(A1)){buttonvalue=2;};
// if (digitalRead(A2)){buttonvalue=3;};
if (loop1 == 0)
{
if (buttonvalue != remember1)
{
Serial.print(buttonvalue);
delay(3);
remember1 = buttonvalue;
loop1 = 15;
//digitalWrite(2, 1);
};
}
else
{
delay(10);
//if (loop1>7){blinkr=1;};
loop1--;
};
*/
}