new M,n commands - start integration of Network mode
This commit is contained in:
parent
65f9f15f51
commit
88755ac355
13 changed files with 398 additions and 105 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
00_note_sviluppo.txt
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
|
@ -5,3 +6,4 @@
|
|||
.vscode/ipch
|
||||
|
||||
\.vscode/
|
||||
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
Revisions history
|
||||
-----------------
|
||||
|
||||
* 2023-07-20: Ver 0.9.8 - Luca - Branch: "lab"
|
||||
- Added "Demo" mode:
|
||||
- When Board has [demo_mode=ON] in the EEPROM configuration,
|
||||
it plays a "Simulated" race where cars run without any real player.
|
||||
Useful to test the code and to get people attention in Fairs, etc
|
||||
On user activity (somebody uses the controllers) the boards jumps
|
||||
back automatically to demo=off mode (Users play races via Controllers)
|
||||
- Start implementing Relay Race funcionality
|
||||
|
||||
|
||||
* 2023-07-10: Ver 0.9.7 - Lab ---> Master
|
||||
- Branch Lab merged to Master
|
||||
|
||||
* 2021-11-20: Ver 0.9.7 - Luca - Branch: "lab"
|
||||
...............................................
|
||||
- Changed Version Number to 0.9.7
|
||||
- ready to merge with master branch
|
||||
- ver 0.9.7 managed by companion desktopApp
|
||||
|
|
Binary file not shown.
BIN
doc/OLR_Protocol_Serial.pdf
Normal file
BIN
doc/OLR_Protocol_Serial.pdf
Normal file
Binary file not shown.
BIN
doc/docSrc/OLR_Protocol_Serial.odt
Normal file
BIN
doc/docSrc/OLR_Protocol_Serial.odt
Normal file
Binary file not shown.
|
@ -48,7 +48,7 @@ int SerialCommand::checkSerial() {
|
|||
}
|
||||
} else {
|
||||
// buffer full
|
||||
// re4set and retunn error
|
||||
// reset and retunn error
|
||||
_buf[_bufIdx++] = '\0';
|
||||
_bufIdx=0;
|
||||
return(-2);
|
||||
|
|
|
@ -4,21 +4,31 @@ enum {
|
|||
DELTA_ANALOG = 5,
|
||||
};
|
||||
|
||||
int DIGITAL_CTRL[4];
|
||||
|
||||
static float const ACEL = 0.2;
|
||||
|
||||
void controller_setup( void ) {
|
||||
|
||||
|
||||
/***
|
||||
if( DIGITAL_MODE == false ){
|
||||
pinMode(PIN_VCC_ADC1, OUTPUT);
|
||||
pinMode(PIN_VCC_ADC2, OUTPUT);
|
||||
digitalWrite(PIN_VCC_ADC1, HIGH);
|
||||
digitalWrite(PIN_VCC_ADC2, HIGH);
|
||||
}
|
||||
|
||||
pinMode( DIG_CONTROL_1, INPUT_PULLUP); //pull up in adc
|
||||
pinMode( DIG_CONTROL_2, INPUT_PULLUP);
|
||||
pinMode( DIG_CONTROL_3, INPUT_PULLUP);
|
||||
pinMode( DIG_CONTROL_4, INPUT_PULLUP);
|
||||
***/
|
||||
|
||||
DIGITAL_CTRL[CTRL_1]= DIG_CTRL_1_PIN;
|
||||
DIGITAL_CTRL[CTRL_2]= DIG_CTRL_2_PIN;
|
||||
DIGITAL_CTRL[CTRL_3]= DIG_CTRL_3_PIN;
|
||||
DIGITAL_CTRL[CTRL_4]= DIG_CTRL_4_PIN;
|
||||
|
||||
|
||||
pinMode( DIG_CTRL_1_PIN, INPUT_PULLUP); //pull up in adc
|
||||
pinMode( DIG_CTRL_2_PIN, INPUT_PULLUP);
|
||||
pinMode( DIG_CTRL_3_PIN, INPUT_PULLUP);
|
||||
pinMode( DIG_CTRL_4_PIN, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
void controller_init( controller_t* ct, enum ctr_type mode, int pin ) {
|
||||
|
@ -41,9 +51,9 @@ byte controller_getStatus( controller_t* ct ) {
|
|||
}
|
||||
ct->badc = ct->adc;
|
||||
}
|
||||
else if( ct->mode == DEBUG_MODE ){
|
||||
else if( ct->mode == DEMO_MODE ){
|
||||
ct->adc++;
|
||||
if( ct->adc >= 60){
|
||||
if( ct->adc >= 15){
|
||||
ct->adc = 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -10,20 +10,34 @@ extern "C"{
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern int DIGITAL_CTRL[]; // Global Array containig PINs used for the Digital Controllers (ex: Push Buttons)
|
||||
|
||||
|
||||
#define DIG_CTRL_1_PIN A2 // switch player 1 to PIN and GND
|
||||
#define DIG_CTRL_2_PIN A0 // switch player 2 to PIN and GND
|
||||
#define DIG_CTRL_3_PIN A3 // switch player 3 to PIN and GND
|
||||
#define DIG_CTRL_4_PIN A1 // switch player 4 to PIN and GND
|
||||
|
||||
|
||||
|
||||
enum ctr_idx { // Used to access controller by "name" (and not via zero-offset index)
|
||||
CTRL_1 = 0, // Ex: DIGITAL_CTRL[CTRL_2]
|
||||
CTRL_2 ,
|
||||
CTRL_3 ,
|
||||
CTRL_4
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define DIG_CONTROL_1 A2 // switch player 1 to PIN and GND
|
||||
#define DIG_CONTROL_2 A0 // switch player 2 to PIN and GND
|
||||
#define DIG_CONTROL_3 A3 // switch player 3 to PIN and GND
|
||||
#define DIG_CONTROL_4 A1 // switch player 4 to PIN and GND
|
||||
|
||||
#define PIN_VCC_ADC1 6
|
||||
#define PIN_VCC_ADC2 7
|
||||
|
||||
enum ctr_type{
|
||||
enum ctr_type {
|
||||
NOT_DEFINED = 0,
|
||||
DIGITAL_MODE,
|
||||
ANALOG_MODE,
|
||||
DEBUG_MODE,
|
||||
DEMO_MODE,
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
|
|
|
@ -124,7 +124,7 @@ bool ramp_isactive( track_t* tck ) {
|
|||
}
|
||||
|
||||
|
||||
void car_resetPosition( car_t* car) {
|
||||
void car_resetPosition( car_t* car, bool reset_speed) {
|
||||
|
||||
car->trackID = TRACK_MAIN;
|
||||
car->speed = 0;
|
||||
|
@ -135,6 +135,12 @@ void car_resetPosition( car_t* car) {
|
|||
car->battery = 100;
|
||||
}
|
||||
|
||||
void car_setSpeed( car_t* car, float speed) {
|
||||
car->speed = speed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void box_init( track_t* tck ) {
|
||||
tck->boxactive = true;
|
||||
}
|
||||
|
@ -152,14 +158,18 @@ int tracklen_configure( track_t* tck, int nled ) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int autostart_configure( track_t* tck, int autostart ) {
|
||||
int autostart_configure( track_t* tck, uint8_t autostart ) {
|
||||
param_option_set(&tck->cfg, AUTOSTART_MODE_OPTION, (boolean) autostart);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int demo_configure( track_t* tck, uint8_t demo ) {
|
||||
param_option_set(&tck->cfg, DEMO_MODE_OPTION, (boolean) demo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int players_n_configure( track_t* tck, int val ) {
|
||||
int players_n_configure( track_t* tck, uint8_t val ) {
|
||||
switch(val){
|
||||
case 2 :
|
||||
param_option_set(&tck->cfg, PLAYER_3_OPTION, false);
|
||||
|
|
|
@ -75,7 +75,7 @@ void car_init( car_t* car, controller_t* ct, uint32_t color );
|
|||
|
||||
void car_updateController( car_t* car );
|
||||
|
||||
void car_resetPosition( car_t* car);
|
||||
void car_resetPosition( car_t* car, bool reset_speed);
|
||||
|
||||
void update_track( track_t* tck, car_t* car );
|
||||
|
||||
|
@ -89,9 +89,11 @@ bool box_isactive( track_t* tck );
|
|||
|
||||
int tracklen_configure( track_t* tck, int nled );
|
||||
|
||||
int autostart_configure( track_t* tck, int autostart );
|
||||
int autostart_configure( track_t* tck, uint8_t autostart );
|
||||
|
||||
int players_n_configure( track_t* tck, int val );
|
||||
int demo_configure( track_t* tck, uint8_t demo ) ;
|
||||
|
||||
int players_n_configure( track_t* tck, uint8_t val );
|
||||
|
||||
int boxlen_configure( track_t* tck, int box_len, int boxalwaysOn );
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ void param_setdefault( struct cfgparam* cfg ) {
|
|||
|
||||
param_option_set(cfg, PLAYER_3_OPTION, PLAYER_3);
|
||||
param_option_set(cfg, PLAYER_4_OPTION, PLAYER_4);
|
||||
param_option_set(cfg, DEMO_MODE_OPTION, DEMO_MODE_ST);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ extern "C"{
|
|||
#define SLOPE_ALWAYS_ON false
|
||||
#define PLAYER_3 false
|
||||
#define PLAYER_4 false
|
||||
#define DEMO_MODE_ST false
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -33,14 +34,14 @@ enum cfgparam_option_bit {
|
|||
SLOPE_MODE_OPTION = 3,
|
||||
PLAYER_3_OPTION = 4,
|
||||
PLAYER_4_OPTION = 5,
|
||||
NOT_USED_3_OPTION = 6,
|
||||
NOT_USED_4_OPTION = 7,
|
||||
DEMO_MODE_OPTION = 6,
|
||||
NOT_USED_7_OPTION = 7,
|
||||
};
|
||||
|
||||
enum cfgpar {
|
||||
CFGPARAM_VER = 6, // Change this value (+=1) every time the [cfgparam] struct is modified
|
||||
CFGPARAM_VER = 7, // Change this value (+=1) every time the [cfgparam] struct is modified
|
||||
// This will force an update with the new [struct] to the settings
|
||||
// stored in EEPROM with an old (invalid) struct
|
||||
// stored in EEPROM with an old (invalid) struct
|
||||
LEN_UID = 16,
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
| | | |_ __ ___ _ __ | | | |__ | | | | | |__) |__ _ ___ ___
|
||||
| | | | '_ \ / _ \ '_ \ | | | __| | | | | | _ // _` |/ __/ _ \
|
||||
| |__| | |_) | __/ | | | | |____| |____| |__| | | | \ \ (_| | (_| __/
|
||||
\____/| .__/ \___|_| |_| |______|______|_____/ |_| \_\__,_|\___\___|
|
||||
\____/| .__/ \___|_| |_| |______|______|_____/ |_| \_\__,_file:///home/buka/Desktop/OpenLedRace/Code/olr-arduino/Current/open-led-race|\___\___|
|
||||
| |
|
||||
|_|
|
||||
Open LED Race
|
||||
|
@ -16,6 +16,9 @@
|
|||
(at your option) any later version.
|
||||
|
||||
|
||||
Current Version by:
|
||||
LucaBuka (https://gitlab.com/lucabuka)
|
||||
|
||||
First public version by:
|
||||
Angel Maldonado (https://gitlab.com/angeljmc)
|
||||
Gerardo Barbarov (gbarbarov AT singulardevices DOT com)
|
||||
|
@ -30,12 +33,9 @@
|
|||
|
||||
*/
|
||||
|
||||
|
||||
// 2021/07/20 - Ver 0.9.6 - lab branch
|
||||
// --see changelog.txt
|
||||
|
||||
char const softwareId[] = "A4P0"; // A4P -> A = Open LED Race, 4P0 = Game ID (4P = 4 Players, 0=Type 0)
|
||||
char const version[] = "0.9.7";
|
||||
char const version[] = "0.9.8";
|
||||
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
@ -45,7 +45,7 @@ char const version[] = "0.9.7";
|
|||
#include "SoftTimer.h"
|
||||
#include "SerialCommand.h"
|
||||
|
||||
#define PIN_LED 2 // R 500 ohms to DI pin for WS2812 and WS2813, for WS2813 BI pin of first LED to GND , CAP 1000 uF to VCC 5v/GND,power supplie 5V 2A
|
||||
#define PIN_LED 2 // R 500 ohms to DI pin for WS2812 and WS2813, for WS2813 BI pin of first LED to GND , CAP 1000 uF to VCC 5v/GND,power supply 5V 2A
|
||||
#define PIN_AUDIO 3 // through CAP 2uf to speaker 8 ohms
|
||||
|
||||
#define REC_COMMAND_BUFLEN 32 // received command buffer size
|
||||
|
@ -76,6 +76,9 @@ char const version[] = "0.9.7";
|
|||
|
||||
#define NEWRACE_DELAY 5000
|
||||
|
||||
#define INACTIVITY_TIMEOUT_DELAY 15000
|
||||
|
||||
|
||||
enum{
|
||||
MAX_CARS = 4,
|
||||
};
|
||||
|
@ -104,7 +107,7 @@ typedef struct ack{
|
|||
|
||||
|
||||
struct cfgcircuit{
|
||||
int outtunnel;
|
||||
uint8_t outtunnel;
|
||||
};
|
||||
|
||||
enum phases{
|
||||
|
@ -126,7 +129,11 @@ struct race{
|
|||
bool newcfg;
|
||||
enum phases phase;
|
||||
byte numcars;
|
||||
int winner;
|
||||
byte winner;
|
||||
bool demo_mode;
|
||||
bool demo_mode_on_received;
|
||||
bool demo_mode_off_received;
|
||||
bool network_race;
|
||||
};
|
||||
|
||||
|
||||
|
@ -145,9 +152,12 @@ static track_t tck;
|
|||
|
||||
static int const eeadrInfo = 0;
|
||||
|
||||
static unsigned long lastmillis = 0;
|
||||
static unsigned long last_telemetry_millis = 0;
|
||||
unsigned long last_activity_millis = 0;
|
||||
|
||||
SoftTimer startRace_delay = SoftTimer(); // non blocking delay() for Autostart, Countdown
|
||||
SoftTimer demoMode_delay = SoftTimer(); // non blocking delay() for activate Demo Mode on inactivity
|
||||
|
||||
SoftTimer customDelay = SoftTimer(); // non blocking delay()
|
||||
|
||||
// Used to manage countdown phases
|
||||
int countdown_phase=1;
|
||||
|
@ -162,6 +172,7 @@ int win_music[] = {
|
|||
|
||||
char tracksID[ NUM_TRACKS ][2] ={"U","M","B","I","O"};
|
||||
|
||||
|
||||
/* ----------- Function prototypes ------------------- */
|
||||
|
||||
void sendResponse( ack_t *ack);
|
||||
|
@ -179,6 +190,13 @@ SerialCommand serialCommand = SerialCommand(cmd, REC_COMMAND_BUFLEN, EOL, &Seria
|
|||
char txbuff[TX_COMMAND_BUFLEN];
|
||||
|
||||
Adafruit_NeoPixel track;
|
||||
static uint32_t car_color[]={
|
||||
COLOR1,
|
||||
COLOR2,
|
||||
COLOR3,
|
||||
COLOR4
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -192,32 +210,35 @@ void setup() {
|
|||
param_load( &tck.cfg );
|
||||
|
||||
track = Adafruit_NeoPixel( tck.cfg.track.nled_total, PIN_LED, NEO_GRB + NEO_KHZ800 );
|
||||
|
||||
controller_init( &switchs[0], DIGITAL_MODE, DIG_CONTROL_1 );
|
||||
car_init( &cars[0], &switchs[0], COLOR1 );
|
||||
controller_init( &switchs[1], DIGITAL_MODE, DIG_CONTROL_2 );
|
||||
car_init( &cars[1], &switchs[1], COLOR2 );
|
||||
|
||||
|
||||
// First 2 controllers always active (Red, Green)
|
||||
race.numcars = 2;
|
||||
|
||||
if( controller_isActive( DIG_CONTROL_3 ) || param_option_is_active(&tck.cfg, PLAYER_3_OPTION) || param_option_is_active(&tck.cfg, PLAYER_4_OPTION) ) {
|
||||
controller_init( &switchs[2], DIGITAL_MODE, DIG_CONTROL_3 );
|
||||
car_init( &cars[2], &switchs[2], COLOR3 );
|
||||
|
||||
// Calculate actual players number
|
||||
if( controller_isActive( DIGITAL_CTRL[CTRL_3] ) || param_option_is_active(&tck.cfg, PLAYER_3_OPTION) || param_option_is_active(&tck.cfg, PLAYER_4_OPTION) ) {
|
||||
++race.numcars;
|
||||
}
|
||||
if( controller_isActive( DIGITAL_CTRL[CTRL_4] ) || param_option_is_active(&tck.cfg, PLAYER_4_OPTION)) {
|
||||
++race.numcars;
|
||||
}
|
||||
|
||||
if( controller_isActive( DIG_CONTROL_4 ) || param_option_is_active(&tck.cfg, PLAYER_4_OPTION)) {
|
||||
controller_init( &switchs[3], DIGITAL_MODE, DIG_CONTROL_4 );
|
||||
car_init( &cars[3], &switchs[3], COLOR4 );
|
||||
++race.numcars;
|
||||
}
|
||||
// Check if DEMO mode is configured
|
||||
race.demo_mode = param_option_is_active(&tck.cfg, DEMO_MODE_OPTION);
|
||||
enum ctr_type current_mode = (race.demo_mode == true) ? DEMO_MODE : DIGITAL_MODE;
|
||||
|
||||
// !!! Eliminare var current_mode ...mettere if contratto direttamente in f() call
|
||||
|
||||
// Initialize Controllers for very player
|
||||
set_controllers_mode(race.numcars, current_mode ) ;
|
||||
|
||||
// Initialize car for every player
|
||||
init_cars(race.numcars);
|
||||
|
||||
track.begin();
|
||||
strip_clear( &tck );
|
||||
|
||||
|
||||
// Check Box before Physic/Sound to allow user to have Box and Physics with no sound
|
||||
if(digitalRead(DIG_CONTROL_2)==0 || param_option_is_active(&tck.cfg, BOX_MODE_OPTION) ) { //push switch 2 on reset for activate boxes (pit lane)
|
||||
if(digitalRead(DIGITAL_CTRL[CTRL_2])==0 || param_option_is_active(&tck.cfg, BOX_MODE_OPTION) ) { //push switch 2 on reset for activate boxes (pit lane)
|
||||
box_init( &tck );
|
||||
track_configure( &tck, tck.cfg.track.nled_total - tck.cfg.track.box_len );
|
||||
draw_box_entrypoint( &tck );
|
||||
|
@ -225,23 +246,29 @@ void setup() {
|
|||
track_configure( &tck, 0 );
|
||||
}
|
||||
|
||||
if( digitalRead(DIG_CONTROL_1)==0 || param_option_is_active(&tck.cfg, SLOPE_MODE_OPTION) ) { // push switch 1 on reset for activate physics
|
||||
if( digitalRead(DIGITAL_CTRL[CTRL_1])==0 || param_option_is_active(&tck.cfg, SLOPE_MODE_OPTION) ) { // push switch 1 on reset for activate physics
|
||||
ramp_init( &tck );
|
||||
draw_ramp( &tck );
|
||||
track.show();
|
||||
delay(2000);
|
||||
if ( digitalRead( DIG_CONTROL_1 ) == 0 ) { //retain push switch on reset for activate FX sound
|
||||
if ( digitalRead( DIGITAL_CTRL[CTRL_1] ) == 0 ) { //retain push switch on reset for activate FX sound
|
||||
SMOTOR=1;
|
||||
tone(PIN_AUDIO,100);}
|
||||
}
|
||||
|
||||
race.cfg.startline = tck.cfg.race.startline;// true;
|
||||
race.cfg.nlap = tck.cfg.race.nlap;// NUMLAP;
|
||||
race.cfg.nrepeat = tck.cfg.race.nrepeat;// 1;
|
||||
race.cfg.finishline = tck.cfg.race.finishline;// true;
|
||||
race.network_race = false; // always starts in standalone mode
|
||||
race.demo_mode_on_received = false;
|
||||
race.demo_mode_off_received = false;
|
||||
|
||||
race.cfg.startline = tck.cfg.race.startline; // always true for Standalone mode
|
||||
race.cfg.nlap = tck.cfg.race.nlap; // NUMLAP;
|
||||
race.cfg.nrepeat = tck.cfg.race.nrepeat; // always 1 for Standalone mode
|
||||
race.cfg.finishline = tck.cfg.race.finishline; // always true for Standalone mode
|
||||
|
||||
customDelay.start(0); // first race starts with no delay
|
||||
race.phase = READY;
|
||||
startRace_delay.start(0); // first race starts with no delay
|
||||
race.phase = READY; // READY is the first status for Standalone mode
|
||||
|
||||
last_activity_millis = millis();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -255,6 +282,17 @@ void loop() {
|
|||
sendResponse(&ack);
|
||||
}
|
||||
|
||||
// Exit DEMO mode when a Player touch a controller
|
||||
if( race.demo_mode_off_received || (race.demo_mode && players_actity(race.numcars)) ){
|
||||
exit_demo_mode();
|
||||
}
|
||||
// If demo_mode option is set in board configuration
|
||||
// -> Enter demo mode after INACTIVITY_TIMEOUT_DELAY
|
||||
if( race.demo_mode_on_received || (param_option_is_active(&tck.cfg, DEMO_MODE_OPTION) && race.demo_mode==false && ready_for_demo_mode()) ) {
|
||||
activate_demo_mode();
|
||||
}
|
||||
|
||||
|
||||
// PLEASE NOTE:
|
||||
// DO NOT call "track.show()" in the loop() while in configuration mode !!!
|
||||
// It would mess up with Serial communication (receives only 2 bytes - if the
|
||||
|
@ -269,19 +307,24 @@ void loop() {
|
|||
if( race.newcfg ) {
|
||||
race.newcfg = false;
|
||||
countdownReset();
|
||||
customDelay.start(0);
|
||||
race.phase = READY;
|
||||
startRace_delay.start(0);
|
||||
|
||||
// for Standalone mode, gets into READY status
|
||||
// for Network races gets into CONFIGURATION OK statue
|
||||
race.phase = ( race.network_race == false ) ? READY : CONFIG_OK;
|
||||
|
||||
send_phase( race.phase );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case READY:
|
||||
{
|
||||
if(param_option_is_active(&tck.cfg, AUTOSTART_MODE_OPTION)){ // Auto-Start Mode ON
|
||||
if(customDelay.elapsed()) {
|
||||
if(startRace_delay.elapsed()) {
|
||||
for( int i = 0; i < race.numcars; ++i) {
|
||||
car_resetPosition( &cars[i] );
|
||||
car_resetPosition( &cars[i], true );
|
||||
cars[i].repeats = 0;
|
||||
}
|
||||
tck.ledcoin = COIN_RESET;
|
||||
|
@ -297,7 +340,7 @@ void loop() {
|
|||
draw_box_entrypoint( &tck );
|
||||
for( int i = 0; i < race.numcars; ++i) {
|
||||
if (controller_getStatus(cars[i].ct)==false){
|
||||
car_resetPosition( &cars[i] );
|
||||
car_resetPosition( &cars[i], true );
|
||||
//Serial.println(i);
|
||||
track.setPixelColor(i,cars[i].color);
|
||||
cars[i].repeats = 0;
|
||||
|
@ -319,8 +362,7 @@ void loop() {
|
|||
{
|
||||
if( race.cfg.startline ){
|
||||
// Countdown: semaphore and tones
|
||||
if(start_race_done()) {
|
||||
// Countdown done
|
||||
if(start_race_done()) { // Countdown done
|
||||
for( int i = 0; i < race.numcars; ++i ) {
|
||||
cars[i].st = CAR_ENTER;
|
||||
}
|
||||
|
@ -367,7 +409,7 @@ void loop() {
|
|||
run_racecycle( &cars[i], i );
|
||||
if( cars[i].st == CAR_FINISH ) {
|
||||
race.phase = COMPLETE;
|
||||
race.winner = i;
|
||||
race.winner = (byte) i;
|
||||
send_phase( race.phase );
|
||||
break;
|
||||
}
|
||||
|
@ -377,18 +419,18 @@ void loop() {
|
|||
if (SMOTOR==1) tone(PIN_AUDIO,FBEEP+int(cars[0].speed*440*1)+int(cars[1].speed*440*2)+int(cars[2].speed*440*3)+int(cars[3].speed*440*4));
|
||||
if (TBEEP>0) {TBEEP--;} else {FBEEP=0;};
|
||||
|
||||
// Print p command!!!
|
||||
// Print p command!!!
|
||||
unsigned long nowmillis = millis();
|
||||
if( abs( nowmillis - lastmillis ) > 250 ){
|
||||
lastmillis = nowmillis;
|
||||
if( abs( nowmillis - last_telemetry_millis ) > 250 ){
|
||||
last_telemetry_millis = nowmillis;
|
||||
print_cars_positions( cars );
|
||||
}
|
||||
// ----------------
|
||||
// ----------------
|
||||
}
|
||||
break;
|
||||
|
||||
case COMPLETE :
|
||||
{
|
||||
{
|
||||
strip_clear( &tck );
|
||||
track.show();
|
||||
if ( race.cfg.finishline ){
|
||||
|
@ -397,9 +439,25 @@ void loop() {
|
|||
strip_clear( &tck );
|
||||
}
|
||||
track.show();
|
||||
customDelay.start(NEWRACE_DELAY);
|
||||
race.phase = READY;
|
||||
}
|
||||
|
||||
startRace_delay.start(NEWRACE_DELAY);
|
||||
|
||||
// for Standalone mode, gets into READY status
|
||||
// for Network races gets into IDLE statue
|
||||
race.phase = ( race.network_race == false ) ? READY : IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONFIG_OK: // OLR Network only
|
||||
case IDLE: // OLR Network only
|
||||
{
|
||||
; // In a Relay Race the configuration is sent (via 'C' command) by the
|
||||
// Host ("Nerwork Client" program running on another Computer)
|
||||
// When the board reach the CONFIG_OK status...it does nothing but wait for
|
||||
// the next Command coming form the Host.
|
||||
// Same thing for the IDLE status (reached at the end of a relay race)
|
||||
// In other words, in Relay Races, some Status changes comes from the Host
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -413,6 +471,73 @@ void loop() {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void set_controllers_mode(uint8_t numctrl, uint8_t mode ) {
|
||||
for( uint8_t i = 0; i < numctrl; ++i) {
|
||||
controller_init( &switchs[i], mode, DIGITAL_CTRL[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void init_cars(uint8_t numcars ) {
|
||||
for( uint8_t i = 0; i < numcars; ++i) {
|
||||
car_init( &cars[i], &switchs[i], car_color[i] );
|
||||
}
|
||||
}
|
||||
|
||||
bool players_actity(uint8_t numcars ) {
|
||||
for( uint8_t i = 0; i < numcars; ++i) {
|
||||
if(controller_isActive(DIGITAL_CTRL[i]))
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if Controllers (players) were incative for more than INACTIVITY_TIMEOUT_DELAY
|
||||
*/
|
||||
bool ready_for_demo_mode(void) {
|
||||
if(players_actity(race.numcars)){
|
||||
demoMode_delay.start(INACTIVITY_TIMEOUT_DELAY); // Reset timeout when somebody is using controllers
|
||||
}
|
||||
return (demoMode_delay.elapsed());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void activate_demo_mode(void){
|
||||
race.demo_mode = true;
|
||||
race.demo_mode_on_received = false; // reset flag
|
||||
set_controllers_mode(race.numcars, DEMO_MODE ) ;
|
||||
race.winner=0; // Fake set (used in Status=Complete by draw_winner())
|
||||
race.phase = COMPLETE;
|
||||
|
||||
sprintf(txbuff, "%c%d%c", 'M', 1 , EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void exit_demo_mode(void){
|
||||
race.demo_mode = false;
|
||||
race.demo_mode_off_received = false; // reset flag
|
||||
set_controllers_mode(race.numcars, DIGITAL_MODE ) ;
|
||||
race.winner=0; // Fake set (used in Status=Complete by draw_winner())
|
||||
race.phase = COMPLETE;
|
||||
|
||||
sprintf(txbuff, "%c%d%c", 'M', 0 , EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
}
|
||||
|
||||
void send_phase( int phase ) {
|
||||
sprintf(txbuff, "R%d%c",phase,EOL);
|
||||
serialCommand.sendCommand(txbuff);
|
||||
|
@ -421,9 +546,29 @@ void send_phase( int phase ) {
|
|||
|
||||
void run_racecycle( car_t *car, int i ) {
|
||||
struct cfgtrack const* cfg = &tck.cfg.track;
|
||||
|
||||
// if( car->st == CAR_COMING ) { // OLR Network only
|
||||
// // To be implemented
|
||||
// }
|
||||
|
||||
if( car->st == CAR_ENTER ) {
|
||||
car_resetPosition( car );
|
||||
|
||||
// Standalone mode => On Race start the Speed get RESET (speed=0)
|
||||
// Network race => Car speed set when receiving the Car_Enter Serial command
|
||||
(race.network_race == true) ? car_resetPosition( car, false ) : car_resetPosition( car, true );
|
||||
|
||||
|
||||
// In DEMO_MODE Red car gets a different bost on start (allows to see all cars in the circuit)
|
||||
if( switchs[0].mode == DEMO_MODE ){
|
||||
cars[0].speed = 1.2;
|
||||
float dec = 0.4;
|
||||
for( uint8_t i = 1; i < race.numcars; ++i ) {
|
||||
cars[i].speed = 1.2 - dec;
|
||||
dec += 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( car->repeats < race.cfg.nrepeat )
|
||||
car->st = CAR_RACING;
|
||||
else
|
||||
|
@ -440,7 +585,7 @@ void run_racecycle( car_t *car, int i ) {
|
|||
&& car->dist > ( cfg->nled_main*car->nlap - race.circ.outtunnel ) ) {
|
||||
car->leaving = true;
|
||||
car->st = CAR_LEAVING;
|
||||
}
|
||||
}
|
||||
|
||||
if( car->nlap > race.cfg.nlap ) {
|
||||
++car->repeats;
|
||||
|
@ -452,14 +597,30 @@ void run_racecycle( car_t *car, int i ) {
|
|||
car->st = CAR_FINISH;
|
||||
}
|
||||
}
|
||||
|
||||
if( car->st == CAR_LEAVING ) { // OLR Network only
|
||||
car->st = CAR_RACING;
|
||||
sprintf( txbuff, "r%d%c", i + 1, EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
}
|
||||
|
||||
if( car->st == CAR_GO_OUT ) { // OLR Network only
|
||||
car->st = CAR_WAITING;
|
||||
//#warning Insert function to map speed!
|
||||
byte const speed = car->speed * 10;
|
||||
byte const data = (i + 1) << 5 | ( 0b00011111 & speed );
|
||||
sprintf( txbuff, "s%c%c", data, EOL );
|
||||
serialCommand.sendCommand(txbuff);;
|
||||
car_resetPosition( car, true );
|
||||
car->trackID = NOT_TRACK;
|
||||
}
|
||||
|
||||
if ( car->st == CAR_FINISH ){
|
||||
car->trackID = NOT_TRACK;
|
||||
sprintf( txbuff, "w%d%c", i + 1, EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
//sendCommand(txbuff);
|
||||
|
||||
car_resetPosition( car );
|
||||
car_resetPosition(car, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,7 +671,7 @@ void print_cars_positions( car_t* cars ) {
|
|||
boolean start_race_done( ) {
|
||||
if(countdown_new_phase){
|
||||
countdown_new_phase=false;
|
||||
customDelay.start(CONTDOWN_PHASE_DURATION);
|
||||
startRace_delay.start(CONTDOWN_PHASE_DURATION);
|
||||
strip_clear( &tck );
|
||||
if(ramp_isactive( &tck )) draw_ramp( &tck );
|
||||
if(box_isactive( &tck )) draw_box_entrypoint( &tck );
|
||||
|
@ -530,7 +691,7 @@ boolean start_race_done( ) {
|
|||
track.setPixelColor(LED_SEMAPHORE-2, track.Color(0,255,0));
|
||||
break;
|
||||
case 4:
|
||||
customDelay.start(CONTDOWN_STARTSOUND_DURATION);
|
||||
startRace_delay.start(CONTDOWN_STARTSOUND_DURATION);
|
||||
tone(PIN_AUDIO,880);
|
||||
track.setPixelColor(LED_SEMAPHORE-2, track.Color(0,0,0));
|
||||
track.setPixelColor(0, track.Color(255,255,255));
|
||||
|
@ -542,7 +703,7 @@ boolean start_race_done( ) {
|
|||
}
|
||||
track.show();
|
||||
}
|
||||
if(customDelay.elapsed()) {
|
||||
if(startRace_delay.elapsed()) {
|
||||
noTone(PIN_AUDIO);
|
||||
countdown_new_phase=true;
|
||||
countdown_phase++;
|
||||
|
@ -559,7 +720,7 @@ void countdownReset() {
|
|||
}
|
||||
|
||||
|
||||
void sound_winner( track_t* tck, int winner ) {
|
||||
void sound_winner( track_t* tck, byte winner ) {
|
||||
int const msize = sizeof(win_music) / sizeof(int);
|
||||
for (int note = 0; note < msize; note++) {
|
||||
tone(PIN_AUDIO, win_music[note],200);
|
||||
|
@ -738,16 +899,46 @@ ack_t manageSerialCommand() {
|
|||
case 'R' : // Set Race Phase
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
int const phase = atoi( cmd + 1);
|
||||
if( 0 > phase || RACE_PHASES <= phase) return ack;
|
||||
uint8_t const phase = atoi( cmd + 1);
|
||||
// Does not accept anymore R=1 as Enter Configuration / Use command @ instead
|
||||
if( 0 > phase || RACE_PHASES <= phase || phase == CONFIG) return ack;
|
||||
race.phase = (enum phases) phase;
|
||||
ack.rp = OK;
|
||||
if ( race.phase == CONFIG ) { // accept R1 as a EnterConfigurationMode command - DEPRECATED
|
||||
enter_configuration_mode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u' : // Car Enter the Circuit - // OLR Network only
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
byte const data = cmd[1];
|
||||
byte const ncar = 0b00000111 & ( data >> 5 );
|
||||
byte const speed = 0b00011111 & data;
|
||||
if( 0 >= ncar || race.numcars < ncar) return ack;
|
||||
cars[ncar-1].st = CAR_ENTER;
|
||||
cars[ncar-1].speed = (float) speed / 10;
|
||||
ack.rp = OK;
|
||||
if( false ) {
|
||||
sprintf( txbuff, "%s %d, %s %d, %s %d", "CAR: ", ncar, "STATUS: ", cars[ncar-1].st, "SPEED: ", (int)cars[ncar-1].speed * 10 );
|
||||
printdebug( txbuff, LOG );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 't' : // Car Coming into the Circuit - // OLR Network only
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
byte const ncar = atoi( cmd + 1);
|
||||
if( 0 >= ncar || race.numcars < ncar) return ack;
|
||||
cars[ncar-1].st = CAR_COMING;
|
||||
ack.rp = OK;
|
||||
if ( false ) {
|
||||
sprintf( txbuff, "%s %d, %s %d", "CAR: ", ncar, "STATUS: ", cars[ncar-1].st);
|
||||
printdebug( txbuff, LOG );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'C' : //Parse race configuration -> C1,2,3,0
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
|
@ -787,7 +978,7 @@ ack_t manageSerialCommand() {
|
|||
case 'T' : //Parse Track configuration -> Track length
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
|
||||
|
||||
char * pch = strtok (cmd,"T");
|
||||
if( !pch ) return ack;
|
||||
|
||||
|
@ -855,7 +1046,7 @@ ack_t manageSerialCommand() {
|
|||
if( !pch ) return ack;
|
||||
int slopeperm = atoi( pch );
|
||||
|
||||
int err = ramp_configure( &tck, init, center, end, high, slopeperm );
|
||||
uint8_t err = ramp_configure( &tck, init, center, end, high, slopeperm );
|
||||
if( err ) return ack;
|
||||
ack.rp = OK;
|
||||
|
||||
|
@ -876,51 +1067,73 @@ ack_t manageSerialCommand() {
|
|||
|
||||
pch = strtok (pch, "," );
|
||||
if( !pch ) return ack;
|
||||
int delta = atoi( pch );
|
||||
uint8_t delta = atoi( pch );
|
||||
|
||||
pch = strtok (NULL, "," );
|
||||
if( !pch ) return ack;
|
||||
int min = atoi( pch );
|
||||
uint8_t min = atoi( pch );
|
||||
|
||||
pch = strtok (NULL, "," );
|
||||
if( !pch ) return ack;
|
||||
int boost = atoi( pch );
|
||||
uint8_t boost = atoi( pch );
|
||||
|
||||
pch = strtok (NULL, ",");
|
||||
if( !pch ) return ack;
|
||||
int active = atoi( pch );
|
||||
uint8_t active = atoi( pch );
|
||||
|
||||
int err = battery_configure( &tck, delta, min, boost, active );
|
||||
uint8_t err = battery_configure( &tck, delta, min, boost, active );
|
||||
if( err ) return ack;
|
||||
ack.rp = OK;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G' : //Parse Autostart configuration -> Gautostart
|
||||
case 'G' : // Parse Autostart configuration -> Gautostart
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
|
||||
char * pch = strtok (cmd,"G");
|
||||
if( !pch ) return ack;
|
||||
|
||||
int autostart = atoi( cmd + 1 );
|
||||
int err = autostart_configure( &tck, autostart);
|
||||
uint8_t autostart = atoi( cmd + 1 );
|
||||
uint8_t err = autostart_configure( &tck, autostart);
|
||||
if( err ) return ack;
|
||||
|
||||
ack.rp = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P' : //Parse Player 3/4 configuration -> P[2|3|4]
|
||||
case 'M' : // Parse DEMO mode configuration
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
|
||||
char * pch = strtok (cmd,"M");
|
||||
if( !pch ) return ack;
|
||||
|
||||
uint8_t demo = atoi( cmd + 1 );
|
||||
|
||||
uint8_t err = demo_configure( &tck, demo);
|
||||
if( err ) return ack;
|
||||
ack.rp = OK;
|
||||
|
||||
if(demo == 0) {
|
||||
race.demo_mode_off_received = true;
|
||||
} else if( race.demo_mode){
|
||||
race.demo_mode_on_received = true;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P' : // Parse Player 3/4 configuration -> P[2|3|4]
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
|
||||
char * pch = strtok (cmd,"P");
|
||||
if( !pch ) return ack;
|
||||
|
||||
int autostart = atoi( cmd + 1 );
|
||||
int err = players_n_configure( &tck, autostart);
|
||||
uint8_t players_n = atoi( cmd + 1 );
|
||||
uint8_t err = players_n_configure( &tck, players_n);
|
||||
if( err ) return ack;
|
||||
|
||||
ack.rp = OK;
|
||||
|
@ -952,6 +1165,20 @@ ack_t manageSerialCommand() {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'H' : // Tunnel configuration - // OLR Network only
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
uint8_t const dtunnel = atoi( cmd + 1);
|
||||
if( 0 >= dtunnel || 254 < dtunnel) return ack;
|
||||
race.circ.outtunnel = dtunnel;
|
||||
ack.rp = OK;
|
||||
if ( false ) { //VERBOSE
|
||||
sprintf( txbuff, "%s %d", "TUNNEL: ", race.circ.outtunnel );
|
||||
printdebug( txbuff, LOG );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'D' : // Load Default Parameters and store them in from EEPROM
|
||||
{
|
||||
|
@ -1006,6 +1233,16 @@ ack_t manageSerialCommand() {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'n' : // Set "Network Race" mode (Relay race)
|
||||
{
|
||||
ack.type = cmd[0];
|
||||
race.network_race = true;
|
||||
race.phase = COMPLETE; // Immediatly ends the current race (if any)
|
||||
race.winner=0; // Set a fake winner (used in Status=Complete by draw_winner())
|
||||
ack.rp = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Q': // Get current configuration Info
|
||||
{
|
||||
struct cfgparam const* cfg = &tck.cfg;
|
||||
|
@ -1041,13 +1278,16 @@ ack_t manageSerialCommand() {
|
|||
EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
|
||||
sprintf( txbuff, "%s:%d,%d,%d,%d,%d,%d%c", "QRC",
|
||||
sprintf( txbuff, "%s:%d,%d,%d,%d,%d,%d,%d,%d%c", "QRC",
|
||||
cfg->race.startline,
|
||||
cfg->race.nlap,
|
||||
cfg->race.nrepeat,
|
||||
cfg->race.finishline,
|
||||
param_option_is_active(&tck.cfg, PLAYER_3_OPTION),
|
||||
param_option_is_active(&tck.cfg, PLAYER_4_OPTION),
|
||||
param_option_is_active(&tck.cfg, DEMO_MODE_OPTION),
|
||||
//race.demo_mode,
|
||||
race.network_race,
|
||||
EOL );
|
||||
serialCommand.sendCommand(txbuff);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue