RETRO ROBOT E
ROBOT.cpp
- Committer:
- RLRiedinger
- Date:
- 2015-03-02
- Revision:
- 0:4837c9695a02
File content as of revision 0:4837c9695a02:
#include "ROBOT.h" #define AUTO_START const char* ROBOT::LOSE_1 = ""; const char* ROBOT::LOSE_2 = ""; const char* ROBOT::SPLASH_1 = ""; const char* ROBOT::SPLASH_2 = ""; const char* ROBOT::SSID = "XXXXXXXX"; const char* ROBOT::PASSWORD = "XXXXXXXX"; struct match { char *RESPONSE; char *pRESPONSE; } matchtab[] = { { "+IPD," }, { "\r\n> " }, { "busy s..." }, { "OK\r\n" }, { "+ERROR\r\n" }, }; ROBOT::ROBOT() : left(P0_14, PullUp), right(P0_11, PullUp), down(P0_12, PullUp), up(P0_13, PullUp), square(P0_16, PullUp), circle(P0_1, PullUp), led1(P0_9), led2(P0_8), pwm(P0_18), i2c(D_SDA, D_SCL), serial_bridge1(&i2c, SC16IS750_SA0), serial_bridge2(&i2c, SC16IS750_SA1), esp8266_rst(ESP8266_RST) { pIPD_BUFFER = IPD_BUFFER; DEBUG = 0; heartbeatflag = false; Address_T = "192.168.0.32"; Address = Address_T; #ifdef AUTO_START echo_comands = 0; #else echo_comands = 0; #endif mPROMPT = 0; mIPD = 0; mCOUNT = 0; COUNT = 0; uCOUNT = 0; mCOLON = 0; this->serial_bridge1.baud(14745600UL, 9600); this->serial_bridge2.baud(14745600UL, 19200); this->serial_bridge1.format(8, Serial::None, 1); this->serial_bridge2.format(8, Serial::None, 1); this->serial_bridge1.set_fifo_control(); this->serial_bridge2.set_fifo_control(); this->serial_bridge1.flush(); this->serial_bridge2.flush(); this->serial_bridge1.set_modem_control(); this->serial_bridge2.set_modem_control(); this->serial_bridge1.set_flow_triggers(); this->serial_bridge2.set_flow_triggers(); this->ESP8266_reset(); srand(0); this->lastUp = false; this->lastDown = false; this->mode = true; this->colors[0] = DisplayN18::RED; this->colors[1] = DisplayN18::GREEN; this->colors[2] = DisplayN18::BLUE; this->initialize(); } void ROBOT::serial_print1(char * BUFFER) { while (*BUFFER != '\0') { serial_bridge1.putc((int) *BUFFER++); } } void ROBOT::serial_print2(char * BUFFER) { while (*BUFFER != '\0') { serial_bridge2.putc((int) *BUFFER++); } } void ROBOT::debug_print(unsigned int line, const char* function) { if (DEBUG) { sprintf(UART_BUFFER, "%6d %s\r\n", line, function); this->serial_print2(UART_BUFFER); } } void ROBOT::debug_print_string(unsigned int line, const char* function, char * pBUFFER) { if (DEBUG) { sprintf(UART_BUFFER, "%6d %s [%s]\r\n", line, function, pBUFFER); this->serial_print2(UART_BUFFER); } } void ROBOT::debug_print2(unsigned int line, const char* function) { if (DEBUG) { sprintf(UART_BUFFER, "%6d %s\r\n", line, function); this->serial_print2(UART_BUFFER); } } void ROBOT::debug_print_string2(unsigned int line, const char* function, char * pBUFFER) { if (DEBUG) { sprintf(UART_BUFFER, "%6d %s [%s]\r\n", line, function, pBUFFER); this->serial_print2(UART_BUFFER); } } void ROBOT::show_menu(void) { serial_print2("0: Exit\n\r"); serial_print2("1: Show Menu\n\r"); serial_print2("2: Init\n\r"); serial_print2("3: IO Port Out\n\r"); serial_print2("4: Transparant mode\n\r"); serial_print2("5: Free bufferspace\n\r"); #if (0) serial_print2("6: Enable RTS/CTS\n\r"); serial_print2("7: Disable RTS/CTS\n\r"); serial_print2("8: Write block\n\r"); serial_print2("9: Baudrate 9600\n\r"); serial_print2("A: Baudrate 115200\n\r"); serial_print2("B: Transparant mode with buffer display\n\r"); #endif #if (0) serial_print2("C: Test printf\n\r"); #endif serial_print2("D: Test connected\n\r"); #if(0) serial_print2("D: \n\r"); serial_print2("P: \n\r"); #endif serial_print2("T: Test ESP8266 192.168.0.6\n\r"); #if (0) serial_print2("U: Test ESP8266 192.168.0.14\n\r"); serial_print2("V: Test ESP8266 192.168.0.22\n\r"); #endif serial_print2("W: Toggle ECHO mode\n\r"); serial_print2("Z: Toggle DEBUG mode\n\r"); serial_print2("\n\r"); while (serial_bridge2.writableCount() < 64); First = 1; } void ROBOT::blink (DigitalOut LED) { LED = 1; wait(0.05); LED = 0; } // Heartbeat monitor void ROBOT::pulse(void) { led2 = !led2; } void ROBOT::heartbeat_start(void) { heartbeat.attach(this, &ROBOT::pulse, 0.5); } void ROBOT::heartbeat_stop(void) { heartbeat.detach(); } void ROBOT::ESP8266_reset(void) { esp8266_rst = 0; wait(0.1); esp8266_rst = 1; wait(1.0); while (serial_bridge1.readable()) { serial_bridge1.getc(); wait(0.005); } } void ROBOT::reset_matchtab(void) { for (int i = 0; i < NMATCHES; i++) { matchtab[i].pRESPONSE = matchtab[i].RESPONSE; } } int ROBOT::match_RESPONSES(char c, struct match table[], int n) { // debug_print(__LINE__, __FUNCTION__); for (int i = 0; i < n; i++) { if (c == *table[i].pRESPONSE) { ++table[i].pRESPONSE; if (*table[i].pRESPONSE == '\0') { table[i].pRESPONSE = table[i].RESPONSE; return(i + 1); } } else { table[i].pRESPONSE = table[i].RESPONSE; if (c == *table[i].pRESPONSE) { ++table[i].pRESPONSE; if (*table[i].pRESPONSE == '\0') { table[i].pRESPONSE = table[i].RESPONSE; return(i + 1); } } } } return(0); } int ROBOT::echo(int show, int timeout) { debug_print(__LINE__, __FUNCTION__); Timer ReceiveTimer; char c = '\0'; // char IIR_STATUS = 0; int return_code = 0; debug_print(__LINE__, __FUNCTION__); ReceiveTimer.start(); debug_print(__LINE__, __FUNCTION__); while (!return_code) { // debug_print(__LINE__, __FUNCTION__); if (ReceiveTimer.read_ms() > timeout) { debug_print(__LINE__, __FUNCTION__); return_code = -1; } // From Serial to SPI/I2C #ifndef AUTO_START while (!return_code && serial_bridge2.readable()) { debug_print(__LINE__, __FUNCTION__); c = serial_bridge2.getc(); if (c == '#') { debug_print(__LINE__, __FUNCTION__); return_code = QUIT; } else { serial_bridge1.putc(c); } } #endif // From SPI/I2C to serial int readable1; // int readable1 = serial_bridge1.readableCount(); // sprintf(FORMAT_BUFFER, "readable1 = %i", readable1); // debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); while (!return_code && ((readable1 = serial_bridge1.readableCount()) > 0)) { // sprintf(FORMAT_BUFFER, "readable1 = %i", readable1); // debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); ReceiveTimer.reset(); c = serial_bridge1.getc(); #ifndef AUTO_START if (show) { serial_bridge2.putc(c); sprintf(UART_BUFFER, "%6d %s [%c]\r\n", __LINE__, __FUNCTION__, c); serial_print2(UART_BUFFER); } #endif return_code = match_RESPONSES(c, matchtab, NMATCHES); } } sprintf(FORMAT_BUFFER, "return_code = %i", return_code); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); ReceiveTimer.stop(); debug_print(__LINE__, __FUNCTION__); return(return_code); } // Game Math: Faster Sine & Cosine with Polynomial Curves // http://allenchou.net/2014/02/game-math-faster-sine-cosine-with-polynomial-curves/ // Posted on February 28, 2014 by Allen Chou double ROBOT::Hill(double x) { const float a0 = 1.0f; const float a2 = 2.0f / PI - 12.0f / (PI * PI); const float a3 = 16.0f / (PI * PI * PI) - 4.0f / (PI * PI); const float xx = x * x; const float xxx = xx * x; return a0 + a2 * xx + a3 * xxx; } double ROBOT::FastSin(double x) { // wrap x within [0, TWO_PI) const float a = x * TWO_PI_INV; x -= static_cast < int > (a) * TWO_PI; if (x < 0.0f) { x += TWO_PI; } // 4 pieces of hills if (x < HALF_PI) { return Hill(HALF_PI - x); } else if (x < PI) { return Hill(x - HALF_PI); } else if (x < 3.0f * HALF_PI) { return -Hill(3.0f * HALF_PI - x); } else { return -Hill(x - 3.0f * HALF_PI); } } double ROBOT::FastCos(double x) { return FastSin(x + HALF_PI); } int ROBOT::process_IPD(char c) { sprintf(FORMAT_BUFFER, "c = [%c]", c); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); int return_code = 0; if (!mCOUNT && (c >= '0') && (c <= '9')) { COUNT = COUNT * 10 + (int) c - '0'; uCOUNT = 0; sprintf(FORMAT_BUFFER, "COUNT = %i", COUNT); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); } else if (!mCOLON && (c == ':')) { debug_print(__LINE__, __FUNCTION__); mCOUNT = 1; mCOLON = 1; } else if (mCOLON && (uCOUNT < COUNT) && (uCOUNT < 80)) { debug_print(__LINE__, __FUNCTION__); *pIPD_BUFFER++ = c; *pIPD_BUFFER = 0; uCOUNT++; sprintf(FORMAT_BUFFER, "uCOUNT = %i", uCOUNT); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); if (uCOUNT == COUNT) { debug_print(__LINE__, __FUNCTION__); sprintf(FORMAT_BUFFER, "%6d %s [%s]\r\n", __LINE__, __FUNCTION__, IPD_BUFFER); serial_print2(FORMAT_BUFFER); // [21:40:34.9 1234 1234 1234 12345678 12345678] // [17:14:02.0 336 67 -32 1000677 1000747] // [0123456789012345678901234567890123456789012] // [0000000000111111111122222222223333333333444] // int hours, minutes, seconds, tenths, angle; // unsigned int hours, minutes, seconds, tenths, angle; // double CurrentTime, OldTime, ElapsedTime, Angle, Speed; // uint64_t leftencoder, rightencoder, oldleftencoder, oldrightencoder; // int mPROMPT, mIPD, mCOUNT, COUNT, uCOUNT, mCOLON, First; IPD_BUFFER[15] = 0; IPD_BUFFER[20] = 0; IPD_BUFFER[25] = 0; // IPD_BUFFER[34] = 0; // IPD_BUFFER[43] = 0; int hours = 10 * (int)(IPD_BUFFER[0] - '0') + (int)(IPD_BUFFER[1] - '0'); int minutes = 10 * (int)(IPD_BUFFER[3] - '0') + (int)(IPD_BUFFER[4] - '0'); int seconds = 10 * (int)(IPD_BUFFER[6] - '0') + (int)(IPD_BUFFER[7] - '0'); int tenths = (int)(IPD_BUFFER[9] - '0'); sprintf(FORMAT_BUFFER, "%6d %s [%02d:%02d:%02d.%1d]\r\n", __LINE__, __FUNCTION__, hours, minutes, seconds, tenths); serial_print2(FORMAT_BUFFER); CurrentTime = (double)(60 * ((60 * hours) + minutes) + seconds + (double)(tenths / 10)); sprintf(FORMAT_BUFFER, "%6d %s CurrentTime = %6.1f\r\n", __LINE__, __FUNCTION__, CurrentTime); serial_print2(FORMAT_BUFFER); Angle = (double)atoi((char *)(IPD_BUFFER + 11)); sprintf(FORMAT_BUFFER, "%6d %s [Angle = %4.0f\r\n", __LINE__, __FUNCTION__, Angle); serial_print2(FORMAT_BUFFER); #if (0) leftencoder = (uint64_t)atol((char *)(IPD_BUFFER + 26)); rightencoder = (uint64_t)atol((char *)(IPD_BUFFER + 35)); sprintf(FORMAT_BUFFER, "%6d %s [LE = %8lld] [RE = %8lld]\r\n", __LINE__, __FUNCTION__, leftencoder, rightencoder); serial_print2(FORMAT_BUFFER); #endif if (First) { First = 0; } else { ElapsedTime = CurrentTime - OldTime; if (ElapsedTime < 0.0) { ElapsedTime += 86400.0; } sprintf(FORMAT_BUFFER, "%6d %s [ElapsedTime = %6.1f]\r\n", __LINE__, __FUNCTION__, ElapsedTime); serial_print2(FORMAT_BUFFER); #if (0) int64_t leftencoderdelta = leftencoder - oldleftencoder; int64_t rightencoderdelta = rightencoder - oldrightencoder; if (leftencoderdelta > 0x3fffffff) { leftencoderdelta -= 0xffffffff; } else if (leftencoderdelta < - 0x3fffffff) { leftencoderdelta += 0xffffffff; } sprintf(FORMAT_BUFFER, "%6d %s [leftencoderdelta = %8lld]\r\n", __LINE__, __FUNCTION__, leftencoderdelta); serial_print2(FORMAT_BUFFER); if (rightencoderdelta > 0x3fffffff) { rightencoderdelta -= 0xffffffff; } else if (rightencoderdelta < - 0x3fffffff) { rightencoderdelta += 0xffffffff; } sprintf(FORMAT_BUFFER, "%6d %s [rightencoderdelta = %8lld]\r\n", __LINE__, __FUNCTION__, rightencoderdelta); serial_print2(FORMAT_BUFFER); double EncoderDelta = (double) (leftencoderdelta > rightencoderdelta ? leftencoderdelta : rightencoderdelta); sprintf(FORMAT_BUFFER, "%6d %s [EncoderDelta = %6.1f]\r\n", __LINE__, __FUNCTION__, EncoderDelta); serial_print2(FORMAT_BUFFER); double Velocity = EncoderDelta / ElapsedTime / 10.0; sprintf(FORMAT_BUFFER, "%6d %s [Velocity = %6.2f]\r\n", __LINE__, __FUNCTION__, Velocity); serial_print2(FORMAT_BUFFER); R = Velocity * ElapsedTime; #endif this->clearBall(); this->disp.drawCircle(this->circleX, this->circleY, 2 * ROBOT::BALL_RADIUS, DisplayN18::BLACK); #if (1) this->circleX = (int)atoi((char *)(IPD_BUFFER + 16)) + DisplayN18::WIDTH / 2; this->circleY = (int)atoi((char *)(IPD_BUFFER + 21)) + 3 * DisplayN18::HEIGHT / 4; #else this->ballX += (int) (R * FastCos(Angle * PI / 180.0) + 0.5); this->ballY += (int) (R * FastSin(Angle * PI / 180.0) + 0.5); #endif if (this->circleX - ROBOT::BALL_RADIUS < 0) { this->circleX = ROBOT::BALL_RADIUS; } else if (this->circleX + ROBOT::BALL_RADIUS > DisplayN18::WIDTH) { this->circleX = DisplayN18::WIDTH - ROBOT::BALL_RADIUS; } if (this->circleY - ROBOT::BALL_RADIUS < 0) { this->circleY = ROBOT::BALL_RADIUS; } else if (this->circleY + ROBOT::BALL_RADIUS > DisplayN18::HEIGHT) { this->circleY = DisplayN18::HEIGHT - ROBOT::BALL_RADIUS; } if (this->ballX - ROBOT::BALL_RADIUS < 0) { this->ballX = ROBOT::BALL_RADIUS; } else if (this->ballX + ROBOT::BALL_RADIUS > DisplayN18::WIDTH) { this->ballX = DisplayN18::WIDTH - ROBOT::BALL_RADIUS; } if (this->ballY - ROBOT::BALL_RADIUS < 0) { this->ballY = ROBOT::BALL_RADIUS; } else if (this->ballY + ROBOT::BALL_RADIUS > DisplayN18::HEIGHT) { this->ballY = DisplayN18::HEIGHT - ROBOT::BALL_RADIUS; } this->drawBall(); this->disp.drawCircle(this->circleX, this->circleY, 2 * ROBOT::BALL_RADIUS, DisplayN18::WHITE); this->DrawBox(); sprintf(FORMAT_BUFFER, "%6d %s [this->circleX = %4i this->circleY = %4i]\r\n", __LINE__, __FUNCTION__, this->circleX, this->circleY); serial_print2(FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "%6d %s [this->ballX = %4i this->ballY = %4i]\r\n", __LINE__, __FUNCTION__, this->ballX, this->ballY); serial_print2(FORMAT_BUFFER); // this->ballX = DisplayN18::WIDTH / 2 - ROBOT::BALL_RADIUS; // this->ballY = DisplayN18::HEIGHT / 4 - ROBOT::BALL_RADIUS; } OldTime = CurrentTime; oldleftencoder = leftencoder; oldrightencoder = rightencoder; mIPD = 0; } } // debug(__LINE__, __FUNCTION__); return(return_code); } void ROBOT::process_buttons(void) { debug_print(__LINE__, __FUNCTION__); #if (1) if (!square) { BUFFER[5] = 'S'; } else { BUFFER[5] = 's'; } sprintf(BUFFER, "%03i %03i %c", this->ballX - DisplayN18::WIDTH / 2, this->ballY - 3 * DisplayN18::HEIGHT / 4, square ? 's' : 'S'); sprintf(FORMAT_BUFFER, "%6d %s [%s]\r\n", __LINE__, __FUNCTION__, BUFFER); serial_print2(FORMAT_BUFFER); #else if (!left) { BUFFER[0] = 'L'; } else { BUFFER[0] = 'l'; } if (!right) { BUFFER[1] = 'R'; } else { BUFFER[1] = 'r'; } if (!down) { BUFFER[2] = 'D'; } else { BUFFER[2] = 'd'; } if (!up) { BUFFER[3] = 'U'; } else { BUFFER[3] = 'u'; } if (!square) { BUFFER[5] = 'S'; } else { BUFFER[5] = 's'; } if (!circle) { BUFFER[6] = 'C'; } else { BUFFER[6] = 'c'; } BUFFER[7] = 0; #endif serial_print1(BUFFER); // // Should wait for OK ... // mPROMPT = 0; debug_print(__LINE__, __FUNCTION__); } int ROBOT::terminal_emulator(int echo_comands, int timeout) { debug_print(__LINE__, __FUNCTION__); int return_code = 0; char c = '\0'; mPROMPT = 0; mIPD = 0; #ifndef AUTO_START #if (0) int ODOMETER_index = 0; #endif #endif Timer ReceiveTimer; Timer ButtonTimer; int Button_Timeout = Initial_Button_Timeout; ReceiveTimer.start(); ButtonTimer.start(); debug_print(__LINE__, __FUNCTION__); while (return_code != ERROR) { // debug_print(__LINE__, __FUNCTION__); // From Serial to SPI/I2C #ifndef AUTO_START while (!return_code && serial_bridge2.readable()) { ReceiveTimer.reset(); c = serial_bridge2.getc(); if (c == '#') { // debug_print(__LINE__, __FUNCTION__); return_code = QUIT; } else { serial_bridge1.putc(c); } } #endif // From SPI/I2C to serial while ((return_code != ERROR) && serial_bridge1.readable()) { if (!mIPD) { ReceiveTimer.reset(); } // debug_print(__LINE__, __FUNCTION__); c = serial_bridge1.getc(); #ifndef AUTO_START if (echo_comands) { serial_bridge2.putc(c); sprintf(UART_BUFFER, "%6d %s [%c]\r\n", __LINE__, __FUNCTION__, c); serial_print2(UART_BUFFER); } #endif return_code = match_RESPONSES(c, matchtab, NMATCHES); if (return_code != 0) { sprintf(FORMAT_BUFFER, "return_code = %i", return_code); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); } if ((return_code == IPD) && !mIPD) { debug_print(__LINE__, __FUNCTION__); return_code = 0; mIPD = 1; mCOUNT = 0; COUNT = 0; uCOUNT = 0; mCOLON = 0; pIPD_BUFFER = IPD_BUFFER; } else if (mIPD) { led1 = 1; debug_print(__LINE__, __FUNCTION__); process_IPD(c); ReceiveTimer.reset(); led1 = 0; } else if (return_code == PROMPT) { led1 = 1; debug_print(__LINE__, __FUNCTION__); mPROMPT = 1; return_code = 0; process_buttons(); ButtonTimer.start(); led1 = 0; } else if ((return_code == OK) || (return_code == BUSY)) { led1 = 1; debug_print(__LINE__, __FUNCTION__); if (mIPD) { mIPD = 0; } else if (mPROMPT) { mPROMPT = 0; } led1 = 0; } else if (return_code == ERROR) { // debug_print(__LINE__, __FUNCTION__); } } if (ReceiveTimer.read_ms() / 100 % 10 == 0) { #if (1) this->clearBall(); this->disp.drawCircle(this->circleX, this->circleY, 2 * ROBOT::BALL_RADIUS, DisplayN18::BLACK); // +---+-----+---+ // | 6 | 7 | 8 | // +---+-----+---+ // | 3 | 4 | 5 | // +---+-----+---+ // | 0 | 1 | 2 | // +---+-----+---+ debug_print(__LINE__, __FUNCTION__); sprintf(FORMAT_BUFFER, "%i4 %i4 %i3", this->ballX, this->ballY, ROBOT::BALL_RADIUS); debug_print_string2(__LINE__, __FUNCTION__, FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "%i4 %i4", DisplayN18::WIDTH, DisplayN18::HEIGHT); debug_print_string2(__LINE__, __FUNCTION__, FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "%i3 %i3", this->BoxWidth, this->BoxHeight); debug_print_string2(__LINE__, __FUNCTION__, FORMAT_BUFFER); if (this->ballX + ROBOT::BALL_RADIUS == DisplayN18::WIDTH / 2 - BoxWidth / 2 - 1) { debug_print2(__LINE__, __FUNCTION__); if (this->ballY - ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 + BoxHeight / 2 + 1) { // 0 - No +X (Right) and -Y (Up) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read() && this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read() && this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else if ((this->ballY + ROBOT::BALL_RADIUS >= DisplayN18::HEIGHT / 2 - BoxHeight / 2) && (this->ballY - ROBOT::BALL_RADIUS <= DisplayN18::HEIGHT / 2 + BoxHeight / 2)) { // 3 - No +X (Right) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else if (this->ballY + ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 - BoxHeight / 2 - 1) { // 6 - No +X (Right) and +Y (Down) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read() && this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read() && this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else { debug_print2(__LINE__, __FUNCTION__); if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } } } else if ((this->ballX - ROBOT::BALL_RADIUS >= DisplayN18::WIDTH / 2 - BoxWidth / 2 - 1) && (this->ballX - ROBOT::BALL_RADIUS <= DisplayN18::WIDTH / 2 + BoxWidth / 2 + 1)) { debug_print2(__LINE__, __FUNCTION__); if (this->ballY - ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 + BoxHeight / 2 + 1) { // 1 - No -Y (Up) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else if ((this->ballY + ROBOT::BALL_RADIUS >= DisplayN18::HEIGHT / 2 - BoxHeight / 2) && (this->ballY + ROBOT::BALL_RADIUS <= DisplayN18::HEIGHT / 2 + BoxHeight / 2)) { // 4 - Oops inside box allow him to leave debug_print2(__LINE__, __FUNCTION__); if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } } else if (this->ballY + ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 - BoxHeight / 2 - 1) { // 7 - No +Y (Down) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } } else { debug_print2(__LINE__, __FUNCTION__); if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } } } else if (this->ballX - ROBOT::BALL_RADIUS == DisplayN18::WIDTH / 2 + BoxWidth / 2 + 1) { debug_print2(__LINE__, __FUNCTION__); if (this->ballY - ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 + BoxHeight / 2 + 1) { // 2 - No -X (Left) and +Y (Down) debug_print2(__LINE__, __FUNCTION__); if (!this->left.read() && this->down.read()) { debug_print(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read() && this->left.read()) { debug_print(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read() && this->left.read()) { debug_print(__LINE__, __FUNCTION__); this->ballY++; } } else if ((this->ballY + ROBOT::BALL_RADIUS >= DisplayN18::HEIGHT / 2 - BoxHeight / 2) && (this->ballY - ROBOT::BALL_RADIUS <= DisplayN18::HEIGHT / 2 + BoxHeight / 2)) { // 5 - No -X (Left) if (!this->right.read()) { debug_print(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else if (this->ballY + ROBOT::BALL_RADIUS == DisplayN18::HEIGHT / 2 - BoxHeight / 2 - 1) { // 8 - No -X (Left) and +Y (Down) if (!this->left.read() && this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read() && this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } } else { debug_print2(__LINE__, __FUNCTION__); if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } } } else { debug_print2(__LINE__, __FUNCTION__); if (!this->up.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY--; } else if (!this->down.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballY++; } if (!this->left.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX--; } else if (!this->right.read()) { debug_print2(__LINE__, __FUNCTION__); this->ballX++; } } if (this->ballX - ROBOT::BALL_RADIUS < 0) { this->ballX = ROBOT::BALL_RADIUS; } else if (this->ballX + ROBOT::BALL_RADIUS > DisplayN18::WIDTH) { this->ballX = DisplayN18::WIDTH - ROBOT::BALL_RADIUS; } if (this->ballY - ROBOT::BALL_RADIUS < 0) { this->ballY = ROBOT::BALL_RADIUS; } else if (this->ballY + ROBOT::BALL_RADIUS > DisplayN18::HEIGHT) { this->ballY = DisplayN18::HEIGHT - ROBOT::BALL_RADIUS; } this->drawBall(); this->disp.drawCircle(this->circleX, this->circleY, 2 * ROBOT::BALL_RADIUS, DisplayN18::WHITE); #endif sprintf(FORMAT_BUFFER, "ReceiveTimer.read_ms() = %i", ReceiveTimer.read_ms()); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "ButtonTimer.read_ms() = %i", ButtonTimer.read_ms()); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "mIPD = %i", mIPD); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); sprintf(FORMAT_BUFFER, "mPROMPT = %i", mPROMPT); debug_print_string(__LINE__, __FUNCTION__, FORMAT_BUFFER); } if (ReceiveTimer.read_ms() > timeout) { debug_print(__LINE__, __FUNCTION__); return_code = ERROR; } else if (!mIPD && !mPROMPT && (ButtonTimer.read_ms() > Button_Timeout)) { debug_print(__LINE__, __FUNCTION__); led1 = 0; serial_print1("AT+CIPSEND=9\r"); led1 = 1; ButtonTimer.reset(); ButtonTimer.stop(); ReceiveTimer.reset(); } } ReceiveTimer.stop(); ButtonTimer.stop(); debug_print(__LINE__, __FUNCTION__); return(return_code); } void ROBOT::DrawBox(void) { this->disp.drawLine(DisplayN18::WIDTH / 2 - BoxWidth / 2, DisplayN18::HEIGHT / 2 - BoxHeight / 2, DisplayN18::WIDTH / 2 + BoxWidth / 2, DisplayN18::HEIGHT / 2 - BoxHeight / 2, DisplayN18::GREEN); this->disp.drawLine(DisplayN18::WIDTH / 2 + BoxWidth / 2, DisplayN18::HEIGHT / 2 - BoxHeight / 2, DisplayN18::WIDTH / 2 + BoxWidth / 2, DisplayN18::HEIGHT / 2 + BoxHeight / 2, DisplayN18::GREEN); this->disp.drawLine(DisplayN18::WIDTH / 2 + BoxWidth / 2, DisplayN18::HEIGHT / 2 + BoxHeight / 2, DisplayN18::WIDTH / 2 - BoxWidth / 2, DisplayN18::HEIGHT / 2 + BoxHeight / 2, DisplayN18::GREEN); this->disp.drawLine(DisplayN18::WIDTH / 2 - BoxWidth / 2, DisplayN18::HEIGHT / 2 + BoxHeight / 2, DisplayN18::WIDTH / 2 - BoxWidth / 2, DisplayN18::HEIGHT / 2 - BoxHeight / 2, DisplayN18::GREEN); } int ROBOT::test(void) { debug_print(__LINE__, __FUNCTION__); First = 1; this->circleX = DisplayN18::WIDTH / 2; this->circleY = 3 * DisplayN18::HEIGHT / 4; this->ballX = DisplayN18::WIDTH / 2; this->ballY = 3 * DisplayN18::HEIGHT / 4; this->disp.clear(); this->drawBall(); this->disp.drawCircle(this->circleX, this->circleY, 2 * ROBOT::BALL_RADIUS, DisplayN18::WHITE); this->DrawBox(); int return_code; reset_matchtab(); debug_print(__LINE__, __FUNCTION__); blink(led1); serial_print1("AT\r"); debug_print(__LINE__, __FUNCTION__); if ((return_code = echo(echo_comands, 10000)) == OK) { blink(led1); debug_print(__LINE__, __FUNCTION__); serial_print1("AT+CWMODE=1\r"); if ((return_code = echo(echo_comands, 10000)) == OK) { blink(led1); debug_print(__LINE__, __FUNCTION__); sprintf(FORMAT_BUFFER, "AT+CWJAP=\"%s\",\"%s\"\r", SSID, PASSWORD); serial_print1(FORMAT_BUFFER); if ((return_code = echo(echo_comands, 10000)) == OK) { blink(led1); debug_print(__LINE__, __FUNCTION__); serial_print1("AT+CIPMUX=0\r"); if ((return_code = echo(echo_comands, 10000)) == OK) { blink(led1); debug_print(__LINE__, __FUNCTION__); serial_bridge1.printf("AT+CIPSTART=\"TCP\",\"%s\",5001\r", Address); if ((return_code = echo(echo_comands, 30000)) == OK) { debug_print(__LINE__, __FUNCTION__); for (int i = 0; i < 20; i++) { blink(led1); serial_bridge1.flush(); wait(0.05); } return_code = terminal_emulator(echo_comands, 10000); } } } } } debug_print(__LINE__, __FUNCTION__); #ifndef AUTO_START if (return_code != QUIT) { serial_print2("ERROR\r\n"); } #endif led1 = 1; wait(1.0); return return_code; } void ROBOT::test2(void) { while (1) { debug_print(__LINE__, __FUNCTION__); } } int ROBOT::get_options(void) { #ifndef AUTO_START int return_code; bool running = true; bool running_test = true; char command, ch; while (!serial_bridge2.readable()); command = serial_bridge1.getc(); #if defined(TARGET_LPC11U24) serial_print2("\r\nHello World from LPC11U24\r\n"); #endif #if defined(TARGET_LPC1768) serial_print2("\r\nHello World from LPC1768\r\n"); #endif #if defined(TARGET_KL25Z) serial_print2("\r\nHello World from KL25Z\r\n"); #endif #if defined(TARGET_LPC812) serial_print2("\r\nHello World from LPC812\r\n"); #endif int i = 0; #endif heartbeat_start(); // myled1 = 1; // LED Off // We need to enable flow control or we overflow buffers and // lose data when used with the WiFly. Note that flow control // needs to be enabled on the WiFly for this to work but it's // possible to do that with flow control enabled here but not // there. // serial_bridge1.set_flow_control(SC16IS750::RTSCTS); serial_bridge1.ioSetDirection(0xFF); // All outputs serial_bridge1.ioSetState(0xFF); // All On #ifdef AUTO_START Address = Address_T; while (1) { test(); } #else show_menu(); while (serial_bridge2.writableCount() < 64); serial_bridge2.flush(); serial_print2(">"); while (running) { if (serial_bridge2.readable()) { command = serial_bridge2.getc(); serial_bridge2.printf("command = %c\n\r", command); switch (command) { case '0' : serial_print2("Done\n\r"); running = false; break; case '1' : show_menu(); break; case '2' : serial_print2("Hardware Reset\n\r"); serial_bridge1.hwReset(); // test serial_print2("Init\n\r"); serial_bridge1._init(); ESP8266_reset(); serial_print2("Hardware Init done\n\r"); break; case '3' : serial_print2("IO Port Out\n\r"); i = 0; while (!serial_bridge2.readable()) { serial_bridge1.ioSetState(i); // serial_bridge1.ioGetState() ; // test // wait(0.5); // pc.putc('*'); i = (i + 1) & 0xFF; } serial_bridge2.getc(); serial_print2("IO Port Out Done\n\r"); break; case '4' : serial_print2("Transparant Mode, Enter '#' to quit...\n\r"); running_test = true; while (running_test) { // From SPI/I2C to serial while (serial_bridge2.readable()) { ch = serial_bridge2.getc(); running_test = (ch != '#'); serial_bridge1.putc(ch); } // From Serial to SPI/I2C while (running_test && serial_bridge1.readable()) { ch = serial_bridge1.getc(); running_test = (ch != '#'); serial_bridge2.putc(ch); } } serial_print2("\n\rTransparant Mode done\n\r"); break; case '5' : serial_bridge2.printf("Available for Reading = %3d (Free Space = %3d)\n\r", serial_bridge1.readableCount(), SC16IS750_FIFO_RX - serial_bridge1.readableCount()); serial_bridge2.printf("Available for Writing = %3d (Used Space = %3d)\n\r", serial_bridge1.writableCount(), SC16IS750_FIFO_TX - serial_bridge1.writableCount()); break; #if (0) case '6' : serial_print2("Enable RTS/CTS\n\r"); serial_bridge1.set_flow_control(SC16IS750::RTSCTS); break; case '7' : serial_print2("Disable RTS/CTS\n\r"); serial_bridge1.set_flow_control(SC16IS750::Disabled); break; case '8' : serial_print2("Write block\n\r"); serial_bridge1.writeString("Hello World from mbed and SC16IS750 "); break; case '9' : serial_print2("Baudrate = 9600\n\r"); serial_bridge2.baud(14745600UL, 9600); break; case 'A' : serial_print2("Baudrate = 115200\n\r"); serial_bridge2.baud(14745600UL, 115200); break; case 'B' : serial_print2("Transparent Mode with buffer display, Enter '#' to quit...\n\r"); running_test=true; while (running_test) { // From SPI/I2C to serial while (running_test && serial_bridge2.readable()) { ch = serial_bridge2.getc(); running_test = (ch != '#'); serial_bridge1.putc(ch); // Show buffers when character was entered serial_print2("\n\r"); serial_bridge2.printf("Available for Reading = %3d (Free Space = %3d)\n\r", serial_bridge1.readableCount(), SC16IS750_FIFO_RX - serial_bridge1.readableCount()); serial_bridge2.printf("Available for Writing = %3d (Used Space = %3d)\n\r", serial_bridge1.writableCount(), SC16IS750_FIFO_TX - serial_bridge1.writableCount()); } // From Serial to SPI/I2C while (running_test && serial_bridge1.readable()) { ch = serial_bridge1.getc(); running_test = (ch != '#'); serial_bridge2.putc(ch); } } serial_print2("\n\rTransparant Mode done\n\r"); break; #endif #if (0) case 'C' : serial_print2("Test printf()\n\r"); serial_bridge2.printf("Available for Reading = %3d (Free Space = %3d)\n\r", serial_bridge1.readableCount(), SC16IS750_FIFO_RX - serial_bridge1.readableCount() ); serial_bridge2.printf("Available for Writing = %3d (Used Space = %3d)\n\r", serial_bridge1.writableCount(), SC16IS750_FIFO_TX - serial_bridge1.writableCount()); serial_print2("\n\rTest printf() done\n\r"); break; #endif case 'D' : serial_print2("Test connected\n\r"); if (!serial_bridge1.connected()){ serial_print2("Failed to detect UART bridge\r\n"); } else { serial_print2("Found UART bridge!\r\n"); } break; case 'T' : serial_print2("Test ESP8266 192.168.0.6\n\r"); Address = Address_T; return_code = test(); serial_bridge2.printf("return_code = %6i\r\n", return_code); break; #if (0) case 'U' : serial_print2("Test ESP8266 192.168.0.14\n\r"); Address = Address_U; return_code = test(); serial_bridge2.printf("return_code = %6i\r\n", return_code); break; case 'V' : serial_print2("Test ESP8266 192.168.0.22\n\r"); Address = Address_V; return_code = test(); serial_bridge2.printf("return_code = %6i\r\n", return_code); break; case 'W' : serial_print2("Test ESP8266 192.168.0.23\n\r"); Address = Address_W; return_code = test(); serial_bridge2.printf("return_code = %6i\r\n", return_code); break; #endif case 'W' : serial_print2("Toggle ECHO mode\n\r"); echo_comands = ~echo_comands; serial_bridge2.printf("ECHO is %s\n\r", echo_comands ? "on" : "off"); break; case 'Z' : serial_print2("Toggle DEBUG mode\n\r"); DEBUG = ~DEBUG; serial_bridge2.printf("DEBUG is %s\n\r", DEBUG ? "on" : "off"); while (0) { serial_bridge2.printf("%6d %s\n\r", __LINE__, __FUNCTION__); debug_print(__LINE__, __FUNCTION__); } break; default : break; } // switch serial_print2(">"); } // if } // while #endif return(0); } double ROBOT::convert(char* buffer) { double val = ((buffer[0] << 2) | (buffer[1] >> 6)); if (val > 511.0) val -= 1024.0; return val / 512.0; } void ROBOT::printDouble(double value, int x, int y) { char buffer[10]; int len = sprintf(buffer, "%.1f", value); this->disp.drawString(x, y, buffer, DisplayN18::WHITE, DisplayN18::BLACK); } void ROBOT::drawAxes() { for (int i = 0; i < 3; i++) { this->disp.drawLine(0, i * (ROBOT::GRAPH_HEIGHT + ROBOT::GRAPH_SPACING), 0, i * (ROBOT::GRAPH_HEIGHT + ROBOT::GRAPH_SPACING) + ROBOT::GRAPH_HEIGHT, DisplayN18::WHITE); this->disp.drawLine(0, i * (ROBOT::GRAPH_HEIGHT + ROBOT::GRAPH_SPACING) + ROBOT::GRAPH_HEIGHT / 2, DisplayN18::WIDTH, i * (ROBOT::GRAPH_HEIGHT + ROBOT::GRAPH_SPACING) + ROBOT::GRAPH_HEIGHT / 2, DisplayN18::WHITE); } } void ROBOT::drawPoint(int axis, double value) { if (value < -1.0) value = -1.0; if (value > 1.0) value = 1.0; value += 1.0; value /= 2.0; value = 1.0 - value; value *= ROBOT::GRAPH_HEIGHT; this->disp.setPixel(this->graphX, axis * (ROBOT::GRAPH_HEIGHT + ROBOT::GRAPH_SPACING) + (int)value, this->colors[axis]); } void ROBOT::checkGraphReset() { if (this->graphX > DisplayN18::WIDTH) { this->graphX = 0; this->disp.clear(); this->drawAxes(); } } void ROBOT::initialize() { this->initializeBall(); this->paddleX = DisplayN18::WIDTH / 2 - ROBOT::PADDLE_WIDTH / 2; this->pwmTicksLeft = 0; this->lives = 4; this->pwm.period_ms(1); this->pwm.write(0.00); this->disp.clear(); } void ROBOT::initializeBall() { this->ballX = DisplayN18::WIDTH / 2 - ROBOT::BALL_RADIUS; this->ballY = DisplayN18::HEIGHT / 4 - ROBOT::BALL_RADIUS; this->ballSpeedX = rand() % 2 ? 1 : -1; this->ballSpeedY = rand() % 2 ? 1 : -1; } void ROBOT::tick() { this->checkButtons(); this->clearPaddle(); this->clearBall(); this->updatePaddle(); this->updateBall(); this->checkCollision(); this->drawPaddle(); this->drawBall(); this->checkPwm(); this->checkLives(); wait_ms(25); } void ROBOT::checkButtons() { if (!this->square.read()) { this->mode = !this->mode; this->disp.clear(); if (!this->mode) { this->graphX = 0; this->drawAxes(); } this->led1.write(this->mode); this->led2.write(!this->mode); } bool xDir = this->ballSpeedX > 0; bool yDir = this->ballSpeedY > 0; bool isUp = !this->up.read(); bool isDown = !this->down.read(); if (isUp && isDown) goto end; if (!isUp && !isDown) goto end; if (isUp && this->lastUp) goto end; if (isDown && this->lastDown) goto end; if (!xDir) this->ballSpeedX *= -1; if (!yDir) this->ballSpeedY *= -1; if (isUp) { if (++this->ballSpeedX > 5) this->ballSpeedX = 5; if (++this->ballSpeedY > 5) this->ballSpeedY = 5; } else if (isDown) { if (--this->ballSpeedX == 0) this->ballSpeedX = 1; if (--this->ballSpeedY == 0) this->ballSpeedY = 1; } if (!xDir) this->ballSpeedX *= -1; if (!yDir) this->ballSpeedY *= -1; end: this->lastUp = isUp; this->lastDown = isDown; } void ROBOT::drawString(const char* str, int y) { this->disp.drawString(DisplayN18::WIDTH / 2 - (DisplayN18::CHAR_WIDTH + DisplayN18::CHAR_SPACING) * strlen(str) / 2, y, str, DisplayN18::WHITE, DisplayN18::BLACK); } void ROBOT::showSplashScreen() { this->disp.drawLine(0, 0, DisplayN18::WIDTH, DisplayN18::HEIGHT, DisplayN18::WHITE); this->disp.drawLine(0, DisplayN18::HEIGHT, DisplayN18::WIDTH, 0, DisplayN18::WHITE); while (this->circle.read()) wait_ms(1); this->disp.clear(); } void ROBOT::clearPaddle() { this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - ROBOT::PADDLE_HEIGHT, ROBOT::PADDLE_WIDTH, ROBOT::PADDLE_HEIGHT, DisplayN18::BLACK); } void ROBOT::drawPaddle() { this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - ROBOT::PADDLE_HEIGHT, ROBOT::PADDLE_WIDTH, ROBOT::PADDLE_HEIGHT, DisplayN18::BLUE); } void ROBOT::updatePaddle() { if (this->left.read()) this->paddleX += ROBOT::PADDLE_SPEED; if (this->right.read()) this->paddleX -= ROBOT::PADDLE_SPEED; } void ROBOT::clearBall() { this->disp.fillRect(this->ballX - ROBOT::BALL_RADIUS, ballY - ROBOT::BALL_RADIUS, ROBOT::BALL_RADIUS * 2, ROBOT::BALL_RADIUS * 2, DisplayN18::BLACK); } void ROBOT::drawBall() { this->disp.fillRect(this->ballX - ROBOT::BALL_RADIUS, ballY - ROBOT::BALL_RADIUS, ROBOT::BALL_RADIUS * 2, ROBOT::BALL_RADIUS * 2, DisplayN18::RED); } void ROBOT::updateBall() { this->ballX += this->ballSpeedX; this->ballY += this->ballSpeedY; } void ROBOT::checkCollision() { if (this->paddleX < 0) this->paddleX = 0; if (this->paddleX + ROBOT::PADDLE_WIDTH > DisplayN18::WIDTH) this->paddleX = DisplayN18::WIDTH - ROBOT::PADDLE_WIDTH; if ((this->ballX - ROBOT::BALL_RADIUS < 0 && this->ballSpeedX < 0) || (this->ballX + ROBOT::BALL_RADIUS >= DisplayN18::WIDTH && this->ballSpeedX > 0)) this->ballSpeedX *= -1; if (this->ballY - ROBOT::BALL_RADIUS < 0 && this->ballSpeedY < 0) this->ballSpeedY *= -1; if (this->ballY + ROBOT::BALL_RADIUS >= DisplayN18::HEIGHT - ROBOT::PADDLE_HEIGHT && this->ballSpeedY > 0) { if (this->ballY + ROBOT::BALL_RADIUS >= DisplayN18::HEIGHT) { this->initializeBall(); this->lives--; } else if (this->ballX > this->paddleX && this->ballX < this->paddleX + ROBOT::PADDLE_WIDTH) { this->ballSpeedY *= -1; this->pwmTicksLeft = ROBOT::BOUNCE_SOUND_TICKS; } } } void ROBOT::checkPwm() { if (this->pwmTicksLeft == 0) { this->pwm.write(0.0); } else { this->pwmTicksLeft--; this->pwm.write(0.5); } } void ROBOT::checkLives() { if (this->lives == 0) { this->disp.clear(); this->drawString(ROBOT::LOSE_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT); this->drawString(ROBOT::LOSE_2, DisplayN18::HEIGHT / 2); while (this->circle.read()) wait_ms(1); this->initialize(); } else { this->disp.drawCharacter(0, 0, static_cast<char>(this->lives + '0'), DisplayN18::WHITE, DisplayN18::BLACK); } }