2015-01-15 23:57:55 +00:00
//Copyright (C) 2010-2014 Henk Jegers
2019-01-10 14:55:21 +00:00
//Copyright (C) 2019 giuliof (GOLEM)
2015-01-15 23:57:55 +00:00
//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/>.
2018-12-17 21:00:23 +00:00
//for questions email to info@archeryclock.com
2015-01-15 23:57:55 +00:00
// 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)
2018-12-17 21:00:23 +00:00
// 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)
2015-01-15 23:57:55 +00:00
2019-01-10 14:55:21 +00:00
# include "utils.h"
2015-01-15 23:57:55 +00:00
2019-01-11 13:04:26 +00:00
// Commands data structures
2018-12-18 18:21:54 +00:00
enum PanelSide_t
{
LEFT = 0 ,
RIGHT = 1
} ;
enum BuzzerStatus_t
{
BUZZER_OFF ,
BUZZER_ON
} ;
struct cfg_t
{
PanelSide_t PanelSide : 1 ;
BuzzerStatus_t BuzzerStatus : 1 ;
2019-01-11 13:04:26 +00:00
uint8_t abcd : 3 ; // unclear meaning
2018-12-18 18:21:54 +00:00
uint8_t competition : 3 ; // unclear meaning
uint8_t GroupsNumber : 6 ;
2018-12-18 17:05:00 +00:00
uint8_t : 0 ;
} cfg ;
2018-12-18 18:21:54 +00:00
struct trafficvalue_t
{
2019-02-22 15:28:08 +00:00
uint8_t cmd : 3 ; // < 0b111
2018-12-18 18:21:54 +00:00
BuzzerStatus_t buzzer : 1 ;
uint8_t TrafficLightLeft : 3 ;
uint8_t TrafficLightRight : 3 ;
uint8_t ArcherGroups : 6 ;
//uint8_t : 0;
} ;
struct statevalue_t
{
2019-02-22 15:28:08 +00:00
uint8_t cmd : 4 ; // = 0b1111
2019-01-11 13:04:26 +00:00
uint8_t abcd : 3 ; // unclear meaning
2018-12-18 18:21:54 +00:00
uint8_t competition : 3 ; // unclear meaning
uint8_t : 3 ;
uint8_t GroupsNumber : 6 ;
//uint8_t : 0;
} ;
struct digitsvalue_t
{
uint8_t cmd : 1 ;
PanelSide_t side : 1 ;
uint8_t sideOverride : 1 ;
uint8_t minutes : 1 ;
uint8_t rDigit : 4 ;
uint8_t mDigit : 4 ;
uint8_t lDigit : 4 ;
} ;
union ReceivedCommand_t {
int raw ;
trafficvalue_t t ;
statevalue_t s ;
digitsvalue_t d ;
} ReceivedCommand ;
2019-01-10 14:55:21 +00:00
# define DOTS_bm _BV(7)
2019-02-22 15:28:08 +00:00
# define DOTS_PIN 23
2019-01-10 14:55:21 +00:00
2019-01-11 13:04:26 +00:00
# define ABCD_PORT A
# define LEFTDIGIT_PORT K
# define MIDDIGIT_PORT L
2019-01-10 14:55:21 +00:00
# define RIGHTDIGIT_PORT C
2019-01-11 13:04:26 +00:00
# define TRAFLIGHT_PORT F
2015-01-15 23:57:55 +00:00
2019-01-10 14:55:21 +00:00
# define HORNP_PIN 7
# define REDP_PIN 6
# define ORANGEP_PIN 5
# define GREENP_PIN 4
2018-12-17 21:00:23 +00:00
2019-02-22 15:28:08 +00:00
//#define notA_PIN 78
//#define notB_PIN 77
//#define notC_PIN 76
//#define notD_PIN 75
# define A_PIN 22
# define B_PIN 24
# define C_PIN 26
# define D_PIN 27
# define AC_PIN 25
# define BD_PIN 28
2019-01-10 14:55:21 +00:00
2019-02-08 22:17:11 +00:00
# define LR_PIN 10
# define MUTE_PIN 9
# define BRIGHT_PIN 8
2019-01-10 14:55:21 +00:00
2019-01-11 13:04:26 +00:00
// "translation" for seven segment
# define CHAR_P 15
# define CHAR_DASH 10
2019-02-22 15:28:08 +00:00
//const uint8_t segment[16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40, 0x00, 0x3f, 0x00, 0x00, 0x73}; //0,1,2,3,4,5,6,7,8,9,-, , , , ,P
const uint8_t segment [ 16 ] = { 0xbe , 0x82 , 0x6e , 0xea , 0xd2 , 0xf8 , 0xfc , 0x8a , 0xfe , 0xfa , 0x40 , 0x0 , 0xbe , 0x0 , 0x0 , 0x5e } ; //0,1,2,3,4,5,6,7,8,9,-, , , , ,P
2015-01-15 23:57:55 +00:00
2019-02-08 22:17:11 +00:00
boolean dataAvailable ( char & digit ) {
if ( Serial1 . available ( ) )
{
digit = Serial1 . read ( ) ; // Read serial buffer
return 1 ;
}
else if ( Serial . available ( ) )
{
digit = Serial . read ( ) ; // Read serial buffer
return 1 ;
}
return 0 ;
}
2018-12-17 21:00:23 +00:00
void setup ( )
{
2019-01-11 13:04:26 +00:00
pinMode ( LR_PIN , INPUT_PULLUP ) ;
2019-01-10 14:55:21 +00:00
pinMode ( MUTE_PIN , INPUT_PULLUP ) ;
2019-02-08 22:17:11 +00:00
pinMode ( BRIGHT_PIN , INPUT_PULLUP ) ;
2015-01-15 23:57:55 +00:00
2019-01-11 13:04:26 +00:00
CATDDR ( ABCD_PORT ) = 0xFF ;
CATDDR ( LEFTDIGIT_PORT ) = 0xFF ;
CATDDR ( MIDDIGIT_PORT ) = 0xFF ;
2019-01-10 14:55:21 +00:00
CATDDR ( RIGHTDIGIT_PORT ) = 0xFF ;
2019-01-11 13:04:26 +00:00
CATDDR ( TRAFLIGHT_PORT ) = 0xFF ;
2015-01-15 23:57:55 +00:00
2019-01-11 13:04:26 +00:00
pinMode ( REDP_PIN , OUTPUT ) ;
2019-01-10 14:55:21 +00:00
pinMode ( ORANGEP_PIN , OUTPUT ) ;
2019-01-11 13:04:26 +00:00
pinMode ( GREENP_PIN , OUTPUT ) ;
2019-01-10 14:55:21 +00:00
pinMode ( HORNP_PIN , OUTPUT ) ;
2015-01-15 23:57:55 +00:00
2018-12-18 17:05:00 +00:00
// Load system configuration
2019-01-11 13:10:18 +00:00
cfg . BuzzerStatus = digitalRead ( MUTE_PIN ) ? BUZZER_ON : BUZZER_OFF ;
2019-02-08 22:17:11 +00:00
cfg . PanelSide = digitalRead ( LR_PIN ) ? LEFT : RIGHT ;
2018-12-18 17:05:00 +00:00
2018-12-18 19:26:10 +00:00
// Communication w/PC for debug or other puroposes
2015-01-15 23:57:55 +00:00
Serial . begin ( 9600 ) ;
Serial . println ( " Arduino Serial Link " ) ;
2018-12-17 21:00:23 +00:00
Serial . println ( " connected! " ) ;
2018-12-18 19:26:10 +00:00
// Communication w/XBEE
Serial1 . begin ( 9600 ) ;
2015-01-15 23:57:55 +00:00
}
2018-12-17 21:00:23 +00:00
void loop ( )
{
2019-01-10 14:55:21 +00:00
// A command is received
2019-02-08 22:17:11 +00:00
char digit ;
if ( dataAvailable ( digit ) )
2018-12-17 21:00:23 +00:00
{
2018-12-18 16:45:19 +00:00
/* ** Buffer to store received char **
* Data is an integer string terminated with newline ' \n '
* */
static String inputString = " " ;
// Check if string terminator
2019-02-22 14:01:51 +00:00
if ( digit = = ' \r ' )
2018-12-17 21:00:23 +00:00
{
2018-12-18 16:45:19 +00:00
// Make string conversion
2018-12-18 18:21:54 +00:00
ReceivedCommand . raw = inputString . toInt ( ) ;
2018-12-18 16:45:19 +00:00
inputString = " " ;
2018-12-17 21:00:23 +00:00
2019-01-11 13:04:26 +00:00
// Now decode command and apply to the panel
// Refer to documentation for command structure
2018-12-17 21:00:23 +00:00
2018-12-18 18:21:54 +00:00
// Parsing of DIGITS command
if ( ReceivedCommand . d . cmd = = 0 b0 )
2018-12-18 16:45:19 +00:00
{
2018-12-18 18:21:54 +00:00
// Parse command only if is same side as this panel (or comamnd says to override)
2019-02-22 11:35:16 +00:00
if ( ReceivedCommand . d . sideOverride | | ( ReceivedCommand . d . side = = cfg . PanelSide ) )
2018-12-18 18:21:54 +00:00
{
2019-01-11 13:04:26 +00:00
CATPORT ( MIDDIGIT_PORT ) = segment [ ReceivedCommand . d . mDigit ] ;
CATPORT ( RIGHTDIGIT_PORT ) = segment [ ReceivedCommand . d . rDigit ] ;
// Turn on dot between minutes and seconds only if count is in minutes and its digit is a representable value (not dash)
2019-02-22 15:28:08 +00:00
CATPORT ( LEFTDIGIT_PORT ) = segment [ ReceivedCommand . d . lDigit ] ;
2019-01-11 13:04:26 +00:00
if ( ReceivedCommand . d . lDigit ! = CHAR_DASH & & ReceivedCommand . d . minutes )
2019-02-22 15:28:08 +00:00
digitalWrite ( DOTS_PIN , HIGH ) ;
2019-01-11 13:04:26 +00:00
else
2019-02-22 15:28:08 +00:00
digitalWrite ( DOTS_PIN , LOW ) ;
2018-12-18 18:21:54 +00:00
}
}
// Parsing of TRAFFIC command
2019-02-22 15:28:26 +00:00
else if ( ReceivedCommand . t . cmd = = 0 b001 )
2018-12-18 16:45:19 +00:00
{
2019-01-11 13:04:26 +00:00
// Set buzzer depending on mute switch
2018-12-18 18:21:54 +00:00
if ( cfg . BuzzerStatus = = BUZZER_ON )
{
2019-01-11 13:04:26 +00:00
digitalWrite ( HORNP_PIN , ReceivedCommand . t . buzzer ) ;
2018-12-18 18:21:54 +00:00
}
2019-01-11 13:04:26 +00:00
// Set Traffic lights depending on side switch
2018-12-18 18:21:54 +00:00
if ( cfg . PanelSide = = RIGHT )
2019-01-11 13:04:26 +00:00
{
2019-02-22 15:28:08 +00:00
digitalWrite ( GREENP_PIN , ReceivedCommand . t . TrafficLightRight & _BV ( 0 ) ) ; // green right side
digitalWrite ( ORANGEP_PIN , ReceivedCommand . t . TrafficLightRight & _BV ( 1 ) ) ; // orange right side
digitalWrite ( REDP_PIN , ReceivedCommand . t . TrafficLightRight & _BV ( 2 ) ) ; // red right side
CATPORT ( TRAFLIGHT_PORT ) = ( ReceivedCommand . t . TrafficLightRight & _BV ( 0 ) ? 0 b11 < < 6 : 0 ) |
( ReceivedCommand . t . TrafficLightRight & _BV ( 1 ) ? 0 b1001 < < 2 : 0 ) |
( ReceivedCommand . t . TrafficLightRight & _BV ( 2 ) ? 0 b11 < < 3 : 0 ) ;
2019-01-11 13:04:26 +00:00
}
2018-12-18 18:21:54 +00:00
else
2019-01-11 13:04:26 +00:00
{
2019-02-22 15:28:08 +00:00
digitalWrite ( GREENP_PIN , ReceivedCommand . t . TrafficLightLeft & _BV ( 0 ) ) ; // green left side
digitalWrite ( ORANGEP_PIN , ReceivedCommand . t . TrafficLightLeft & _BV ( 1 ) ) ; // orange left side
digitalWrite ( REDP_PIN , ReceivedCommand . t . TrafficLightLeft & _BV ( 2 ) ) ; // red left side
CATPORT ( TRAFLIGHT_PORT ) = ( ReceivedCommand . t . TrafficLightLeft & _BV ( 0 ) ? 0 b11 < < 6 : 0 ) |
( ReceivedCommand . t . TrafficLightLeft & _BV ( 1 ) ? 0 b1001 < < 2 : 0 ) |
( ReceivedCommand . t . TrafficLightLeft & _BV ( 2 ) ? 0 b11 < < 3 : 0 ) ;
2019-01-11 13:04:26 +00:00
}
2018-12-18 18:21:54 +00:00
2019-01-11 13:04:26 +00:00
// Set ABCD(EF)
2019-02-22 15:28:08 +00:00
digitalWrite ( A_PIN , ReceivedCommand . t . ArcherGroups & _BV ( 0 ) ) ; //A
digitalWrite ( B_PIN , ReceivedCommand . t . ArcherGroups & _BV ( 1 ) ) ; //B
digitalWrite ( C_PIN , ReceivedCommand . t . ArcherGroups & _BV ( 2 ) ) ; //C
digitalWrite ( D_PIN , ReceivedCommand . t . ArcherGroups & _BV ( 3 ) ) ; //D
digitalWrite ( AC_PIN , ReceivedCommand . t . ArcherGroups & ( _BV ( 0 ) | _BV ( 2 ) ) ) ; //AC
digitalWrite ( BD_PIN , ReceivedCommand . t . ArcherGroups & ( _BV ( 1 ) | _BV ( 3 ) ) ) ; //BD
2019-01-11 13:04:26 +00:00
// EF not implemented in this hardware
2018-12-18 18:21:54 +00:00
/*
digitalWrite ( 6 , ( ( ( statevalue > > 7 ) & B00000111 ) ! = 2 ) and ( trafficvalue & 0x4000 ) ) ; //E
digitalWrite ( 7 , ( ( ( statevalue > > 7 ) & B00000111 ) ! = 2 ) and ( trafficvalue & 0x8000 ) ) ; //F
digitalWrite ( A15 , ( ( ( statevalue > > 7 ) & B00000111 ) = = 2 ) and ( trafficvalue & 0x4000 ) ) ; //green right arrow for fita finals
digitalWrite ( 39 , ( ( ( statevalue > > 7 ) & B00000111 ) = = 2 ) and ( trafficvalue & 0x8000 ) ) ; //green left arrow for fita finals
*/
2019-01-10 14:55:21 +00:00
2019-01-11 13:04:26 +00:00
// Set not{A,B,C,D,(E,F)}
2019-02-22 15:28:08 +00:00
/*if (cfg.abcd != 6)
2019-01-11 13:04:26 +00:00
{
uint8_t notABCD_on = 0 ;
// not A is on if archer group A is not selected
digitalWrite ( notA_PIN , cfg . GroupsNumber > 1 & & ! ( ReceivedCommand . t . ArcherGroups & _BV ( 0 ) ) ) ;
2019-01-10 14:55:21 +00:00
2019-01-11 13:04:26 +00:00
// not B ~ not D are on if groups are effectively present and are not selected
if ( cfg . competition ! = 2 & & cfg . competition ! = 4 )
{
digitalWrite ( notA_PIN , cfg . GroupsNumber > 1 & & ! ( ReceivedCommand . t . ArcherGroups & _BV ( 1 ) ) ) ;
digitalWrite ( notA_PIN , cfg . GroupsNumber > 2 & & ! ( ReceivedCommand . t . ArcherGroups & _BV ( 2 ) ) ) ;
digitalWrite ( notA_PIN , cfg . GroupsNumber > 3 & & ! ( ReceivedCommand . t . ArcherGroups & _BV ( 3 ) ) ) ;
}
else
{
digitalWrite ( notB_PIN , LOW ) ;
digitalWrite ( notC_PIN , LOW ) ;
digitalWrite ( notD_PIN , LOW ) ;
}
}
else
{
digitalWrite ( notA_PIN , HIGH ) ;
digitalWrite ( notB_PIN , HIGH ) ;
digitalWrite ( notC_PIN , HIGH ) ;
digitalWrite ( notD_PIN , HIGH ) ;
2019-02-22 15:28:08 +00:00
} */
2018-12-18 18:21:54 +00:00
}
// Parsing of STATE command
else if ( ReceivedCommand . s . cmd = = 0 b1111 )
2018-12-18 16:45:19 +00:00
{
2018-12-18 18:21:54 +00:00
cfg . abcd = ReceivedCommand . s . abcd ;
cfg . competition = ReceivedCommand . s . competition ;
cfg . GroupsNumber = ReceivedCommand . s . GroupsNumber ;
}
2018-12-18 16:45:19 +00:00
}
2018-12-18 18:21:54 +00:00
else // if (char) digit != '\n'
2018-12-17 21:00:23 +00:00
{
2018-12-18 16:45:19 +00:00
inputString + = digit ;
}
}
2015-01-15 23:57:55 +00:00
2019-01-10 14:55:21 +00:00
// This feature is not implemented in this hardware
/*
2018-12-17 21:00:23 +00:00
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
2019-01-10 14:55:21 +00:00
*/
2018-12-17 21:00:23 +00:00
2019-01-10 14:55:21 +00:00
// This feature is not implemented in this hardware
/*
2018-12-17 21:00:23 +00:00
//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 )
{
2015-01-15 23:57:55 +00:00
Serial . print ( buttonvalue ) ;
delay ( 3 ) ;
2018-12-17 21:00:23 +00:00
remember1 = buttonvalue ;
loop1 = 15 ;
2015-01-15 23:57:55 +00:00
//digitalWrite(2, 1);
} ;
2018-12-17 21:00:23 +00:00
}
else
{
delay ( 10 ) ;
//if (loop1>7){blinkr=1;};
2015-01-15 23:57:55 +00:00
loop1 - - ;
} ;
2018-12-18 18:21:54 +00:00
*/
2015-01-15 23:57:55 +00:00
}