/* * SSL_GFX.cpp * * Created on: Feb 11, 2024 * Author: Gabriel */ #include "SSL_GFX.hpp" #include "BMplain_font.h" SSL_GFX::SSL_GFX(ILI9341* hDisplay, uint16_t posX, uint16_t posY, uint8_t hBuffer[][sizeX][3], uint32_t size) : hDisplay(hDisplay), posX(posX), posY(posY), hBuffer(hBuffer), size(size){ } SSL_GFX::~SSL_GFX() { } int32_t SSL_GFX::init() { int32_t errors = 0; return errors; } int32_t SSL_GFX::draw() { if(size != sizeY*sizeX*3){ // Invalid parameter return -1; } int32_t errors = 0; uint8_t colorBoundingBox[3]; if(robotStatus.connected){ colorBoundingBox[0] = 0; colorBoundingBox[1] = 0xFC; colorBoundingBox[2] = 0; }else{ colorBoundingBox[0] = 0xFC; colorBoundingBox[1] = 0; colorBoundingBox[2] = 0; } errors += drawBoundingBox(colorBoundingBox); uint8_t colorRobot[3] = {0b11111100, 0b11111100, 0b11111100}; errors += drawRobotSilhouette(colorRobot); errors += drawId(colorRobot); errors += drawBatteryBar(); errors += drawRobotLid(); errors += drawRobotTeam(); errors += drawBall(); errors += hDisplay->setPosition(posX, posY, sizeX, sizeY); errors += hDisplay->write((uint8_t*)hBuffer, 19200); return errors; } int32_t SSL_GFX::setRobotStatus(RobotStatus status) { robotStatus = status; return 0; } // Private methods int32_t SSL_GFX::drawBoundingBox(uint8_t color[3]) { for(uint32_t i=0; i= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; for(uint32_t i=0; i<3; i++){ hBuffer[y0 + y][x0 + x][i] = color[i]; hBuffer[y0 + y][x0 - x][i] = color[i]; //hBuffer[y0 - y][x0 + x][i] = color[i]; //hBuffer[y0 - y][x0 - x][i] = color[i]; hBuffer[y0 + x][x0 + y][i] = color[i]; hBuffer[y0 + x][x0 - y][i] = color[i]; hBuffer[y0 - x][x0 + y][i] = color[i]; hBuffer[y0 - x][x0 - y][i] = color[i]; } } while(x>=0){ for(uint32_t i=0; i<3; i++){ hBuffer[y0 - y][x0 + x][i] = color[i]; hBuffer[y0 - y][x0 - x][i] = color[i]; } x--; } return 0; } int32_t SSL_GFX::drawRobotLid() { uint32_t errors = 0; uint8_t colorPurple[3] = {0xFC, 0x00, 0xFC}; uint8_t colorGreen[3] = {0x00, 0xFC, 0x00}; uint8_t* colorCircle[4]; switch(robotStatus.robotId){ case 0: colorCircle[0] = colorPurple; colorCircle[1] = colorPurple; colorCircle[2] = colorGreen; colorCircle[3] = colorPurple; break; case 1: colorCircle[0] = colorGreen; colorCircle[1] = colorPurple; colorCircle[2] = colorGreen; colorCircle[3] = colorPurple; break; case 2: colorCircle[0] = colorGreen; colorCircle[1] = colorGreen; colorCircle[2] = colorGreen; colorCircle[3] = colorPurple; break; case 3: colorCircle[0] = colorPurple; colorCircle[1] = colorGreen; colorCircle[2] = colorGreen; colorCircle[3] = colorPurple; break; case 4: colorCircle[0] = colorPurple; colorCircle[1] = colorPurple; colorCircle[2] = colorPurple; colorCircle[3] = colorGreen; break; case 5: colorCircle[0] = colorGreen; colorCircle[1] = colorPurple; colorCircle[2] = colorPurple; colorCircle[3] = colorGreen; break; case 6: colorCircle[0] = colorGreen; colorCircle[1] = colorGreen; colorCircle[2] = colorPurple; colorCircle[3] = colorGreen; break; case 7: colorCircle[0] = colorPurple; colorCircle[1] = colorGreen; colorCircle[2] = colorPurple; colorCircle[3] = colorGreen; break; case 8: colorCircle[0] = colorGreen; colorCircle[1] = colorGreen; colorCircle[2] = colorGreen; colorCircle[3] = colorGreen; break; case 9: colorCircle[0] = colorPurple; colorCircle[1] = colorPurple; colorCircle[2] = colorPurple; colorCircle[3] = colorPurple; break; case 10: colorCircle[0] = colorPurple; colorCircle[1] = colorPurple; colorCircle[2] = colorGreen; colorCircle[3] = colorGreen; break; case 11: colorCircle[0] = colorGreen; colorCircle[1] = colorGreen; colorCircle[2] = colorPurple; colorCircle[3] = colorPurple; break; } errors += drawCircle(colorCircle[0], 28, 33, 4); errors += drawCircle(colorCircle[1], 52, 33, 4); errors += drawCircle(colorCircle[2], 32, 52, 4); errors += drawCircle(colorCircle[3], 48, 52, 4); return errors; } int32_t SSL_GFX::drawRobotTeam(){ uint8_t colorTobotTeam[3]; if(robotStatus.team){ colorTobotTeam[0] = 0b11111100; colorTobotTeam[1] = 0b11111100; colorTobotTeam[2] = 0; }else{ colorTobotTeam[0] = 0; colorTobotTeam[1] = 0; colorTobotTeam[2] = 0b11111100; } return drawCircle(colorTobotTeam, 40, 40, 5); } int32_t SSL_GFX::drawBall() { int32_t errors = 0; uint8_t hasBallColor[3] = {0xFC, 0xA0, 0x00}; uint8_t noBallColor[3] = {0x00, 0x00, 0x00}; if(robotStatus.status&1){ drawCircle(hasBallColor, 40, 21, 4); }else{ drawCircle(noBallColor, 40, 21, 4); } return errors; } int32_t SSL_GFX::drawId(uint8_t color[3]) { uint32_t errors = 0; errors += drawText(color, 3, 71, (uint8_t*)"ID = ", 5); if(robotStatus.robotId<10){ uint8_t robotIdChar[2] = {robotStatus.robotId+48, 32}; errors += drawText(color, 33, 71, robotIdChar, 2); }else{ uint8_t robotIdChar[2] = {49, robotStatus.robotId+(uint8_t)38}; errors += drawText(color, 33, 71, robotIdChar, 2); } return errors; } int32_t SSL_GFX::drawBatteryBar() { uint32_t errors = 0; for(uint32_t j = 3; j<7; j++){ for(uint32_t k = 3; k<77; k++){ if(robotStatus.batteryLevel*74 > k-3){ if(robotStatus.batteryLevel>0.5){ hBuffer[j][k][0] = ((uint8_t)(512-robotStatus.batteryLevel*512))&0xFC; hBuffer[j][k][1] = 255&0xFC; hBuffer[j][k][2] = 0; }else{ hBuffer[j][k][0] = 255&0xFC; hBuffer[j][k][1] = ((uint8_t)(robotStatus.batteryLevel*511))&0xFC; hBuffer[j][k][2] = 0; } }else{ hBuffer[j][k][0] = 0; hBuffer[j][k][1] = 0; hBuffer[j][k][2] = 0; } } } return errors; } int32_t SSL_GFX::drawText(uint8_t color[3], uint16_t posX, uint16_t posY, uint8_t* string, uint32_t size) { if(posX+6*size > sizeX){ // Out of bounds return -1; } if(posY+6 > sizeY){ // Out of bounds return -1; } for(uint32_t i = 0; i>(j))&1){ hBuffer[j+posY][k+posX][0] = color[0]; hBuffer[j+posY][k+posX][1] = color[1]; hBuffer[j+posY][k+posX][2] = color[2]; }else{ hBuffer[j+posY][k+posX][0] = 0; hBuffer[j+posY][k+posX][1] = 0; hBuffer[j+posY][k+posX][2] = 0; } } } posX += 6; } return 0; } int32_t SSL_GFX::drawCircle(uint8_t color[3], uint16_t posX, uint16_t posY, uint16_t radius) { uint32_t errors = 0; uint8_t corners = 3; uint8_t delta = 0; int16_t x0 = posX; int16_t y0 = posY; int16_t r = radius; int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r; int16_t px = x; int16_t py = y; delta++; // Avoid some +1's in the loop for(uint32_t i=0; i < 2*r + 1; i++){ hBuffer[i + y0 - r][x0][0] = color[0]; hBuffer[i + y0 - r][x0][1] = color[1]; hBuffer[i + y0 - r][x0][2] = color[2]; } while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; // These checks avoid double-drawing certain lines, important // for the SSD1306 library which has an INVERT drawing mode. if (x < (y + 1)) { if (corners & 1) for(uint32_t i=0; i<2*y + delta; i++){ hBuffer[i + y0 - y][x0 + x][0] = color[0]; hBuffer[i + y0 - y][x0 + x][1] = color[1]; hBuffer[i + y0 - y][x0 + x][2] = color[2]; } if (corners & 2) for(uint32_t i=0; i<2*y + delta; i++){ hBuffer[i + y0 - y][x0 - x][0] = color[0]; hBuffer[i + y0 - y][x0 - x][1] = color[1]; hBuffer[i + y0 - y][x0 - x][2] = color[2]; } } if (y != py) { if (corners & 1) for(uint32_t i=0; i<2*px + delta; i++){ hBuffer[i + y0 - px][x0 + py][0] = color[0]; hBuffer[i + y0 - px][x0 + py][1] = color[1]; hBuffer[i + y0 - px][x0 + py][2] = color[2]; } if (corners & 2) for(uint32_t i=0; i<2*px + delta; i++){ hBuffer[i + y0 - px][x0 - py][0] = color[0]; hBuffer[i + y0 - px][x0 - py][1] = color[1]; hBuffer[i + y0 - px][x0 - py][2] = color[2]; } py = y; } px = x; } return errors; }