#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <PrintEx.h>
#include "data_types.h"
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
StreamEx fmt = Serial;
image_data_t target = {240, 240, 40};
void setup() {
Serial.begin(9600);
tft.begin();
tft.setRotation(4);
}
void loop(void) {
//refresh display
clearScreen();
drawTarget(target);
shootSensors(); //draw sensors below image, for debug visualization
fmt.println("generating sample group");
//generate sample shots
for(int i=0; i<10; i++){
float shotX = randomf(-120,120);
float shotY = randomf(0,240);
fmt.printf("Shot %i: [%f, %f]\n", i+1, shotX, shotY);
shot_data_t testShot = {shotX, shotY, 5.56f};
drawShot(testShot);
delay(2000);
}
fmt.println("group complete.\nclearing in 10s...");
delay(10000);
}
// generate random float within bounds
float randomf(float minf, float maxf){
return map(random(0, 1000), 0, 1000, minf, maxf);
}
// clear display
void clearScreen(){
fmt.println("clearing display");
tft.fillScreen(ILI9341_BLACK);
}
// draw a sample target
void drawTarget(image_data_t t){
fmt.println("drawing target");
//draw target boundary (this could be an image)
tft.fillRect(0, 0, t.widthCm, t.heightCm, ILI9341_WHITE);
// draw a simple aiming point with some rings
uint16_t centerX = t.widthCm / 2;
uint16_t centerY = t.heightCm / 2;
uint16_t ringSize = t.radiusCm / 5;
bool darkRing = true;
for(int drawSize = t.radiusCm; drawSize > 0; drawSize -= ringSize){
tft.fillCircle(centerX, centerY, drawSize, darkRing ? ILI9341_DARKGREY : ILI9341_LIGHTGREY);
darkRing = !darkRing;
}
}
// send shots at each 'sensor' in an offset position to show
// on the screen where they are relative to the display image.
void shootSensors(){
uint16_t backSensorOffset = -20;
uint16_t frontSensorOffset = -40;
shot_data_t sensor1 = {-55, backSensorOffset, 12.0f};
shot_data_t sensor2 = {0, backSensorOffset, 12.0f};
shot_data_t sensor3 = {55, backSensorOffset, 12.0f};
shot_data_t sensor4 = {-55, frontSensorOffset, 12.0f};
shot_data_t sensor5 = {0, frontSensorOffset, 12.0f};
shot_data_t sensor6 = {55, frontSensorOffset, 12.0f};
drawShot(sensor1);
drawShot(sensor2);
drawShot(sensor3);
drawShot(sensor4);
drawShot(sensor5);
drawShot(sensor6);
}
// draw a shot relative to the display image
void drawShot(shot_data_t data){
//start in the 'center' of the displayed target, offset should be the same for both
float shotRelativeX = (target.widthCm / 2.0f) + data.xCm;
//invert vertical position to be relative to bottom of image
float shotRelativeY = target.heightCm - data.yCm;
//draw emphasis (make small bullets more visible)
float emphasisDia = target.widthCm * 0.025; // size relative to screen/image size rather than physical size.
tft.fillCircle(shotRelativeX, shotRelativeY, emphasisDia, ILI9341_PINK);
//draw bullet
float shotRadiusCm = data.caliberCm / 2.0; //calculate radius for draw function.
shotRadiusCm = max(1, shotRadiusCm); // ensure radius greater than or equal to 1
tft.fillCircle(shotRelativeX, shotRelativeY, shotRadiusCm, ILI9341_RED);
}