Removed unused directory

This commit is contained in:
Fenoglio 2018-07-12 00:33:49 +02:00
parent af6a6920e9
commit 95be944080
4 changed files with 0 additions and 20190 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,95 +0,0 @@
/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978

View file

@ -1,103 +0,0 @@
#ifndef speedclock_H
#define speedclock_H
//-------------- defines for the radio devices NRF24 ---------------------------------------------------------
#define STATION_SEL0 9 // this 9 for Nano
#define STATION_SEL1 10 // this 10 for Nano
typedef enum {BASESTATION = 0, TOPSTATION} radio_type_e;
#define RF24_CNS 7 // this is 7 for the Nano, D4 for the ESP
#define RF24_CE 8 // this is 8 for the Nano, D3 for the ESP
#define RF24_PA_LEVEL RF24_PA_LOW // sending power level RF24_PA_LOW, ????
//--------------- defines for the I2C
//#define SCL A5 // I2C clock pin
//#define SDA A4 // I2C data pin
//--------------- define the structure and type of data that sender and receiver will exchange ----------------
typedef struct transcv_struct{
unsigned long topstationtime; // the top station sends its time (millis()) continously to the base station
unsigned long topbuttonpressedtime; // the top station sends the time in millis() when the button was pressed - this is already the calculated time
}transcv_s;
#define STOPBUTTON_IN 2 // this is the input for the button
#define STOPBUTTON_PRESSED LOW // this the signal level the top button will be at as soon as pressed
#define MIN_DELAY_BETWEEN_PRESSED_MS 1000 // this defines the time in milliseconds before the button is expected to be pressed again. We do this to avaoid keybouncing
#define MIN_DELAY_BETWEEN_SEND_MS 1000 // this defines the time in milliseconds before the next set of data will be send to the base station - except the button was pressed.
#define CONN_TIMEOUT 10000 // if there was no data received from the TOPSTATION for that amount of time - the connection is flagged as lost
#define STARTBUTTON_IN 4 // start button
#define STARTBUTTON_PRESSED LOW
#define CANCELBUTTON_IN 2 // chancle button
#define CANCELBUTTON_PRESSED LOW
#define FAILSTARTBUTTON_IN 3 // fail start button
#define FAILSTARTBUTTON_PRESSED LOW
#define PIEZO_PIN 6 // piezo speaker
#define WARN_LED A1 // yellow warn LED
#define WARN_LED_ON HIGH
#define WARN_LED_OFF LOW
#define FAIL_LED A3 // red fail LED
#define FAIL_LED_ON HIGH
#define FAIL_LED_OFF LOW
#define READY_LED A2 // green ready LED
#define READY_LED_ON HIGH
#define READY_LED_OFF LOW
#define RUN_LED A0 // blue run LED
#define RUN_LED_ON HIGH
#define RUN_LED_OFF LOW
#define DISPLAY_I2C_ADDRESS 0x3C //Adress of the Display
typedef enum {TIMER_INIT = 0, TIMER_NOCONNECTION, TIMER_IDLE, TIMER_READY, TIMER_STARTED, TIMER_RUNNING , TIMER_CANCELLED, TIMER_STOPPED, TIMER_TIMEDOUT, TIMER_FAIL, TIMER_WAIT} timer_state_e;
typedef enum {MODE_COMPETE = 0, MODE_TRAINING, MODE_CALIBRATION} timer_mode_e; // compete - full mode with false start detector, training - no false start detection, calibration - parellel wired connection between top and base to kalibrate the offset calculation of the wireless connection
// READY_LED, WARN_LED, RUN_LED, FAIL_LED
const float LEDStates[][3] =
{
[TIMER_INIT] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_OFF},
[TIMER_NOCONNECTION] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON},
[TIMER_IDLE] = {READY_LED_ON, RUN_LED_OFF, FAIL_LED_OFF},
[TIMER_READY] = {READY_LED_ON, RUN_LED_OFF, FAIL_LED_OFF},
[TIMER_STARTED] = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
[TIMER_RUNNING] = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_OFF},
[TIMER_CANCELLED] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON},
[TIMER_STOPPED] = {READY_LED_ON, RUN_LED_ON, FAIL_LED_OFF},
[TIMER_TIMEDOUT] = {READY_LED_OFF, RUN_LED_ON, FAIL_LED_ON},
[TIMER_FAIL] = {READY_LED_OFF, RUN_LED_OFF, FAIL_LED_ON}
};
#define MAX_DIFFERENCE_OFFSET_MS 100 // 0,001sec is the maximum offset we allow between the current offset and the mean offset. if it is more - restart offset calculation
#define REQUIRED_NUMBER_MEANVALS 100 // we need at least this number of meanvalues to be ready to start a run
#define MAX_ALLOWED_FAILED_OFFSETS 3 // if more than this number of offsets are out of the specified MAX_DIFFERENCE_OFFSET_MS value, offset calcultion will be restarted
#define STARTSEQ_LENGTH_MS 3100 // the length of the start sequence from the time the button was pressed ... includes the 3 tones
#define STARTSEQ_STARTPAUSE_MS 1000
#define STARTSEQ_TONEPAUSE_MS 1000
#define STARTSEQ_TON_1_2_LENGTH_MS 200
#define STARTSEQ_TON_1_2_FREQUENCY NOTE_G4
#define STARTSEQ_TON_3_LENGTH_MS 100
#define STARTSEQ_TON_3_FREQUENCY NOTE_C6
#define FAILSEQ_TONEPAUSE_MS 400
#define FAILSEQ_TON_LENGTH_MS 300
#define FAILSEQ_TON_FREQUENCY NOTE_G1
#define TIMER_MAX_TIME 99999
#define TIMER_TIMEOUT 20000
//--------------------------------------- function declarations ----------------------------------------------
void receive_values(void);
void false_start_isr(void);
void update_screen(timer_state_e state);
void set_state_LEDs(timer_state_e state, boolean warn);
void startSequence(void);
void update_statemessage(timer_state_e timer_state);
void failSequence(void);
void wait(unsigned long ms);
#endif

View file

@ -1,515 +0,0 @@
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include "RF24.h"
#include "speedclock.h"
#include "pitch.h"
// internal defines for the OLED display ...
SSD1306AsciiWire display;
/****************** User Config for NRF24***************************/
/*** Set this radio as radio number RADIO0 or RADIO1 ***/
radio_type_e stationNumber = BASESTATION; //---> TOPSTATION has the button connected, BASESTATION is the default ...
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(RF24_CNS,RF24_CE);
/**********************************************************/
byte addresses[][12] = {"top_station","basestation"}; // Radio pipe addresses for the 2 nodes to communicate.
uint8_t counter_time_offset = 0; // number of used values for the mean value calculation
signed long sum_time_offset = 0; // sum of offset values
signed long mean_time_offset = 0; // mean value for the offset
signed long current_time_offset = 0; // current offset ...
signed long running_time_offset = 0; // offset that will be used for this run ...
unsigned long start_time = 0; // if the timer is running this is that start time ...
unsigned long runner_start_time = 0; // this is the time the runner left the pad - so the status of the falsetstart pin goes to high again - but this is OK and a real start
unsigned long run_time = 0; // if the timer is running this is that start time ...
boolean warn_during_run = false; // will be set to true if there is a warning during the run - usually an offset sync error
unsigned long connection_last_established_at_ms = 0; // time the last active connection was established
boolean connection_available = false; // if there were no data for longer then CONN_TIMEOUT the connection will be flaged as lost ...
uint8_t failed_offsets = MAX_ALLOWED_FAILED_OFFSETS; // number of offset values that did not fullfill the MAX_DIFFERENCE_OFFSET_MS criterion
timer_state_e timer_state = TIMER_IDLE; // current state needs to be initialized to somethin different then new_state due to the fact that some pieces of the code check for differnt values of state and _new_state to detect an update...
timer_state_e timer_new_state = TIMER_NOCONNECTION; // next state - in the startup phase the first state - will be TIMER_NOCONNECTION ... checking if a connection to TOPSTATION is established
timer_mode_e timer_mode = MODE_COMPETE; // mode of the BASESTATION - this can be changed in IDLE state by pressing the CANCEL button
transcv_s radio_data;
void setup(){
Serial.begin(115200);
// this is the top button - will be pressed by the speed climber as soon she/he reaches the top ...
pinMode(STOPBUTTON_IN, INPUT_PULLUP);
pinMode(STARTBUTTON_IN, INPUT_PULLUP);
pinMode(CANCELBUTTON_IN, INPUT_PULLUP);
pinMode(FAILSTARTBUTTON_IN, INPUT_PULLUP);
pinMode(WARN_LED, OUTPUT);
pinMode(FAIL_LED, OUTPUT);
pinMode(READY_LED, OUTPUT);
// Setup and configure the NRF radio
// radio setup ...
radio.begin();
radio.setRetries(15, 15); //the first is the time between reties in multiple of 250ms, the second is the numer of attempts
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[1]);
radio.startListening();
radio_data.topstationtime = millis(); // set the current milli second count
radio_data.topbuttonpressedtime = 0; // set the time the button was pressed last time to 0
//initialise Wire and OLED
Wire.begin();
Wire.setClock(400000L);
display.begin(&Adafruit128x64, DISPLAY_I2C_ADDRESS);
display.clear();
}
void loop(void) {
/****************** Code for the TOPSTATION is here - the stop button is connected to the top station ***************************/
if ( stationNumber == BASESTATION ) {
// receive data from top_station, calculate offset and set 'last connection' time stamp
receive_values();
// update the OLED screen
update_screen(timer_new_state);
// set state to new_state
timer_state = timer_new_state;
// set LEDs
set_state_LEDs(timer_state, warn_during_run );
switch(timer_state){
case TIMER_NOCONNECTION:
// as long as there is no connection to TOP_STATION we will end up here
if(connection_available == true){
timer_new_state = TIMER_INIT;
}
case TIMER_INIT:
// init the system offset ...
if(connection_available == false){
// if the connection was lost ... switch to noconnection state
timer_new_state = TIMER_NOCONNECTION;
}
else{
// if the offset is claculated switch to IDLE mode ...
if(counter_time_offset > REQUIRED_NUMBER_MEANVALS){
// check if offset is OK - if not .. set state back to INIT
timer_new_state = TIMER_IDLE;
}
}
break;
case TIMER_IDLE:
warn_during_run = false;
if(connection_available == false){
// if the connection was lost ... switch to noconnection state
timer_new_state = TIMER_NOCONNECTION;
}
else{
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
// check if offset is OK - if not .. set state back to INIT
timer_new_state = TIMER_INIT;
}
else{
// check if the FALSESTATE button is pressed - somebody is ready to run ...
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
//wait a few milliseconds to prevent keybouncing - this is a very simplistic method here
delay(10);
//read again and check if still active ...
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
timer_new_state = TIMER_READY;
}
}
}
}
break;
case TIMER_READY:
if(connection_available == false){
// if the connection was lost ... switch to noconnection state
timer_new_state = TIMER_NOCONNECTION;
}
else{
if(digitalRead(FAILSTARTBUTTON_IN) == FAILSTARTBUTTON_PRESSED){
// check if the start button was pressed ... there is at least still someone waiting for the run .
if(digitalRead(STARTBUTTON_IN) == STARTBUTTON_PRESSED){
// now enable the interrupt for the FALSESTART button
attachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN), false_start_isr, CHANGE);
timer_new_state = TIMER_STARTED;
}
}
else{
timer_new_state = TIMER_IDLE;
}
}
break;
case TIMER_STARTED:
//initialize the start countdown
timer_new_state = TIMER_RUNNING;
startSequence();
break;
case TIMER_RUNNING:
noTone(PIEZO_PIN);
if(counter_time_offset < REQUIRED_NUMBER_MEANVALS){
// check if offset is still OK - if not .. set state to TIMER_RUNNING
warn_during_run = true;
}
if(millis() - start_time > TIMER_TIMEOUT){
timer_new_state = TIMER_TIMEDOUT;
}
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
timer_new_state = TIMER_CANCELLED;
}
Serial.println(radio_data.topbuttonpressedtime);
if(radio_data.topbuttonpressedtime > running_time_offset){
if((radio_data.topbuttonpressedtime - running_time_offset) > start_time){
run_time = (radio_data.topbuttonpressedtime - running_time_offset) - start_time;
timer_new_state = TIMER_STOPPED;
}
}
break;
case TIMER_STOPPED:
//calculate the run_time and switch to WAIT
delay(10);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT;
}
break;
case TIMER_FAIL:
//fail start case ....
failSequence();
run_time = 99999;
delay(10);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT;
}
break;
case TIMER_CANCELLED:
// what to do in chancel mode ?
run_time = 99999;
delay(10);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT;
}
break;
case TIMER_TIMEDOUT:
// time out
run_time = millis() - start_time;
delay(10);
if(digitalRead(CANCELBUTTON_IN) != CANCELBUTTON_PRESSED){
timer_new_state = TIMER_WAIT;
}
break;
case TIMER_WAIT:
// disable interrupt if not already done
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
// wait until the chancel button was pressed to go ahead
if(digitalRead(CANCELBUTTON_IN) == CANCELBUTTON_PRESSED){
timer_new_state = TIMER_IDLE;
}
break;
}
}
}
//####################### HELPER FUNCTIONS ###########################
void receive_values(void){
// check if radio data is available - if so read the data
if( radio.available()){
// read data from TOP_STATION ...
while( radio.available()){ // Read all available payloads
radio.read( &radio_data, sizeof(radio_data) ); // Read the data the TOPSTATION sent
}
connection_last_established_at_ms = millis();
connection_available = true;
current_time_offset = radio_data.topstationtime - millis(); // the offset between TOP_STATION and BASESTATION
Serial.print("Current time on host in millis:");
Serial.print(millis());
Serial.print(F(" Current time on client in millis: "));
Serial.println(radio_data.topstationtime);
Serial.print("Offset is: ");
Serial.println(current_time_offset);
Serial.print(F(" Button was pressed last time on client in millis: "));
Serial.println(radio_data.topbuttonpressedtime);
// offset calculation ... only needed if the variation is bigger than allowed or not enough values available already ...
if(counter_time_offset == 0){
// this is the initial setup to start with something - in this case the last offset value that was received
mean_time_offset = current_time_offset;
}
// check current offset of the TOP_STATIOn and the BASESTATION if more than allowed ...
if(abs(current_time_offset - mean_time_offset) < MAX_DIFFERENCE_OFFSET_MS){
// if the current value is in range - decrease the fail counter by 1 if it was not zero already
if(failed_offsets > 0){
Serial.println("INFO: The last received TOPSTATION offset time stamp was again in range. Decrease internal fail counter");
failed_offsets--;
}
// the offset is in range - check if we have already enough values of if we need to add more ...
if(counter_time_offset <= REQUIRED_NUMBER_MEANVALS){
//add the next value to meanvalue calculation ...
sum_time_offset = sum_time_offset + current_time_offset;
counter_time_offset++;
mean_time_offset = sum_time_offset/counter_time_offset;
Serial.print(F("Offset calulation. We have "));
Serial.print(counter_time_offset);
Serial.print(F("/"));
Serial.print(REQUIRED_NUMBER_MEANVALS);
Serial.print(F(" values. Mean offset value based on that is: "));
Serial.println(mean_time_offset);
}
} else {
// the current offset is out of range ...
// if the values before also already failed the criterion but the max allowed number of such fails is not reached ... just increase the counter.
if(failed_offsets < MAX_ALLOWED_FAILED_OFFSETS){
Serial.println("WARNING: The last received TOPSTATION offset time stamp was out of range. Increase internal fail counter");
failed_offsets++;
}
else{
// if the values before also already failed the criterion AND the max allowed number of such fails is reached ... we need to restart the mean calculation and set the timer to unready state ...
Serial.print(F("ERROR: TopStation and BaseStation are out off sync. Offset calculation will be restarted. Last "));
Serial.print(MAX_ALLOWED_FAILED_OFFSETS);
//offset "));
Serial.print(current_time_offset);
Serial.print("is to far from the mean offset ");
Serial.println( abs(current_time_offset - mean_time_offset) );
Serial.print(F(" is more than the allowed: "));
Serial.print(MAX_DIFFERENCE_OFFSET_MS);
Serial.print(F(" compared to the mean offset: "));
Serial.println(mean_time_offset);
counter_time_offset = 0;
sum_time_offset = 0;
mean_time_offset = 0;
failed_offsets = 0;
} // out of range counter exceeds maximum value
} // time offset of TOPSTATION out of range
}
else{
// remove the RF24 connection flag if no data was received for longer time
if(millis() - connection_last_established_at_ms >= CONN_TIMEOUT || connection_last_established_at_ms == 0){
connection_available = false;
Serial.println("ERROR: No connection established to TOPSTATION");
}
else{
Serial.println("No data from TOP_STATION avaialble - OR the connection couldn't be established");
}
} // radio available
}// receive values
void update_screen(timer_state_e state){
bool scr_update = true;
int ypos = 64-42/2;
String header = "no state";
String content = "";
String footer = "";
char header_to_char[50];
char content_to_char[50];
char footer_to_char[50];
float curr_time_local = 0.0;
switch(state){
case TIMER_NOCONNECTION:
header = "No connection";
content = "Waiting..";
footer = "Waiting for TOPSTATION";
break;
case TIMER_INIT:
header = "Init";
content = "...";
footer = "please wait";
break;
case TIMER_IDLE:
header = "Idle!";
content = "00.00 sec";
footer = "Waiting for climber";
break;
case TIMER_READY:
header = "Ready!";
content = "00.00 sec";
footer = "Waiting for start";
break;
case TIMER_STARTED:
header = "Starting ...";
content = "00.00 sec";
footer = "...";
break;
case TIMER_RUNNING:
header = "Running ...";
curr_time_local = (millis() - start_time)/1000.000;
content = curr_time_local;
content += " sec";
curr_time_local = (runner_start_time - start_time)/1000.000;
footer = "Reaction time: ";
footer += curr_time_local;
footer += " sec";
break;
case TIMER_CANCELLED:
header = "Cancelled!";
break;
case TIMER_STOPPED:
header = "Stopped!";
curr_time_local = run_time/1000.000;
content = curr_time_local;
content += " sec";
curr_time_local = (runner_start_time - start_time)/1000.000;
footer = "Reaction time: ";
footer += curr_time_local;
footer += " sec";
break;
case TIMER_TIMEDOUT:
header = "Timed out!";
content = "Invalid!";
break;
case TIMER_FAIL:
header = "False start!";
curr_time_local = (start_time - runner_start_time)/1000.000;
content = curr_time_local;
footer = "seconds too early";
break;
default:
scr_update = false;
break;
}
if(scr_update == true){
if(timer_new_state != timer_state){
display.clear(0,200,0,0);
display.clear(0,200,3,5);
display.clear(0,200,7,7);
}
//snprintf( string_to_char, sizeof(string_to_char),"%s", header);
header.toCharArray(header_to_char, sizeof(header_to_char));
content.toCharArray(content_to_char, sizeof(content_to_char));
footer.toCharArray(footer_to_char, sizeof(footer_to_char));
//Serial.print("DISPLAY: ");
//Serial.println(string_to_char);
display.setFont(System5x7);
display.set1X();
int xpos = (128 - (display.strWidth(header_to_char)))/2 - 10;
display.home();
display.setLetterSpacing(1);
display.setCursor(64 - (display.strWidth(header_to_char) / 2), 0);
display.print(header_to_char);
display.setCursor(1,0);
//check if there is a connection to the topstation
if(connection_available != true){
//if not remove the "Y"
display.print(" ");
}
else {
//if print the "Y"
display.print("Y");
}
display.setCursor(0,1);
display.setLetterSpacing(0);
display.print("----------------------------");
//end of the Header
//display.setLetterSpacing(1);
display.set2X();
display.setCursor(64 - (display.strWidth(content_to_char) / 2), 3);
display.print(content_to_char);
//end of the Content
display.set1X();
display.setCursor(0,6);
display.setLetterSpacing(0);
display.print("----------------------------");
display.setCursor(64 - (display.strWidth(footer_to_char) / 2), 7);
display.print(footer_to_char);
}
}
void set_state_LEDs(timer_state_e state, boolean warn){
// set the LEDS corresponding to the state of the timer ... as long as the system is not waiting for input ...
if(TIMER_WAIT != state){
digitalWrite(READY_LED, LEDStates[state][0]);
digitalWrite(RUN_LED, LEDStates[state][1]);
digitalWrite(FAIL_LED, LEDStates[state][2]);
if(warn == true){
digitalWrite(WARN_LED, WARN_LED_ON);
}
else
{
digitalWrite(WARN_LED, WARN_LED_OFF);
}
}
}
void startSequence(void){
// set the startime - this is the current time plus the length of this sequence
running_time_offset = mean_time_offset;
start_time = millis() + STARTSEQ_LENGTH_MS;
Serial.print("Start time is: ");
Serial.println(start_time);
// this is sequence of usually three tones after a wait time 1sec , in between the tones there is also a delay of 1 sec. Each tone is 200ms seconds long, except the last
if(timer_new_state == TIMER_RUNNING){
wait(STARTSEQ_STARTPAUSE_MS);
}
// first tone
if(timer_new_state == TIMER_RUNNING){
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
wait(STARTSEQ_TONEPAUSE_MS);
}
//second tone
if(timer_new_state == TIMER_RUNNING){
tone(PIEZO_PIN, STARTSEQ_TON_1_2_FREQUENCY,STARTSEQ_TON_1_2_LENGTH_MS );
wait(STARTSEQ_TONEPAUSE_MS);
}
//third tone
if(timer_new_state == TIMER_RUNNING){
tone(PIEZO_PIN, STARTSEQ_TON_3_FREQUENCY,STARTSEQ_TON_3_LENGTH_MS );
wait(STARTSEQ_TON_3_LENGTH_MS);
}
}
void failSequence(void){
// first tone
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
delay(FAILSEQ_TONEPAUSE_MS);
//second tone
tone(PIEZO_PIN, FAILSEQ_TON_FREQUENCY,FAILSEQ_TON_LENGTH_MS );
delay(FAILSEQ_TONEPAUSE_MS);
noTone(PIEZO_PIN);
}
void false_start_isr(void){
// this is the interrupt routine for the FALSESTART button
// this will save the time when the runner is really started
Serial.println("** Interrupt service routine started: false_start_ISR **");
runner_start_time = millis();
if((timer_state == TIMER_STARTED) & (timer_new_state == TIMER_RUNNING)){
timer_new_state = TIMER_FAIL;
noTone(PIEZO_PIN);
Serial.println("** Interrupt service routine detected false_start. Set new state to TIMER_FAIL **");
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
} else {
if((timer_state == TIMER_RUNNING) | (timer_new_state == TIMER_RUNNING) ){
// disable this interrupt;
detachInterrupt(digitalPinToInterrupt(FAILSTARTBUTTON_IN));
}
}
}
void wait(unsigned long ms){
unsigned long current = 0;
unsigned long started = millis();
do{
current = millis()-started;
}while(current < ms);
}