diff --git a/open-led-race_0.0/SerialCommand.cpp b/open-led-race_0.0/SerialCommand.cpp deleted file mode 100644 index 80fdfaf..0000000 --- a/open-led-race_0.0/SerialCommand.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "SerialCommand.h" - - -/* - * - */ -SerialCommand::SerialCommand() { - _initialized = false; -} -/* - * - */ -SerialCommand::SerialCommand(char *buf, int blen, char eoc, Stream* stream) { - init(buf, blen, eoc, stream); -} - -/* - * - */ -void SerialCommand::init(char *buf, int blen, char eoc, Stream* stream) { - if(_initialized) return; - - _stream = stream == NULL ? &Serial : stream; - _buf = buf; - _bufLen = blen; - _bufIdx = 0; - _eoc = eoc; - _initialized = true; -} - - -/* - * - */ -int SerialCommand::getCommand() { - if( !_initialized) return(-1); - - while (_stream->available()) { - if(_bufIdx < _bufLen - 2) { - char data = _stream->read(); - if(data == _eoc) { - int cmsSize=_bufIdx; - _buf[_bufIdx++] = '\0'; - _bufIdx=0; - return(cmsSize); - } else { - _buf[_bufIdx++] = data; - } - } else { - // buffer full - // re4set and retunn error - _buf[_bufIdx++] = '\0'; - _bufIdx=0; - return(-2); - } - } - return(0); - -} - - -void SerialCommand::sendCommand(char* str) { - // get command length - int dlen=0; -// for(; dlen<_bufLen; dlen++ ) { // limit transmitted command length to received command buffer - for(; dlen<80; dlen++ ) { // limit transmitted command length to received command buffer - if(*(str+dlen) == _eoc ){ - dlen++; // send EOC - break; - } - } - _stream->write(str, dlen); - return; -} diff --git a/open-led-race_0.0/SerialCommand.h b/open-led-race_0.0/SerialCommand.h deleted file mode 100644 index bb3af55..0000000 --- a/open-led-race_0.0/SerialCommand.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SerialCommand_h -#define SerialCommand_h - -#include - -class SerialCommand { - - public: - SerialCommand(); - SerialCommand(char *buf, int bufLen, char eoc, Stream* stream); - void init(char *buf, int bufLen, char eoc, Stream* stream); - int getCommand(void); - void sendCommand(char *); - - int overflow; - - protected: - Stream* _stream; - char *_buf; - int _bufIdx; - int _bufLen; - char _eoc; // EndOfCommand char - - bool _initialized; - - -}; - -#endif diff --git a/open-led-race_0.0/SoftTimer.cpp b/open-led-race_0.0/SoftTimer.cpp deleted file mode 100644 index 40e7e11..0000000 --- a/open-led-race_0.0/SoftTimer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "SoftTimer.h" - -SoftTimer::SoftTimer(unsigned long tout) { - this->set(tout); -} - -SoftTimer::SoftTimer() { -} - -/* - * - */ -void SoftTimer::set(unsigned long tout) { - this->timeout=tout; -} - - -void SoftTimer::start() { - this->startTime=millis(); -} - -void SoftTimer::start(unsigned long tout) { - this->set(tout); - this->start(); -} - - -/* - * - */ -boolean SoftTimer::elapsed(){ - if((millis() - this->startTime) > this->timeout) { - return(true); - } - return(false); -} diff --git a/open-led-race_0.0/SoftTimer.h b/open-led-race_0.0/SoftTimer.h deleted file mode 100644 index 55ff24f..0000000 --- a/open-led-race_0.0/SoftTimer.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SoftTimer_h -#define SoftTimer_h - -#include - -class SoftTimer { - - public: - - SoftTimer(void); - SoftTimer(unsigned long); - void set(unsigned long); - void start(void); - void start(unsigned long); - boolean elapsed(void); - - private: - unsigned long startTime=0; - unsigned long timeout=0; - -}; - -#endif diff --git a/open-led-race_0.0/olr-controller.c b/open-led-race_0.0/olr-controller.c deleted file mode 100644 index 1b8e55c..0000000 --- a/open-led-race_0.0/olr-controller.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "olr-controller.h" - -enum { - DELTA_ANALOG = 5, -}; - -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); -} - -void controller_init( controller_t* ct, enum ctr_type mode, int pin ) { - ct->mode = mode; - ct->pin = pin; - ct->delta_analog = DELTA_ANALOG; -} - - -byte controller_getStatus( controller_t* ct ) { - - if( ct->mode == DIGITAL_MODE ){ - return digitalRead( ct->pin ); - } - else if( ct->mode == ANALOG_MODE ){ - ct->adc = analogRead( ct->pin ); - if( abs( ct->badc - ct->adc ) > ct->delta_analog ){ - ct->badc = ct->adc; - return 1; - } - ct->badc = ct->adc; - } - else if( ct->mode == DEBUG_MODE ){ - ct->adc++; - if( ct->adc >= 60){ - ct->adc = 0; - return 1; - } - } - return 0; - -} - - -float controller_getSpeed( controller_t* ct) { - float speed = 0.0; - if ( (ct->flag_sw == 1 ) && (controller_getStatus( ct ) == 0) ) { - ct->flag_sw = 0; - speed = ACEL; - } - - if ( (ct->flag_sw == 0 ) && (controller_getStatus( ct ) == 1 ) ) { - ct->flag_sw = 1; - } - return speed; -} - -float controller_getAccel ( void ) { - return ACEL; -} - -bool controller_isActive( int pin ) { - return !digitalRead( pin ); -} diff --git a/open-led-race_0.0/olr-controller.h b/open-led-race_0.0/olr-controller.h deleted file mode 100644 index 87fad3a..0000000 --- a/open-led-race_0.0/olr-controller.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _OLR_CONTROLLER_LIB_h -#define _OLR_CONTROLLER_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include "Arduino.h" -#include -#include - - -#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{ - NOT_DEFINED = 0, - DIGITAL_MODE, - ANALOG_MODE, - DEBUG_MODE, -}; - -typedef struct{ - enum ctr_type mode; - int pin; - int adc; - int badc; - int delta_analog; - byte flag_sw; -}controller_t; - -void controller_setup( void ); - -void controller_init( controller_t* ct, enum ctr_type mode, int pin ); - -byte controller_getStatus( controller_t* ct ); - -float controller_getSpeed( controller_t* ct ); - -float controller_getAccel ( void ); - -bool controller_isActive( int pin ); - - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - diff --git a/open-led-race_0.0/olr-lib.c b/open-led-race_0.0/olr-lib.c deleted file mode 100644 index 7e2010c..0000000 --- a/open-led-race_0.0/olr-lib.c +++ /dev/null @@ -1,197 +0,0 @@ -#include "Arduino.h" -#include "olr-lib.h" - - -//void process_main_track( track_t* tck, car_t* car ); -//void process_aux_track( track_t* tck, car_t* car ); - - - - - - - -void car_init( car_t* car, controller_t* ct, uint32_t color ) { - car->ct = ct; - car->color = color; - car->trackID = TRACK_MAIN; - car->speed=0; - car->dist=0; - car->dist_aux=0; -} - -void car_updateController( car_t* car ) { - car->speed += controller_getSpeed( car->ct ); -} - -void update_track( track_t* tck, car_t* car ) { - controller_t* ct = car->ct; - struct cfgtrack const* cfg = &tck->cfg.track; - - - if ( car->trackID == TRACK_MAIN - && (int)car->dist % cfg->nled_main == (cfg->init_aux-(cfg->nled_aux)) - // && controller_getStatus( ct ) == 0 ) { //change track by switch - && (car->speed <= SPD_MIN_TRACK_AUX )) { //change track by low speed - - car->trackID = TRACK_AUX; - car->dist_aux = 0; - } - else if( car->trackID == TRACK_AUX - && car->dist_aux > cfg->nled_aux ) { - - car->trackID = TRACK_MAIN; - car->dist += cfg->nled_aux; - } - - /* Update car position in the current track */ - if ( car->trackID == TRACK_AUX ) process_aux_track( tck, car ); - else if ( car->trackID == TRACK_MAIN ) process_main_track( tck, car ); - - /* Update car lap */ - if ( car->dist > ( cfg->nled_main*car->nlap -1) ) car->nlap++; -} - -void process_aux_track( track_t* tck, car_t* car ){ - struct cfgtrack const* cfg = &tck->cfg.track; - - if ( (int)car->dist_aux == tck->ledcoin - && car->speed <= controller_getAccel() ) { - car->speed = controller_getAccel ()*50; - tck->ledcoin = COIN_RESET; - }; - - car->speed -= car->speed * cfg->kf; - car->dist_aux += car->speed; -} - - -void process_main_track( track_t* tck, car_t* car ) { - struct cfgtrack const* cfg = &tck->cfg.track; - - if ( tck->rampactive ) { - struct cfgramp const* r = &tck->cfg.ramp; - int const pos = (int)car->dist % cfg->nled_main; - if ( pos >= r->init && pos < r->center ) - // car->speed -= cfg->kg * r->high * ( pos - r->init ); - car->speed -= cfg->kg * r->high ; - - if ( pos <= r->end && pos > r->center ) - //car->speed += cfg->kg * r->high * ( pos - r->center ); - car->speed += cfg->kg * r->high ; - } - - car->speed -= car->speed * cfg->kf; - car->dist += car->speed; - -} - -void ramp_init( track_t* tck ) { - tck->rampactive = true; -} - - -bool ramp_isactive( track_t* tck ) { - return tck->rampactive; -} - - -void car_resetPosition( car_t* car) { - - car->trackID = TRACK_MAIN; - car->speed = 0; - car->dist = 0; - car->dist_aux = 0; - car->nlap = 1; - car->leaving = false; -} - -void box_init( track_t* tck ) { - tck->boxactive = true; -} - -bool box_isactive( track_t* tck ) { - return tck->boxactive; -} - - - -int tracklen_configure( track_t* tck, int nled ) { - struct cfgtrack* cfg = &tck->cfg.track; - if( nled <= 0 ) return -1; - cfg->nled_total = nled; - return 0; -} - -int boxlen_configure( track_t* tck, int box_len, int boxalwaysOn ) { - struct cfgtrack* cfg = &tck->cfg.track; - - if ( boxalwaysOn != 0 && boxalwaysOn != 1 ) return -1; - if( box_len <= 0 || box_len >= cfg->nled_total ) return -1; - cfg->box_len = box_len; - cfg->box_alwaysOn = boxalwaysOn; - - // Update track->boxactive - tck->boxactive = boxalwaysOn; - return 0; -} - -int physic_configure( track_t* tck, float kgp, float kfp ){ - struct cfgtrack* cfg = &tck->cfg.track; - - if( kgp <= 0.0 || kgp >= 2.0 ) return -1; - if( kfp <= 0.0 || kfp >= 2.0 ) return -1; - cfg->kf = kfp; - cfg->kg = kgp; - return(0); -} - - - -int track_configure( track_t* tck, int init_box ) { - struct cfgtrack* cfg = &tck->cfg.track; - - if(init_box >= cfg->nled_total ) return -1; - cfg->nled_main = ( init_box == 0 ) ? cfg->nled_total : init_box; - cfg->nled_aux = ( init_box == 0 ) ? 0 : cfg->nled_total - init_box; - cfg->init_aux = init_box - 1; - return 0; -} - - -int ramp_configure( track_t* tck, int init, int center, int end, int high, int alwaysOn ) { - struct cfgramp* ramp = &tck->cfg.ramp; - - if ( init >= tck->cfg.track.nled_main || init <= 0 ) return -1; - if ( center >= tck->cfg.track.nled_main || center <= 0 ) return -2; - if ( end >= tck->cfg.track.nled_main || end <= 0 ) return -3; - if ( ! (center > init && center < end) ) return -4; - if ( alwaysOn != 0 && alwaysOn != 1 ) return -5; - - ramp->init = init; - ramp->center = center; - ramp->end = end; - ramp->high = high; - ramp->alwaysOn = alwaysOn; - - // Update track->rampactive - /** - boolean rampactive = &tck->rampactive; - rampactive = alwaysOn; - **/ - tck->rampactive = alwaysOn; - - return 0; -} - -int race_configure( track_t* tck, int startline, int nlap, int nrepeat, int finishline ) { - struct cfgrace* race = &tck->cfg.race; - - if ( startline != 0 && startline != 1 ) return -1; - if ( finishline != 0 && finishline != 1 ) return -1; - race->startline = startline; - race->finishline = finishline; - race->nlap = nlap; - race->nrepeat = nrepeat; - return 0; -} diff --git a/open-led-race_0.0/olr-lib.h b/open-led-race_0.0/olr-lib.h deleted file mode 100644 index 81f84e8..0000000 --- a/open-led-race_0.0/olr-lib.h +++ /dev/null @@ -1,103 +0,0 @@ - -#ifndef _OLR_LIB_h -#define _OLR_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include -#include -#include -#include "olr-controller.h" -#include "olr-param.h" - -#define SPD_MIN_TRACK_AUX 0.8 - -enum stcoin{ - COIN_RESET = -2, - COIN_WAIT = -1, -}; - -enum{ - NOT_TRACK = 0, - TRACK_MAIN, - TRACK_AUX, - TRACK_IN, - TRACK_OUT, - NUM_TRACKS, -}; - - -enum status{ - CAR_WAITING = 0, - CAR_COMING, - CAR_ENTER, - CAR_RACING, - CAR_LEAVING, - CAR_GO_OUT, - CAR_FINISH -}; - -typedef struct{ - controller_t* ct; - float speed; - float dist; - float dist_aux; - byte nlap; - byte repeats; - uint32_t color; - int trackID; - enum status st; - bool leaving; -}car_t; - - - -typedef struct { - struct cfgparam cfg; - int ledcoin; //LED_SPEED_COIN - uint32_t ledtime; - bool rampactive; - bool boxactive; -}track_t; - - -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 update_track( track_t* tck, car_t* car ); - -void process_main_track( track_t* tck, car_t* car ); - -void process_aux_track( track_t* tck, car_t* car ); - -void box_init( track_t* tck ); - -bool box_isactive( track_t* tck ); - -int tracklen_configure( track_t* tck, int nled ); - -int boxlen_configure( track_t* tck, int box_len, int boxalwaysOn ); - -int physic_configure( track_t* tck, float kgp, float kfp ); - -int track_configure( track_t* tck, int init_box ); - -void ramp_init( track_t* tck ); - -bool ramp_isactive( track_t* tck ); - -int ramp_configure( track_t* tck, int init, int center, int end, int high, int alwaysOn ); - -int race_configure( track_t* tck, int startline, int nlap, int nrepeat, int finishline ); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/open-led-race_0.0/olr-param.c b/open-led-race_0.0/olr-param.c deleted file mode 100644 index 81290ab..0000000 --- a/open-led-race_0.0/olr-param.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "olr-param.h" - -void param_setdefault( struct cfgparam* cfg ) { - cfg->setted = true; - - cfg->race.startline = true; - cfg->race.nlap = NUMLAP; - cfg->race.nrepeat = 1; - cfg->race.finishline = true; - - cfg->ramp.init = 80; - cfg->ramp.center = 90; - cfg->ramp.end = 100; - cfg->ramp.high = 6; - cfg->ramp.alwaysOn = false; - - cfg->track.nled_total = MAXLED; - cfg->track.nled_main = MAXLED; // 240 when boxes length = 60 - cfg->track.nled_aux = 0; // 60 - cfg->track.init_aux = -1; // 239 - cfg->track.box_len = BOXLEN; - cfg->track.box_alwaysOn = false; - - cfg->track.kf = 0.015; // friction constant - cfg->track.kg = 0.006; // gravity constant - Used in Slope -} diff --git a/open-led-race_0.0/olr-param.h b/open-led-race_0.0/olr-param.h deleted file mode 100644 index 7d930a8..0000000 --- a/open-led-race_0.0/olr-param.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _OLR_SERIAL_LIB_h -#define _OLR_SERIAL_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include "Arduino.h" -#include -#include - -#define MAXLED 300 -#define BOXLEN 60 -#define NUMLAP 5 - - - -enum{ - LEN_UID = 16, - CFG_VER = 5, // "5" in V0.9.6 (manage "permanent" param for Box and Slope) -}; - -struct cfgrace{ - bool startline; // Used only in OLRNetwork - int nlap; - int nrepeat; // Used only in OLRNetwork - bool finishline; // Used only in OLRNetwork -}; - -// -struct cfgtrack { - int nled_total; - int nled_main; - int nled_aux; - int init_aux; - int box_len; // used to hold the Box Length if the default get changed. - // it's not possible to implicitly store it in nled_main,nled_aux - // because, if these are different to the default, box gets always activated - // (the software does not chek "box_isactive" to draw car position) - bool box_alwaysOn; // added in ver 0.9.6 - - - float kf; - float kg; -}; - -// ramp centred in LED 100 with 10 led fordward and 10 backguard -struct cfgramp { - int init; - int center; - int end; - int high; - bool alwaysOn; // added in ver 0.9.6 -}; - -struct brdinfo { - char uid[LEN_UID + 1]; -}; - -struct cfgparam { - bool setted; - struct cfgrace race; // added in ver 0.9.d - struct cfgtrack track; - struct cfgramp ramp; - struct brdinfo info; -}; - - -void param_setdefault( struct cfgparam* cfg ); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - diff --git a/open-led-race_0.0/open-led-race_0.0.ino b/open-led-race_0.0/open-led-race_0.0.ino deleted file mode 100644 index b3f0431..0000000 --- a/open-led-race_0.0/open-led-race_0.0.ino +++ /dev/null @@ -1,945 +0,0 @@ -/* - * ____ _ ______ _____ _____ - / __ \ | | | ____| __ \ | __ \ - | | | |_ __ ___ _ __ | | | |__ | | | | | |__) |__ _ ___ ___ - | | | | '_ \ / _ \ '_ \ | | | __| | | | | | _ // _` |/ __/ _ \ - | |__| | |_) | __/ | | | | |____| |____| |__| | | | \ \ (_| | (_| __/ - \____/| .__/ \___|_| |_| |______|______|_____/ |_| \_\__,_|\___\___| - | | - |_| - Open LED Race - An minimalist cars race for LED strip - - 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. - - - First public version by: - Angel Maldonado (https://gitlab.com/angeljmc) - Gerardo Barbarov (gbarbarov AT singulardevices DOT com) - - Basen on original idea and 2 players code by: - Gerardo Barbarov for Arduino day Seville 2019 - https://github.com/gbarbarov/led-race - - - Public Repository for this code: - https://gitlab.com/open-led-race/olr-arduino - -*/ - - -// 2020/12/10 - Ver 0.9.6 -// --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.6"; - - - -#include -#include -#include "olr-lib.h" -#include "olr-param.h" -#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_AUDIO 3 // through CAP 2uf to speaker 8 ohms - -#define EOL '\n' // End of Command char used in Protocol - -#define COLOR1 track.Color(255,0,0) -#define COLOR2 track.Color(0,255,0) -#define COLOR3 track.Color(0,0,255) -#define COLOR4 track.Color(255,255,255) - -#define COLOR_RAMP track.Color(64,0,64) -#define COLOR_COIN track.Color(0,255,255) -#define COLOR_BOXMARKS track.Color(64,64,0) -#define LED_SEMAPHORE 12 - -#define CONTDOWN_PHASE_DURATION 2000 -#define CONTDOWN_STARTSOUND_DURATION 40 - -#define NEWRACE_DELAY 5000 - -#define REC_COMMAND_BUFLEN 32 // Received command buffer length -enum{ - MAX_CARS = 4, -}; - - - -enum loglevel { // used in Serial Protocol "!" command (send log/error messageS) - ECHO = 0, - DISABLE = 0, - LOG = 1, - WARNING = 2, - ERROR = 3 -}; - -enum resp{ - NOK = -1, - NOTHING = 0, - OK = 1 -}; - -typedef struct ack{ - enum resp rp; - char type; -}ack_t; - - - -struct cfgcircuit{ - int outtunnel; -}; - -enum phases{ - IDLE = 0, - CONFIG, - CONFIG_OK, - READY, - COUNTDOWN, - RACING, - PAUSE, - RESUME, - COMPLETE, - RACE_PHASES -}; - -struct race{ - struct cfgrace cfg; - struct cfgcircuit circ; - bool newcfg; - enum phases phase; - byte numcars; - int winner; -}; - - -byte SMOTOR=0; -int TBEEP=0; -int FBEEP=0; - -/*------------------------------------------------------*/ -enum loglevel verbose = DISABLE; - -static struct race race; -static car_t cars[ MAX_CARS ]; -static controller_t switchs[ MAX_CARS ]; -static track_t tck; - -static int const eeadrInfo = 0; - -char txbuff[64]; - - - - -static unsigned long lastmillis = 0; - -SoftTimer customDelay = SoftTimer(); // non blocking delay() - -// Used to manage countdown phases -int countdown_phase=1; -bool countdown_new_phase=true; - - -int win_music[] = { - 2637, 2637, 0, 2637, - 0, 2093, 2637, 0, - 3136 -}; - -//int TBEEP=3; - -char tracksID[ NUM_TRACKS ][2] ={"U","M","B","I","O"}; - -/* ----------- Function prototypes ------------------- */ - -void sendResponse( ack_t *ack); -//ack_t parseCommands(AsyncSerial &serial); - -ack_t manageSerialCommand(); - -void printdebug( const char * msg, int errlevel ); -void print_cars_positions( car_t* cars); -void run_racecycle( void ); -void draw_winner( track_t* tck, uint32_t color); - - -char cmd[REC_COMMAND_BUFLEN]; // Stores command received by ReadSerialComand() -SerialCommand serialCommand = SerialCommand(cmd, REC_COMMAND_BUFLEN, EOL, &Serial); // get complete command from serial - - -Adafruit_NeoPixel track; - - -/* - * - */ -void setup() { - - Serial.begin(115200); - randomSeed( analogRead(A6) + analogRead(A7) ); - controller_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 ); - - race.numcars = 2; - - if( controller_isActive( DIG_CONTROL_3 )) { - controller_init( &switchs[2], DIGITAL_MODE, DIG_CONTROL_3 ); - car_init( &cars[2], &switchs[2], COLOR3 ); - ++race.numcars; - } - - if( controller_isActive( DIG_CONTROL_4 )) { - controller_init( &switchs[3], DIGITAL_MODE, DIG_CONTROL_4 ); - car_init( &cars[3], &switchs[3], COLOR4 ); - ++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 || tck.cfg.track.box_alwaysOn ) { //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 ); - } else{ - track_configure( &tck, 0 ); - } - - if( digitalRead(DIG_CONTROL_1)==0 || tck.cfg.ramp.alwaysOn ) { //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 - 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; - - customDelay.start(0); // first race starts with no delay - race.phase = READY; -} - -/* - * - */ -void loop() { - - // look for commands received on serial - ack_t ack = manageSerialCommand(); - if(ack.rp != NOTHING){ - sendResponse(&ack); - } - - - // 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 - // string sent by the host is longer, it gets lost) - // In other phases (READY, RACING, etc) ONLY 2 bytes are guaranteed to be - // succesfully received - So "Enter Configuration Mode" command is just one byte (@) - - if ( race.phase == CONFIG ) { - if( race.newcfg ) { - race.newcfg = false; - countdownReset(); - customDelay.start(0); - race.phase = READY; - send_phase( race.phase ); - } - } - else if ( race.phase == READY ) { - - if(customDelay.elapsed()) { - for( int i = 0; i < race.numcars; ++i) { - car_resetPosition( &cars[i] ); - cars[i].repeats = 0; - } - tck.ledcoin = COIN_RESET; - race.phase = COUNTDOWN; - send_phase( race.phase ); - } - } - else if( race.phase == COUNTDOWN ) { - - if( race.cfg.startline ){ - // Countdown: semaphore and tones - if(start_race_done()) { - // Countdown done - for( int i = 0; i < race.numcars; ++i ) { - cars[i].st = CAR_ENTER; - } - race.phase = RACING; - send_phase( race.phase ); - } - } - } - else if( race.phase == RACING ) { - - strip_clear( &tck ); - - if( box_isactive( &tck ) ) { - if( tck.ledcoin == COIN_RESET ) { - tck.ledcoin = COIN_WAIT; - tck.ledtime = millis() + random(2000,7000); - } - if( tck.ledcoin > 0 ) - draw_coin( &tck ); - else if( millis() > tck.ledtime ) - tck.ledcoin = random( 20, tck.cfg.track.nled_aux - 20 ); - } - - if( ramp_isactive( &tck ) ) - draw_ramp( &tck ); - if( box_isactive( &tck ) ) - draw_box_entrypoint( &tck ); - - for( int i = 0; i < race.numcars; ++i ) { - run_racecycle( &cars[i], i ); - if( cars[i].st == CAR_FINISH ) { - race.phase = COMPLETE; - race.winner = i; - send_phase( race.phase ); - break; - } - } - - track.show(); - 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!!! */ - unsigned long nowmillis = millis(); - if( abs( nowmillis - lastmillis ) > 100 ){ - lastmillis = nowmillis; - print_cars_positions( cars ); - } - /* ---------------- */ - } - else if( race.phase == COMPLETE ) { - strip_clear( &tck ); - track.show(); - if ( race.cfg.finishline ){ - draw_winner( &tck, cars[race.winner].color ); - sound_winner( &tck, race.winner ); - strip_clear( &tck ); - } - track.show(); - customDelay.start(NEWRACE_DELAY); - race.phase = READY; - } - -} - -void send_phase( int phase ) { - sprintf(txbuff, "R%d%c",phase,EOL); - serialCommand.sendCommand(txbuff); -} - - -void run_racecycle( car_t *car, int i ) { - struct cfgtrack const* cfg = &tck.cfg.track; - - if( car->st == CAR_ENTER ) { - car_resetPosition( car ); - if( car->repeats < race.cfg.nrepeat ) - car->st = CAR_RACING; - else - car->st = CAR_GO_OUT; - } - - if( car->st == CAR_RACING ) { - update_track( &tck, car ); - car_updateController( car ); - draw_car( &tck, car ); - - if( car->nlap == race.cfg.nlap - && !car->leaving - && 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; - car->st = CAR_GO_OUT; - } - - if( car->repeats >= race.cfg.nrepeat - && race.cfg.finishline ) { - car->st = CAR_FINISH; - } - } - - if ( car->st == CAR_FINISH ){ - car->trackID = NOT_TRACK; - sprintf( txbuff, "w%d%c", i + 1, EOL ); - serialCommand.sendCommand(txbuff); - - car_resetPosition( car ); - } -} - - -int get_relative_position( car_t* car ) { - enum{ - MIN_RPOS = 0, - MAX_RPOS = 99, - }; - struct cfgtrack const* cfg = &tck.cfg.track; - int trackdist = 0; - int pos = 0; - - switch ( car->trackID ){ - case TRACK_MAIN: - trackdist = (int)car->dist % cfg->nled_main; - pos = map(trackdist, 0, cfg->nled_main -1, MIN_RPOS, MAX_RPOS); - break; - case TRACK_AUX: - trackdist = (int)car->dist_aux; - pos = map(trackdist, 0, cfg->nled_aux -1, MIN_RPOS, MAX_RPOS); - break; - } - return pos; -} - - -void print_cars_positions( car_t* cars ) { - - bool outallcar = true; - for( int i = 0; i < race.numcars; ++i) - outallcar &= cars[i].st == CAR_WAITING; - - if ( outallcar ) return; - - for( int i = 0; i < race.numcars; ++i ) { - int const rpos = get_relative_position( &cars[i] ); - sprintf( txbuff, "p%d%s%d,%d%c", i + 1, tracksID[cars[i].trackID], cars[i].nlap, rpos, EOL ); - serialCommand.sendCommand(txbuff); - } -} - - - - -/* - * non-blocking version - */ -boolean start_race_done( ) { - if(countdown_new_phase){ - countdown_new_phase=false; - customDelay.start(CONTDOWN_PHASE_DURATION); - strip_clear( &tck ); - if(ramp_isactive( &tck )) draw_ramp( &tck ); - if(box_isactive( &tck )) draw_box_entrypoint( &tck ); - switch(countdown_phase) { - case 1: - tone(PIN_AUDIO,400); - track.setPixelColor(LED_SEMAPHORE, track.Color(255,0,0)); - break; - case 2: - tone(PIN_AUDIO,600); - track.setPixelColor(LED_SEMAPHORE, track.Color(0,0,0)); - track.setPixelColor(LED_SEMAPHORE-1, track.Color(255,255,0)); - break; - case 3: - tone(PIN_AUDIO,1200); - track.setPixelColor(LED_SEMAPHORE-1, track.Color(0,0,0)); - track.setPixelColor(LED_SEMAPHORE-2, track.Color(0,255,0)); - break; - case 4: - customDelay.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)); - break; - case 5: - noTone(PIN_AUDIO); - countdownReset(); // reset for next countdown - return(true); - } - track.show(); - } - if(customDelay.elapsed()) { - noTone(PIN_AUDIO); - countdown_new_phase=true; - countdown_phase++; - } - return(false); -} - -/* - * - */ -void countdownReset() { - countdown_phase=1; - countdown_new_phase=true; -} - - -void sound_winner( track_t* tck, int winner ) { - int const msize = sizeof(win_music) / sizeof(int); - for (int note = 0; note < msize; note++) { - tone(PIN_AUDIO, win_music[note],200); - delay(230); - noTone(PIN_AUDIO); - } -} - - -void strip_clear( track_t* tck ) { - struct cfgtrack const* cfg = &tck->cfg.track; - for( int i=0; i < cfg->nled_main; i++) - track.setPixelColor( i, track.Color(0,0,0) ); - - for( int i=0; i < cfg->nled_aux; i++) - track.setPixelColor( cfg->nled_main+i, track.Color(0,0,0) ); -} - - -void draw_coin( track_t* tck ) { - struct cfgtrack const* cfg = &tck->cfg.track; - track.setPixelColor( 1 + cfg->nled_main + cfg->nled_aux - tck->ledcoin,COLOR_COIN ); -} - -void draw_winner( track_t* tck, uint32_t color) { - struct cfgtrack const* cfg = &tck->cfg.track; - for(int i=16; i < cfg->nled_main; i=i+(8 * cfg->nled_main / 300 )){ - track.setPixelColor( i , color ); - track.setPixelColor( i-16 ,0 ); - track.show(); - } -} - -void draw_car( track_t* tck, car_t* car ) { - struct cfgtrack const* cfg = &tck->cfg.track; - - switch ( car->trackID ){ - case TRACK_MAIN: - for(int i=0; i<= car->nlap; ++i ) - track.setPixelColor( ((word)car->dist % cfg->nled_main) + i, car->color ); - break; - case TRACK_AUX: - for(int i=0; i<= car->nlap; ++i ) - track.setPixelColor( (word)(cfg->nled_main + cfg->nled_aux - car->dist_aux) + i, car->color); - break; - } -} - - -/* - * Display on LED Strip current values for Slope and Pitlane - * - */ -void show_cfgpars_onstrip(){ - strip_clear( &tck ); - if( ramp_isactive( &tck ) ) - draw_ramp( &tck ); - if( box_isactive( &tck ) ) - draw_box_entrypoint( &tck ); - track.show(); -} - - -/* - * - */ -void draw_ramp( track_t* _tck ) { - struct cfgramp const* r = &_tck->cfg.ramp; - byte dist = 0; - byte intensity = 0; - for( int i = r->init; i <= r->center; ++i ) { - dist = r->center - r->init; - intensity = ( 32 * (i - r->init) ) / dist; - track.setPixelColor( i, track.Color( intensity,0,intensity ) ); - } - for( int i = r->center; i <= r->end; ++i ) { - dist = r->end - r->center; - intensity = ( 32 * ( r->end - i ) ) / dist; - track.setPixelColor( i, track.Color( intensity,0,intensity ) ); - } -} - - -/* - * - */ -void draw_box_entrypoint( track_t* _tck ) { - struct cfgtrack const* cfg = &_tck->cfg.track; - int out = cfg->nled_total - cfg->box_len; // Pit lane exit (race start) - int in = out - cfg->box_len; // Pit lane Entrance - track.setPixelColor(in ,COLOR_BOXMARKS ); - track.setPixelColor(out ,COLOR_BOXMARKS ); -} - - - -/* - * Check Serial to see if there is a command ready to be processed - * - */ -ack_t manageSerialCommand() { - - ack_t ack = { .rp = NOTHING, .type = '\0' }; - - int clen = serialCommand.getCommand(); - - - if(clen == 0) { - // No commands received - return ack; - } else if(clen < 0) { - // Error receiving command - sprintf( txbuff, "Error reading serial command:[%d]",clen); - printdebug( txbuff, WARNING ); - } - - // clen > 0 ---> Command with length=clen stored in cmd[]. - - ack.rp=NOK; - - - if( cmd[0] == '#' ) { - ack.type = cmd[0]; - sprintf( txbuff, "#%c", EOL ); - serialCommand.sendCommand(txbuff); - ack.rp = NOTHING; - } - - else if( cmd[0] == '@' ) { // Enter "Configuration Mode" status - ack.type = cmd[0]; - if(race.phase == CONFIG) { // Board already in "Configure Mode" - ; // ignore command (will return @OK) - } else { - race.phase = CONFIG; - enter_configuration_mode(); - } - ack.rp = OK; - } - - else if( cmd[0] == '~' ) { // Exit "Configure Mode" - ack.type = cmd[0]; - if(race.phase == CONFIG) { - race.newcfg = true; - } else { // Board NOT in configuration mode - ; // ignore command (will return ~OK) - } - ack.rp = OK; - - } - - else if( cmd[0] == 'R' ) { - ack.type = cmd[0]; - int const phase = atoi( cmd + 1); - if( 0 > phase || RACE_PHASES <= phase) return ack; - race.phase = (enum phases) phase; - ack.rp = OK; - if ( race.phase == CONFIG ) { // accept R1 as a EnterConfigurationMode command - DEPRECATED - enter_configuration_mode(); - } - } - - else if( cmd[0] == 'C' ) { //Parse race configuration -> C1,2,3,0 - ack.type = cmd[0]; - - char * pch = strtok (cmd,"C"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int startline = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int nlap = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int nrepeat = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - //cfg.finishline = atoi( pch ); - int finishline = atoi( pch ); - - int err = race_configure( &tck, startline, nlap, nrepeat, finishline); - if( err ) return ack; - - race.cfg.startline = tck.cfg.race.startline; - race.cfg.nlap = tck.cfg.race.nlap; - race.cfg.nrepeat = tck.cfg.race.nrepeat; - race.cfg.finishline = tck.cfg.race.finishline; - - ack.rp = OK; - } - - else if( cmd[0] == 'T' ) { //Parse Track configuration -> Track length - ack.type = cmd[0]; - - char * pch = strtok (cmd,"T"); - if( !pch ) return ack; - - int nled = atoi( cmd + 1 ); - int err = tracklen_configure( &tck, nled); - if( err ) return ack; - track_configure( &tck, 0); - if( err ) return ack; - - ack.rp = OK; - } - - else if( cmd[0] == 'B' ) { //Parse BoxLenght Configuration -> Alen,perm - ack.type = cmd[0]; - - char * pch = strtok (cmd,"B"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int boxlen = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int boxperm = atoi( pch ); - - int err = boxlen_configure( &tck, boxlen, boxperm ); - if( err ) return ack; - - ack.rp = OK; - - // Force Pitlane ON, so "show_cfgpars_onstrip()" - // will show the new values, even if AlwaysON=false - box_init(&tck); - show_cfgpars_onstrip(); - } - - else if( cmd[0] == 'A' ) { // Parse Ramp configuration -> Astart,center,end,high,perm - ack.type = cmd[0]; - - char * pch = strtok (cmd,"A"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int init = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int center = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int end = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int high = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int slopeperm = atoi( pch ); - - int err = ramp_configure( &tck, init, center, end, high, slopeperm ); - if( err ) return ack; - ack.rp = OK; - - // Force Ramp ON, so "show_cfgpars_onstrip()" - // will show the new values, even if AlwaysON=false - ramp_init(&tck); - - show_cfgpars_onstrip(); - } - - else if( cmd[0] == 'K' ) { // Parse Physic simulation parameters - ack.type = cmd[0]; - - char * pch = strtok (cmd,"K"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - float kgp = atof( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - float kfp = atof( pch ); - - int err = physic_configure( &tck, kgp, kfp ); - if( err ) return ack; - - ack.rp = OK; - } - - else if( cmd[0] == 'D') { - ack.type = cmd[0]; - param_setdefault( &tck.cfg ); - EEPROM.put( eeadrInfo, tck.cfg ); // Save immediately - - printdebug( "Load default parameter values", LOG ); - - ack.rp = OK; - - // Update box/slope active in current Track Struct with values - // just loaded (for show_cfgpars_onstrip()) - struct cfgparam const* cfg = &tck.cfg; - tck.boxactive = cfg->track.box_alwaysOn; - tck.rampactive = cfg->ramp.alwaysOn; - - show_cfgpars_onstrip(); - - } - - else if( cmd[0] == ':' ) { // Set board Unique Id - struct brdinfo* info = &tck.cfg.info; - ack.type = cmd[0]; - if( strlen(cmd + 1) > LEN_UID ) return ack; - strcpy( info->uid, cmd + 1 ); - EEPROM.put( eeadrInfo, tck.cfg ); // Save immediately - ack.rp = OK; - } - - else if( cmd[0] == '$' ) { // Get Board UID - sprintf( txbuff, "%s%s%c", "$", tck.cfg.info.uid, EOL ); - serialCommand.sendCommand(txbuff); - ack.rp = NOTHING; - } - - else if( cmd[0] == '?' ) { // Get Software Id - sprintf( txbuff, "%s%s%c", "?", softwareId, EOL ); - serialCommand.sendCommand(txbuff); - ack.rp = NOTHING; - } - - else if( cmd[0] == '%' ) { // Get Software Version - sprintf( txbuff, "%s%s%c", "%", version, EOL ); - serialCommand.sendCommand(txbuff); - ack.rp = NOTHING; - } - - else if( cmd[0] == 'Q' ) { // Get configuration Info - struct cfgparam const* cfg = &tck.cfg; - - sprintf( txbuff, "%s:%d,%d,%d,%d,%d,%d,%d.%03d,%d.%03d%c", "QTRACK", - cfg->track.nled_total, - cfg->track.nled_main, - cfg->track.nled_aux, - cfg->track.init_aux, - cfg->track.box_len, - cfg->track.box_alwaysOn, - (int)cfg->track.kg, (int)(cfg->track.kg*1000)%1000, // std arduino sprintf() missing %f - (int)cfg->track.kf, (int)(cfg->track.kf*1000)%1000, // std arduino sprintf() missing %f - EOL ); - - serialCommand.sendCommand(txbuff); - - sprintf( txbuff, "%s:%d,%d,%d,%d,%d%c", "QRAMP", - cfg->ramp.init, - cfg->ramp.center, - cfg->ramp.end, - cfg->ramp.high, - cfg->ramp.alwaysOn, - EOL ); - serialCommand.sendCommand(txbuff); - - sprintf( txbuff, "%s:%d,%d,%d,%d%c", "QRACE", - cfg->race.startline, - cfg->race.nlap, - cfg->race.nrepeat, - cfg->race.finishline, - EOL ); - serialCommand.sendCommand(txbuff); - - ack.rp = NOTHING; - } - - else if( cmd[0] == 'W' ) { // Write configuration to EEPROM - ack.type = cmd[0]; - EEPROM.put( eeadrInfo, tck.cfg ); - ack.rp = OK; - } - - return(ack); - -} - -/* - * - */ -void sendResponse( ack_t *ack) { - if(ack->type=='\0'){ - sprintf(txbuff, "%s%c", ack->rp==OK? "OK":"NOK" , EOL ); - } else { - sprintf(txbuff, "%c%s%c", ack->type, ack->rp==OK? "OK":"NOK" , EOL ); - } - serialCommand.sendCommand(txbuff); -} - -/* - * Send Log/Warning/Error messages to host - */ -void printdebug( const char * msg, int errlevel ) { - char tmp [80]; - sprintf( tmp, "!%d,%s%c",errlevel, msg, EOL ); - serialCommand.sendCommand(tmp); -} - - -/* - * reset race parameters - * stop sound - */ -void enter_configuration_mode(){ - noTone(PIN_AUDIO); - strip_clear( &tck ); - track.show(); -} - - - - -void param_load( struct cfgparam* cfg ) { - int cfgversion; - int eeAdress = eeadrInfo; - EEPROM.get( eeAdress, tck.cfg ); - eeAdress += sizeof( cfgparam ); - EEPROM.get( eeAdress, cfgversion ); - - sprintf( txbuff, "%s:%d%c", "Parameters Loaded from EEPROM - Cfg ver", cfgversion, EOL ); -//Serial.print(txbuff); - serialCommand.sendCommand(txbuff); - - - if ( cfgversion != CFG_VER ) { - param_setdefault( &tck.cfg ); - eeAdress = 0; - EEPROM.put( eeAdress, tck.cfg ); - eeAdress += sizeof( cfgparam ); - EEPROM.put( eeAdress, CFG_VER ); - sprintf( txbuff, "%s%c", "DEFAULT PAREMETRS LOADED (and Stored in EEPROM)", EOL ); - serialCommand.sendCommand(txbuff); - - } - -} diff --git a/open-led-race_OK/olr-controller.c b/open-led-race_OK/olr-controller.c deleted file mode 100644 index 1b8e55c..0000000 --- a/open-led-race_OK/olr-controller.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "olr-controller.h" - -enum { - DELTA_ANALOG = 5, -}; - -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); -} - -void controller_init( controller_t* ct, enum ctr_type mode, int pin ) { - ct->mode = mode; - ct->pin = pin; - ct->delta_analog = DELTA_ANALOG; -} - - -byte controller_getStatus( controller_t* ct ) { - - if( ct->mode == DIGITAL_MODE ){ - return digitalRead( ct->pin ); - } - else if( ct->mode == ANALOG_MODE ){ - ct->adc = analogRead( ct->pin ); - if( abs( ct->badc - ct->adc ) > ct->delta_analog ){ - ct->badc = ct->adc; - return 1; - } - ct->badc = ct->adc; - } - else if( ct->mode == DEBUG_MODE ){ - ct->adc++; - if( ct->adc >= 60){ - ct->adc = 0; - return 1; - } - } - return 0; - -} - - -float controller_getSpeed( controller_t* ct) { - float speed = 0.0; - if ( (ct->flag_sw == 1 ) && (controller_getStatus( ct ) == 0) ) { - ct->flag_sw = 0; - speed = ACEL; - } - - if ( (ct->flag_sw == 0 ) && (controller_getStatus( ct ) == 1 ) ) { - ct->flag_sw = 1; - } - return speed; -} - -float controller_getAccel ( void ) { - return ACEL; -} - -bool controller_isActive( int pin ) { - return !digitalRead( pin ); -} diff --git a/open-led-race_OK/olr-controller.h b/open-led-race_OK/olr-controller.h deleted file mode 100644 index 87fad3a..0000000 --- a/open-led-race_OK/olr-controller.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _OLR_CONTROLLER_LIB_h -#define _OLR_CONTROLLER_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include "Arduino.h" -#include -#include - - -#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{ - NOT_DEFINED = 0, - DIGITAL_MODE, - ANALOG_MODE, - DEBUG_MODE, -}; - -typedef struct{ - enum ctr_type mode; - int pin; - int adc; - int badc; - int delta_analog; - byte flag_sw; -}controller_t; - -void controller_setup( void ); - -void controller_init( controller_t* ct, enum ctr_type mode, int pin ); - -byte controller_getStatus( controller_t* ct ); - -float controller_getSpeed( controller_t* ct ); - -float controller_getAccel ( void ); - -bool controller_isActive( int pin ); - - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - diff --git a/open-led-race_OK/olr-lib.c b/open-led-race_OK/olr-lib.c deleted file mode 100644 index 653fed8..0000000 --- a/open-led-race_OK/olr-lib.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "Arduino.h" -#include "olr-lib.h" - - - -void car_init( car_t* car, controller_t* ct, uint32_t color ) { - car->ct = ct; - car->color = color; - car->trackID = TRACK_MAIN; - car->speed=0; - car->dist=0; - car->dist_aux=0; -} - -void car_updateController( car_t* car ) { - car->speed += controller_getSpeed( car->ct ); -} - -void update_track( track_t* tck, car_t* car ) { - controller_t* ct = car->ct; - struct cfgtrack const* cfg = &tck->cfg.track; - - - if ( car->trackID == TRACK_MAIN - && (int)car->dist % cfg->nled_main == (cfg->init_aux-(cfg->nled_aux)) - // && controller_getStatus( ct ) == 0 ) { //change track by switch - && (car->speed <= SPD_MIN_TRACK_AUX )) { //change track by low speed - - car->trackID = TRACK_AUX; - car->dist_aux = 0; - } - else if( car->trackID == TRACK_AUX - && car->dist_aux > cfg->nled_aux ) { - - car->trackID = TRACK_MAIN; - car->dist += cfg->nled_aux; - } - - /* Update car position in the current track */ - if ( car->trackID == TRACK_AUX ) process_aux_track( tck, car ); - else if ( car->trackID == TRACK_MAIN ) process_main_track( tck, car ); - - /* Update car lap */ - if ( car->dist > ( cfg->nled_main*car->nlap -1) ) car->nlap++; -} - -void process_aux_track( track_t* tck, car_t* car ){ - struct cfgtrack const* cfg = &tck->cfg.track; - - if ( (int)car->dist_aux == tck->ledcoin - && car->speed <= controller_getAccel() ) { - car->speed = controller_getAccel ()*50; - tck->ledcoin = COIN_RESET; - }; - - car->speed -= car->speed * cfg->kf; - car->dist_aux += car->speed; -} - - -void process_main_track( track_t* tck, car_t* car ) { - struct cfgtrack const* cfg = &tck->cfg.track; - - if ( tck->rampactive ) { - struct cfgramp const* r = &tck->cfg.ramp; - int const pos = (int)car->dist % cfg->nled_main; - if ( pos >= r->init && pos < r->center ) - // car->speed -= cfg->kg * r->high * ( pos - r->init ); - car->speed -= cfg->kg * r->high ; - - if ( pos <= r->end && pos > r->center ) - //car->speed += cfg->kg * r->high * ( pos - r->center ); - car->speed += cfg->kg * r->high ; - } - - car->speed -= car->speed * cfg->kf; - car->dist += car->speed; - -} - -void ramp_init( track_t* tck ) { - tck->rampactive = true; -} - - -bool ramp_isactive( track_t* tck ) { - return tck->rampactive; -} - - -void car_resetPosition( car_t* car) { - - car->trackID = TRACK_MAIN; - car->speed = 0; - car->dist = 0; - car->dist_aux = 0; - car->nlap = 1; - car->leaving = false; -} - -void box_init( track_t* tck ) { - tck->boxactive = true; -} - -bool box_isactive( track_t* tck ) { - return tck->boxactive; -} - - - -int tracklen_configure( track_t* tck, int nled ) { - struct cfgtrack* cfg = &tck->cfg.track; - if( nled <= 0 ) return -1; - cfg->nled_total = nled; - return 0; -} - -int boxlen_configure( track_t* tck, int box_len, int boxalwaysOn ) { - struct cfgtrack* cfg = &tck->cfg.track; - - if ( boxalwaysOn != 0 && boxalwaysOn != 1 ) return -1; - if( box_len <= 0 || box_len >= cfg->nled_total ) return -1; - cfg->box_len = box_len; - cfg->box_alwaysOn = boxalwaysOn; - - // Update track->boxactive - tck->boxactive = boxalwaysOn; - return 0; -} - -int physic_configure( track_t* tck, float kgp, float kfp ){ - struct cfgtrack* cfg = &tck->cfg.track; - - if( kgp <= 0.0 || kgp >= 2.0 ) return -1; - if( kfp <= 0.0 || kfp >= 2.0 ) return -1; - cfg->kf = kfp; - cfg->kg = kgp; - return(0); -} - - - -int track_configure( track_t* tck, int init_box ) { - struct cfgtrack* cfg = &tck->cfg.track; - - if(init_box >= cfg->nled_total ) return -1; - cfg->nled_main = ( init_box == 0 ) ? cfg->nled_total : init_box; - cfg->nled_aux = ( init_box == 0 ) ? 0 : cfg->nled_total - init_box; - cfg->init_aux = init_box - 1; - return 0; -} - - -int ramp_configure( track_t* tck, int init, int center, int end, int high, int alwaysOn ) { - struct cfgramp* ramp = &tck->cfg.ramp; - - if ( init >= tck->cfg.track.nled_main || init <= 0 ) return -1; - if ( center >= tck->cfg.track.nled_main || center <= 0 ) return -2; - if ( end >= tck->cfg.track.nled_main || end <= 0 ) return -3; - if ( ! (center > init && center < end) ) return -4; - if ( alwaysOn != 0 && alwaysOn != 1 ) return -5; - - ramp->init = init; - ramp->center = center; - ramp->end = end; - ramp->high = high; - ramp->alwaysOn = alwaysOn; - - // Update track->rampactive - /** - boolean rampactive = &tck->rampactive; - rampactive = alwaysOn; - **/ - tck->rampactive = alwaysOn; - - return 0; -} - -int race_configure( track_t* tck, int startline, int nlap, int nrepeat, int finishline ) { - struct cfgrace* race = &tck->cfg.race; - - if ( startline != 0 && startline != 1 ) return -1; - if ( finishline != 0 && finishline != 1 ) return -1; - race->startline = startline; - race->finishline = finishline; - race->nlap = nlap; - race->nrepeat = nrepeat; - return 0; -} diff --git a/open-led-race_OK/olr-lib.h b/open-led-race_OK/olr-lib.h deleted file mode 100644 index 81f84e8..0000000 --- a/open-led-race_OK/olr-lib.h +++ /dev/null @@ -1,103 +0,0 @@ - -#ifndef _OLR_LIB_h -#define _OLR_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include -#include -#include -#include "olr-controller.h" -#include "olr-param.h" - -#define SPD_MIN_TRACK_AUX 0.8 - -enum stcoin{ - COIN_RESET = -2, - COIN_WAIT = -1, -}; - -enum{ - NOT_TRACK = 0, - TRACK_MAIN, - TRACK_AUX, - TRACK_IN, - TRACK_OUT, - NUM_TRACKS, -}; - - -enum status{ - CAR_WAITING = 0, - CAR_COMING, - CAR_ENTER, - CAR_RACING, - CAR_LEAVING, - CAR_GO_OUT, - CAR_FINISH -}; - -typedef struct{ - controller_t* ct; - float speed; - float dist; - float dist_aux; - byte nlap; - byte repeats; - uint32_t color; - int trackID; - enum status st; - bool leaving; -}car_t; - - - -typedef struct { - struct cfgparam cfg; - int ledcoin; //LED_SPEED_COIN - uint32_t ledtime; - bool rampactive; - bool boxactive; -}track_t; - - -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 update_track( track_t* tck, car_t* car ); - -void process_main_track( track_t* tck, car_t* car ); - -void process_aux_track( track_t* tck, car_t* car ); - -void box_init( track_t* tck ); - -bool box_isactive( track_t* tck ); - -int tracklen_configure( track_t* tck, int nled ); - -int boxlen_configure( track_t* tck, int box_len, int boxalwaysOn ); - -int physic_configure( track_t* tck, float kgp, float kfp ); - -int track_configure( track_t* tck, int init_box ); - -void ramp_init( track_t* tck ); - -bool ramp_isactive( track_t* tck ); - -int ramp_configure( track_t* tck, int init, int center, int end, int high, int alwaysOn ); - -int race_configure( track_t* tck, int startline, int nlap, int nrepeat, int finishline ); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/open-led-race_OK/olr-param.c b/open-led-race_OK/olr-param.c deleted file mode 100644 index 81290ab..0000000 --- a/open-led-race_OK/olr-param.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "olr-param.h" - -void param_setdefault( struct cfgparam* cfg ) { - cfg->setted = true; - - cfg->race.startline = true; - cfg->race.nlap = NUMLAP; - cfg->race.nrepeat = 1; - cfg->race.finishline = true; - - cfg->ramp.init = 80; - cfg->ramp.center = 90; - cfg->ramp.end = 100; - cfg->ramp.high = 6; - cfg->ramp.alwaysOn = false; - - cfg->track.nled_total = MAXLED; - cfg->track.nled_main = MAXLED; // 240 when boxes length = 60 - cfg->track.nled_aux = 0; // 60 - cfg->track.init_aux = -1; // 239 - cfg->track.box_len = BOXLEN; - cfg->track.box_alwaysOn = false; - - cfg->track.kf = 0.015; // friction constant - cfg->track.kg = 0.006; // gravity constant - Used in Slope -} diff --git a/open-led-race_OK/olr-param.h b/open-led-race_OK/olr-param.h deleted file mode 100644 index 3535077..0000000 --- a/open-led-race_OK/olr-param.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _OLR_PARAM_LIB_h -#define _OLR_PARAM_LIB_h - -#ifdef __cplusplus - -extern "C"{ -#endif - -#include "Arduino.h" -#include -#include - -#define MAXLED 300 -#define BOXLEN 60 -#define NUMLAP 5 - - - -enum{ - LEN_UID = 16, - CFG_VER = 5, // "5" in V0.9.6 (manage "permanent" param for Box and Slope) -}; - -struct cfgrace{ - bool startline; // Used only in OLRNetwork - int nlap; - int nrepeat; // Used only in OLRNetwork - bool finishline; // Used only in OLRNetwork -}; - -// -struct cfgtrack { - int nled_total; - int nled_main; - int nled_aux; - int init_aux; - int box_len; // used to hold the Box Length if the default get changed. - // it's not possible to implicitly store it in nled_main,nled_aux - // because, if these are different to the default, box gets always activated - // (the software does not chek "box_isactive" to draw car position) - bool box_alwaysOn; // added in ver 0.9.6 - - - float kf; - float kg; -}; - -// ramp centred in LED 100 with 10 led fordward and 10 backguard -struct cfgramp { - int init; - int center; - int end; - int high; - bool alwaysOn; // added in ver 0.9.6 -}; - -struct brdinfo { - char uid[LEN_UID + 1]; -}; - -struct cfgparam { - bool setted; - struct cfgrace race; // added in ver 0.9.d - struct cfgtrack track; - struct cfgramp ramp; - struct brdinfo info; -}; - - -void param_setdefault( struct cfgparam* cfg ); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - diff --git a/open-led-race_OK/open-led-race_OK.ino b/open-led-race_OK/open-led-race_OK.ino deleted file mode 100644 index f306f3c..0000000 --- a/open-led-race_OK/open-led-race_OK.ino +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * ____ _ ______ _____ _____ - / __ \ | | | ____| __ \ | __ \ - | | | |_ __ ___ _ __ | | | |__ | | | | | |__) |__ _ ___ ___ - | | | | '_ \ / _ \ '_ \ | | | __| | | | | | _ // _` |/ __/ _ \ - | |__| | |_) | __/ | | | | |____| |____| |__| | | | \ \ (_| | (_| __/ - \____/| .__/ \___|_| |_| |______|______|_____/ |_| \_\__,_|\___\___| - | | - |_| - Open LED Race - An minimalist cars race for LED strip - - 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. - - - First public version by: - Angel Maldonado (https://gitlab.com/angeljmc) - Gerardo Barbarov (gbarbarov AT singulardevices DOT com) - - Basen on original idea and 2 players code by: - Gerardo Barbarov for Arduino day Seville 2019 - https://github.com/gbarbarov/led-race - - - Public Repository for this code: - https://gitlab.com/open-led-race/olr-arduino - -*/ - - -// 2020/12/10 - Ver 0.9.6 -// --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.6"; - - - -#include -#include -#include "olr-lib.h" -#include "olr-param.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_AUDIO 3 // through CAP 2uf to speaker 8 ohms - -#define REC_COMMAND_BUFLEN 32 -#define EOL '\n' // End of Command char used in Protocol - -#define COLOR1 track.Color(255,0,0) -#define COLOR2 track.Color(0,255,0) -#define COLOR3 track.Color(0,0,255) -#define COLOR4 track.Color(255,255,255) - -#define COLOR_RAMP track.Color(64,0,64) -#define COLOR_COIN track.Color(0,255,255) -#define COLOR_BOXMARKS track.Color(64,64,0) -#define LED_SEMAPHORE 12 - -#define CONTDOWN_PHASE_DURATION 2000 -#define CONTDOWN_STARTSOUND_DURATION 40 - -#define NEWRACE_DELAY 5000 - -enum{ - MAX_CARS = 4, -}; - - - -enum loglevel { // used in Serial Protocol "!" command (send log/error messageS) - ECHO = 0, - DISABLE = 0, - LOG = 1, - WARNING = 2, - ERROR = 3 -}; - - -enum resp{ - NOK = -1, - NOTHING = 0, - OK = 1 -}; - -typedef struct ack{ - enum resp rp; - char type; -}ack_t; - - - -struct cfgcircuit{ - int outtunnel; -}; - -enum phases{ - IDLE = 0, - CONFIG, - CONFIG_OK, - READY, - COUNTDOWN, - RACING, - PAUSE, - RESUME, - COMPLETE, - RACE_PHASES -}; - -struct race{ - struct cfgrace cfg; - struct cfgcircuit circ; - bool newcfg; - enum phases phase; - byte numcars; - int winner; -}; - - -byte SMOTOR=0; -int TBEEP=0; -int FBEEP=0; - -/*------------------------------------------------------*/ -enum loglevel verbose = DISABLE; - -static struct race race; -static car_t cars[ MAX_CARS ]; -static controller_t switchs[ MAX_CARS ]; -static track_t tck; - -static int const eeadrInfo = 0; - -char txbuff[64]; - - - - -static unsigned long lastmillis = 0; - -//SoftTimer customDelay = SoftTimer(); // non blocking delay() - -// Used to manage countdown phases -int countdown_phase=1; -bool countdown_new_phase=true; - - -int win_music[] = { - 2637, 2637, 0, 2637, - 0, 2093, 2637, 0, - 3136 -}; - -//int TBEEP=3; - -char tracksID[ NUM_TRACKS ][2] ={"U","M","B","I","O"}; - -/* ----------- Function prototypes ------------------- */ - -void sendResponse( ack_t *ack); - -ack_t manageSerialCommand(); - -void printdebug( const char * msg, int errlevel ); -void print_cars_positions( car_t* cars); -void run_racecycle( void ); -void draw_winner( track_t* tck, uint32_t color); - -char cmdbuf[REC_COMMAND_BUFLEN]; // Stores command received by ReadSerialComand() - - -Adafruit_NeoPixel track; - - -/* - * - */ -void setup() { - - Serial.begin(115200); - randomSeed( analogRead(A6) + analogRead(A7) ); - controller_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 ); - - race.numcars = 2; - - if( controller_isActive( DIG_CONTROL_3 )) { - controller_init( &switchs[2], DIGITAL_MODE, DIG_CONTROL_3 ); - car_init( &cars[2], &switchs[2], COLOR3 ); - ++race.numcars; - } - - if( controller_isActive( DIG_CONTROL_4 )) { - controller_init( &switchs[3], DIGITAL_MODE, DIG_CONTROL_4 ); - car_init( &cars[3], &switchs[3], COLOR4 ); - ++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 || tck.cfg.track.box_alwaysOn ) { //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 ); - } else{ - track_configure( &tck, 0 ); - } - - if( digitalRead(DIG_CONTROL_1)==0 || tck.cfg.ramp.alwaysOn ) { //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 - 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; - - customDelayStart(0); // first race starts with no delay - race.phase = READY; -} - -/* - * - */ -void loop() { - - // look for commands received on serial - ack_t ack = manageSerialCommand(); - if(ack.rp != NOTHING){ - sendResponse(&ack); - } - - // 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 - // string sent by the host is longer, it gets lost) - // In other phases (READY, RACING, etc) ONLY 2 bytes are guaranteed to be - // succesfully received - So "Enter Configuration Mode" command is just one byte (@) - - switch(race.phase) { - - case CONFIG: - { - if( race.newcfg ) { - race.newcfg = false; - countdownReset(); - customDelayStart(0); - race.phase = READY; - send_phase( race.phase ); - } - } - break; - - case READY: - { - if(customDelayElapsed()) { - for( int i = 0; i < race.numcars; ++i) { - car_resetPosition( &cars[i] ); - cars[i].repeats = 0; - } - tck.ledcoin = COIN_RESET; - race.phase = COUNTDOWN; - send_phase( race.phase ); - } - } - break; - - case COUNTDOWN: - { - if( race.cfg.startline ){ - // Countdown: semaphore and tones - if(start_race_done()) { - // Countdown done - for( int i = 0; i < race.numcars; ++i ) { - cars[i].st = CAR_ENTER; - } - race.phase = RACING; - send_phase( race.phase ); - } - } - } - break; - - case RACING: - { - strip_clear( &tck ); - - if( box_isactive( &tck ) ) { - if( tck.ledcoin == COIN_RESET ) { - tck.ledcoin = COIN_WAIT; - tck.ledtime = millis() + random(2000,7000); - } - if( tck.ledcoin > 0 ) - draw_coin( &tck ); - else if( millis() > tck.ledtime ) - tck.ledcoin = random( 20, tck.cfg.track.nled_aux - 20 ); - } - - if( ramp_isactive( &tck ) ) - draw_ramp( &tck ); - if( box_isactive( &tck ) ) - draw_box_entrypoint( &tck ); - - for( int i = 0; i < race.numcars; ++i ) { - run_racecycle( &cars[i], i ); - if( cars[i].st == CAR_FINISH ) { - race.phase = COMPLETE; - race.winner = i; - send_phase( race.phase ); - break; - } - } - - track.show(); - 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!!! - unsigned long nowmillis = millis(); - if( abs( nowmillis - lastmillis ) > 100 ){ - lastmillis = nowmillis; - print_cars_positions( cars ); - } - // ---------------- - } - break; - - case COMPLETE : - { - strip_clear( &tck ); - track.show(); - if ( race.cfg.finishline ){ - draw_winner( &tck, cars[race.winner].color ); - sound_winner( &tck, race.winner ); - strip_clear( &tck ); - } - track.show(); - customDelayStart(NEWRACE_DELAY); - race.phase = READY; - } - break; - - default: - { - sprintf( txbuff, "Software Error in main loop switch()"); - printdebug( txbuff, WARNING ); - break; - } - - } // switch - -} - -void send_phase( int phase ) { - sprintf(txbuff, "R%d%c",phase,EOL); - sendCommand(txbuff); -} - - -void run_racecycle( car_t *car, int i ) { - struct cfgtrack const* cfg = &tck.cfg.track; - - if( car->st == CAR_ENTER ) { - car_resetPosition( car ); - if( car->repeats < race.cfg.nrepeat ) - car->st = CAR_RACING; - else - car->st = CAR_GO_OUT; - } - - if( car->st == CAR_RACING ) { - update_track( &tck, car ); - car_updateController( car ); - draw_car( &tck, car ); - - if( car->nlap == race.cfg.nlap - && !car->leaving - && 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; - car->st = CAR_GO_OUT; - } - - if( car->repeats >= race.cfg.nrepeat - && race.cfg.finishline ) { - car->st = CAR_FINISH; - } - } - - 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 ); - } -} - - -int get_relative_position( car_t* car ) { - enum{ - MIN_RPOS = 0, - MAX_RPOS = 99, - }; - struct cfgtrack const* cfg = &tck.cfg.track; - int trackdist = 0; - int pos = 0; - - switch ( car->trackID ){ - case TRACK_MAIN: - trackdist = (int)car->dist % cfg->nled_main; - pos = map(trackdist, 0, cfg->nled_main -1, MIN_RPOS, MAX_RPOS); - break; - case TRACK_AUX: - trackdist = (int)car->dist_aux; - pos = map(trackdist, 0, cfg->nled_aux -1, MIN_RPOS, MAX_RPOS); - break; - } - return pos; -} - - -void print_cars_positions( car_t* cars ) { - - bool outallcar = true; - for( int i = 0; i < race.numcars; ++i) - outallcar &= cars[i].st == CAR_WAITING; - - if ( outallcar ) return; - - for( int i = 0; i < race.numcars; ++i ) { - int const rpos = get_relative_position( &cars[i] ); - sprintf( txbuff, "p%d%s%d,%d%c", i + 1, tracksID[cars[i].trackID], cars[i].nlap, rpos, EOL ); - //serialCommand.sendCommand(txbuff); - sendCommand(txbuff); - } -} - - - - -/* - * non-blocking version - */ -boolean start_race_done( ) { - if(countdown_new_phase){ - countdown_new_phase=false; - //customDelay.start(CONTDOWN_PHASE_DURATION); - customDelayStart(CONTDOWN_PHASE_DURATION); - strip_clear( &tck ); - if(ramp_isactive( &tck )) draw_ramp( &tck ); - if(box_isactive( &tck )) draw_box_entrypoint( &tck ); - switch(countdown_phase) { - case 1: - tone(PIN_AUDIO,400); - track.setPixelColor(LED_SEMAPHORE, track.Color(255,0,0)); - break; - case 2: - tone(PIN_AUDIO,600); - track.setPixelColor(LED_SEMAPHORE, track.Color(0,0,0)); - track.setPixelColor(LED_SEMAPHORE-1, track.Color(255,255,0)); - break; - case 3: - tone(PIN_AUDIO,1200); - track.setPixelColor(LED_SEMAPHORE-1, track.Color(0,0,0)); - track.setPixelColor(LED_SEMAPHORE-2, track.Color(0,255,0)); - break; - case 4: - //customDelay.start(CONTDOWN_STARTSOUND_DURATION); - customDelayStart(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)); - break; - case 5: - noTone(PIN_AUDIO); - countdownReset(); // reset for next countdown - return(true); - } - track.show(); - } - if(customDelayElapsed()) { - noTone(PIN_AUDIO); - countdown_new_phase=true; - countdown_phase++; - } - return(false); -} - -/* - * - */ -void countdownReset() { - countdown_phase=1; - countdown_new_phase=true; -} - - -void sound_winner( track_t* tck, int winner ) { - int const msize = sizeof(win_music) / sizeof(int); - for (int note = 0; note < msize; note++) { - tone(PIN_AUDIO, win_music[note],200); - delay(230); - noTone(PIN_AUDIO); - } -} - - -void strip_clear( track_t* tck ) { - struct cfgtrack const* cfg = &tck->cfg.track; - for( int i=0; i < cfg->nled_main; i++) - track.setPixelColor( i, track.Color(0,0,0) ); - - for( int i=0; i < cfg->nled_aux; i++) - track.setPixelColor( cfg->nled_main+i, track.Color(0,0,0) ); -} - - -void draw_coin( track_t* tck ) { - struct cfgtrack const* cfg = &tck->cfg.track; - track.setPixelColor( 1 + cfg->nled_main + cfg->nled_aux - tck->ledcoin,COLOR_COIN ); -} - -void draw_winner( track_t* tck, uint32_t color) { - struct cfgtrack const* cfg = &tck->cfg.track; - for(int i=16; i < cfg->nled_main; i=i+(8 * cfg->nled_main / 300 )){ - track.setPixelColor( i , color ); - track.setPixelColor( i-16 ,0 ); - track.show(); - } -} - -void draw_car( track_t* tck, car_t* car ) { - struct cfgtrack const* cfg = &tck->cfg.track; - - switch ( car->trackID ){ - case TRACK_MAIN: - for(int i=0; i<= car->nlap; ++i ) - track.setPixelColor( ((word)car->dist % cfg->nled_main) + i, car->color ); - break; - case TRACK_AUX: - for(int i=0; i<= car->nlap; ++i ) - track.setPixelColor( (word)(cfg->nled_main + cfg->nled_aux - car->dist_aux) + i, car->color); - break; - } -} - - -/* - * Display on LED Strip current values for Slope and Pitlane - * - */ -void show_cfgpars_onstrip(){ - strip_clear( &tck ); - if( ramp_isactive( &tck ) ) - draw_ramp( &tck ); - if( box_isactive( &tck ) ) - draw_box_entrypoint( &tck ); - track.show(); -} - - -/* - * - */ -void draw_ramp( track_t* _tck ) { - struct cfgramp const* r = &_tck->cfg.ramp; - byte dist = 0; - byte intensity = 0; - for( int i = r->init; i <= r->center; ++i ) { - dist = r->center - r->init; - intensity = ( 32 * (i - r->init) ) / dist; - track.setPixelColor( i, track.Color( intensity,0,intensity ) ); - } - for( int i = r->center; i <= r->end; ++i ) { - dist = r->end - r->center; - intensity = ( 32 * ( r->end - i ) ) / dist; - track.setPixelColor( i, track.Color( intensity,0,intensity ) ); - } -} - - -/* - * - */ -void draw_box_entrypoint( track_t* _tck ) { - struct cfgtrack const* cfg = &_tck->cfg.track; - int out = cfg->nled_total - cfg->box_len; // Pit lane exit (race start) - int in = out - cfg->box_len; // Pit lane Entrance - track.setPixelColor(in ,COLOR_BOXMARKS ); - track.setPixelColor(out ,COLOR_BOXMARKS ); -} - - - -/* - * Check Serial to see if there is a command ready to be processed - * - */ -ack_t manageSerialCommand() { - - ack_t ack = { .rp = NOTHING, .type = '\0' }; - - int clen = checkForCommand(); - if(clen == 0) return ack; // No commands received - if(clen < 0) { // Error receiving command - sprintf( txbuff, "Error reading serial command:[%d]",clen); - printdebug( txbuff, WARNING ); - } - - char * cmd = getCommand(); // clen > 0 ---> Command with length=clen ready - ack.rp=NOK; - - switch (cmd[0]) { - case '#': // Handshake - { - ack.type = cmd[0]; - sprintf( txbuff, "#%c", EOL ); - sendCommand(txbuff); - ack.rp = NOTHING; - } - break; - - case '@' : // Enter "Configuration Mode" status - { - ack.type = cmd[0]; - if(race.phase != CONFIG) {// Ignore command if Board already in "Configure Mode" - race.phase = CONFIG; - enter_configuration_mode(); - } - ack.rp = OK; - } - break; - - case '~' : // Exit "Configure Mode" - { - ack.type = cmd[0]; - if(race.phase == CONFIG) { // Ignore command if Board is not in "Configure Mode" - race.newcfg = true; - } - ack.rp = OK; - } - break; - - case 'R' : // Set Race Phase - { - ack.type = cmd[0]; - int const phase = atoi( cmd + 1); - if( 0 > phase || RACE_PHASES <= phase) 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 'C' : //Parse race configuration -> C1,2,3,0 - { - ack.type = cmd[0]; - - char * pch = strtok (cmd,"C"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int startline = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int nlap = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int nrepeat = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int finishline = atoi( pch ); - - int err = race_configure( &tck, startline, nlap, nrepeat, finishline); - if( err ) return ack; - - race.cfg.startline = tck.cfg.race.startline; - race.cfg.nlap = tck.cfg.race.nlap; - race.cfg.nrepeat = tck.cfg.race.nrepeat; - race.cfg.finishline = tck.cfg.race.finishline; - - ack.rp = OK; - } - break; - - - case 'T' : //Parse Track configuration -> Track length - { - ack.type = cmd[0]; - - char * pch = strtok (cmd,"T"); - if( !pch ) return ack; - - int nled = atoi( cmd + 1 ); - int err = tracklen_configure( &tck, nled); - if( err ) return ack; - track_configure( &tck, 0); - if( err ) return ack; - - ack.rp = OK; - } - break; - - case 'B' : //Parse BoxLenght Configuration -> Blen,perm - { - ack.type = cmd[0]; - - char * pch = strtok (cmd,"B"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int boxlen = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int boxperm = atoi( pch ); - - int err = boxlen_configure( &tck, boxlen, boxperm ); - if( err ) return ack; - - ack.rp = OK; - - // Force Pitlane ON, so "show_cfgpars_onstrip()" - // will show the new values, even if AlwaysON=false - box_init(&tck); - show_cfgpars_onstrip(); - } - break; - - case 'A' : // Parse Ramp configuration -> Astart,center,end,high,perm - { - ack.type = cmd[0]; - - char * pch = strtok (cmd,"A"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - int init = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int center = atoi( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - int end = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int high = atoi( pch ); - - pch = strtok (NULL, ","); - if( !pch ) return ack; - int slopeperm = atoi( pch ); - - int err = ramp_configure( &tck, init, center, end, high, slopeperm ); - if( err ) return ack; - ack.rp = OK; - - // Force Ramp ON, so "show_cfgpars_onstrip()" - // will show the new values, even if AlwaysON=false - ramp_init(&tck); - - show_cfgpars_onstrip(); - } - break; - - case 'K': // Parse Physic simulation parameters - { - ack.type = cmd[0]; - - char * pch = strtok (cmd,"K"); - if( !pch ) return ack; - - pch = strtok (pch, "," ); - if( !pch ) return ack; - float kgp = atof( pch ); - - pch = strtok (NULL, "," ); - if( !pch ) return ack; - float kfp = atof( pch ); - - int err = physic_configure( &tck, kgp, kfp ); - if( err ) return ack; - - ack.rp = OK; - } - break; - - - case 'D' : // Load Default Parameters and store them in from EEPROM - { - ack.type = cmd[0]; - param_setdefault( &tck.cfg ); - EEPROM.put( eeadrInfo, tck.cfg ); // Save immediately - - ack.rp = OK; - - // Update box/slope active in current Track Struct with values - // just loaded (for show_cfgpars_onstrip()) - struct cfgparam const* cfg = &tck.cfg; - tck.boxactive = cfg->track.box_alwaysOn; - tck.rampactive = cfg->ramp.alwaysOn; - - show_cfgpars_onstrip(); - } - break; - - case ':' : // Set board Unique Id - { - struct brdinfo* info = &tck.cfg.info; - ack.type = cmd[0]; - if( strlen(cmd + 1) > LEN_UID ) return ack; - strcpy( info->uid, cmd + 1 ); - EEPROM.put( eeadrInfo, tck.cfg ); // Save immediately - ack.rp = OK; - } - break; - - case '$': // Get Board UID - { - sprintf( txbuff, "%s%s%c", "$", tck.cfg.info.uid, EOL ); - sendCommand(txbuff); - ack.rp = NOTHING; - } - break; - - case '?' : // Get Software Id - { - sprintf( txbuff, "%s%s%c", "?", softwareId, EOL ); - sendCommand(txbuff); - ack.rp = NOTHING; - } - break; - - case '%' : // Get Software Version - { - sprintf( txbuff, "%s%s%c", "%", version, EOL ); - sendCommand(txbuff); - ack.rp = NOTHING; - } - break; - - case 'Q': // Get current configuration Info - { - struct cfgparam const* cfg = &tck.cfg; - sprintf( txbuff, "%s:%d,%d,%d,%d,%d,%d,%d.%03d,%d.%03d%c", "QTRACK", - cfg->track.nled_total, - cfg->track.nled_main, - cfg->track.nled_aux, - cfg->track.init_aux, - cfg->track.box_len, - cfg->track.box_alwaysOn, - (int)cfg->track.kg, (int)(cfg->track.kg*1000)%1000, // std arduino sprintf() missing %f - (int)cfg->track.kf, (int)(cfg->track.kf*1000)%1000, // std arduino sprintf() missing %f - EOL ); - sendCommand(txbuff); - - sprintf( txbuff, "%s:%d,%d,%d,%d,%d%c", "QRAMP", - cfg->ramp.init, - cfg->ramp.center, - cfg->ramp.end, - cfg->ramp.high, - cfg->ramp.alwaysOn, - EOL ); - sendCommand(txbuff); - - sprintf( txbuff, "%s:%d,%d,%d,%d%c", "QRACE", - cfg->race.startline, - cfg->race.nlap, - cfg->race.nrepeat, - cfg->race.finishline, - EOL ); - sendCommand(txbuff); - - ack.rp = NOTHING; - } - break; - - case 'W': // Write configuration to EEPROM - { - ack.type = cmd[0]; - EEPROM.put( eeadrInfo, tck.cfg ); - ack.rp = OK; - } - break; - - } // switch - - return(ack); - -} - -/* - * - */ -void sendResponse( ack_t *ack) { - if(ack->type=='\0'){ - sprintf(txbuff, "%s%c", ack->rp==OK? "OK":"NOK" , EOL ); - } else { - sprintf(txbuff, "%c%s%c", ack->type, ack->rp==OK? "OK":"NOK" , EOL ); - } - sendCommand(txbuff); -} - -/* - * Send Log/Warning/Error messages to host - */ -void printdebug( const char * msg, int errlevel ) { - char header [5]; - sprintf(header, "!%d,",errlevel); - Serial.print(header); - Serial.print(msg); - Serial.print(EOL); -} - - -/* - * reset race parameters - * stop sound - */ -void enter_configuration_mode(){ - noTone(PIN_AUDIO); - strip_clear( &tck ); - track.show(); -} - - - -void param_load( struct cfgparam* cfg ) { - int cfgversion; - int eeAdress = eeadrInfo; - EEPROM.get( eeAdress, tck.cfg ); - eeAdress += sizeof( cfgparam ); - EEPROM.get( eeAdress, cfgversion ); - - sprintf( txbuff, "%s:%d%c", "Parameters Loaded from EEPROM - Cfg ver", cfgversion, EOL ); - sendCommand(txbuff); - - if ( cfgversion != CFG_VER ) { - param_setdefault( &tck.cfg ); - eeAdress = 0; - EEPROM.put( eeAdress, tck.cfg ); - eeAdress += sizeof( cfgparam ); - EEPROM.put( eeAdress, CFG_VER ); - sprintf( txbuff, "%s%c", "DEFAULT PAREMETRS LOADED (and Stored in EEPROM)", EOL ); - //serialCommand. - sendCommand(txbuff); - - } - -} - - - -/* - * Serial Read/Write functions - * --------------------------- - * checkForCommand() - * getCommand() - * sendCommand(char* str) - * - */ -Stream* _stream = &Serial; -int bufIdx; -int checkForCommand() { - while (_stream->available()) { - if(bufIdx < REC_COMMAND_BUFLEN - 2) { - char data = _stream->read(); - if(data == EOL) { - int cmsSize=bufIdx; - cmdbuf[bufIdx++] = '\0'; - bufIdx=0; - return(cmsSize); - } else { - cmdbuf[bufIdx++] = data; - } - } else { - // buffer full - // re4set and retunn error - cmdbuf[bufIdx++] = '\0'; - bufIdx=0; - return(-2); - } - } - return(0); -} - -/* - * - */ -char * getCommand(){ - return(cmdbuf); -} - -/* - * - */ -void sendCommand(char* str) { - // get command length - int dlen=0; - for(; dlen<80; dlen++ ) { - if(*(str+dlen) == EOL ){ - dlen++; // send EOC - break; - } - } - _stream->write(str, dlen); - return; -} - - -/* - * Custon Non-Blocking Delay() functions - * customDelayStart(unsigned long timeout) - * customDelayElapsed - */ -unsigned long customDelay_startTime=0; -unsigned long customDelay_timeout=0; -void customDelayStart(unsigned long tout) { - customDelay_timeout=tout; - customDelay_startTime=millis(); -} -/* - * - */ -boolean customDelayElapsed(){ - if((millis() - customDelay_startTime) > customDelay_timeout) { - return(true); - } - return(false); -}