organism #3
21
organism/Makefile
Normal file
21
organism/Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Uncomment lines below if you have problems with $PATH
|
||||||
|
#SHELL := /bin/bash
|
||||||
|
#PATH := /usr/local/bin:$(PATH)
|
||||||
|
|
||||||
|
all:
|
||||||
|
pio.exe -f -c vim run
|
||||||
|
|
||||||
|
upload:
|
||||||
|
pio.exe -f -c vim run --target upload
|
||||||
|
|
||||||
|
clean:
|
||||||
|
pio.exe -f -c vim run --target clean
|
||||||
|
|
||||||
|
program:
|
||||||
|
pio.exe -f -c vim run --target program
|
||||||
|
|
||||||
|
uploadfs:
|
||||||
|
pio.exe -f -c vim run --target uploadfs
|
||||||
|
|
||||||
|
update:
|
||||||
|
pio.exe -f -c vim update
|
22
organism/platformio.ini
Normal file
22
organism/platformio.ini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:adafruit_matrixportal_esp32s3]
|
||||||
|
platform = espressif32
|
||||||
|
board = adafruit_matrixportal_esp32s3
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
adafruit/Adafruit GFX Library
|
||||||
|
adafruit/Adafruit BusIO
|
||||||
|
Wire
|
||||||
|
fastled/FastLED
|
||||||
|
https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA.git
|
105
organism/src/blur.cpp
Normal file
105
organism/src/blur.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "constants.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
void setupGaussianKernel(float* kernel, int width, float sigma) {
|
||||||
|
float sum = 0.0;
|
||||||
|
for(int i = 0; i < width; i++) {
|
||||||
|
//kernel[width+i] = exp( -(i*i) / (2 * sigma * sigma)) / (PI * 2 * sigma * sigma);
|
||||||
|
kernel[i] = exp(-0.5f * (i * i) / (sigma * sigma));
|
||||||
|
sum += kernel[width];
|
||||||
|
}
|
||||||
|
for(int i; i < width; i++) {
|
||||||
|
kernel[i] = sum/width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//float first_pass[PANEL_WIDTH][PANEL_HEIGHT];
|
||||||
|
void gaussian_blur(float *field[PANEL_WIDTH][PANEL_HEIGHT]) {
|
||||||
|
float kernel[GAUSS_WIDTH];
|
||||||
|
float first_pass[PANEL_WIDTH][PANEL_HEIGHT];
|
||||||
|
memset(first_pass, 0.0, sizeof first_pass);
|
||||||
|
setupGaussianKernel(kernel, GAUSS_WIDTH, GAUSS_SIGMA);
|
||||||
|
// horizontal pass
|
||||||
|
for (int x = 0; x < PANEL_WIDTH; x++) {
|
||||||
|
for(int y = 0; y < PANEL_HEIGHT; y++) {
|
||||||
|
float sum = *field[x][y] * DECAY_FACTOR * kernel[0]; //0.0;
|
||||||
|
int additions = 1;
|
||||||
|
for (int x_offset = 1; x_offset < GAUSS_WIDTH; x_offset++) {
|
||||||
|
if (is_in_bounds(x+x_offset, y)) {
|
||||||
|
sum += *field[x + x_offset][y] * kernel[x_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
if (is_in_bounds(x-x_offset, y)) {
|
||||||
|
sum += *field[x - x_offset][y] * kernel[x_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first_pass[x][y] = sum/GAUSS_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// vertical pass
|
||||||
|
for (int x = 0; x < PANEL_WIDTH; x++) {
|
||||||
|
for(int y = 0; y < PANEL_HEIGHT; y++) {
|
||||||
|
float sum = first_pass[x][y] * kernel[0]; //0.0;
|
||||||
|
int additions = 1;
|
||||||
|
for (int y_offset = 1; y_offset < GAUSS_WIDTH; y_offset++) {
|
||||||
|
if (is_in_bounds(x, y + y_offset)) {
|
||||||
|
sum += first_pass[x][y + y_offset] * kernel[y_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
if (is_in_bounds(x, y - y_offset)) {
|
||||||
|
sum += first_pass[x][y - y_offset] * kernel[y_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*field[x][y] = sum/GAUSS_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void box_blur(float field[PANEL_WIDTH][PANEL_HEIGHT]) {
|
||||||
|
auto first_pass = new float[PANEL_WIDTH][PANEL_HEIGHT]();
|
||||||
|
// horizontal pass
|
||||||
|
for (int x = 0; x < PANEL_WIDTH; x++) {
|
||||||
|
for(int y = 0; y < PANEL_HEIGHT; y++) {
|
||||||
|
float sum;
|
||||||
|
sum = field[x][y] * DECAY_FACTOR; //0.0;
|
||||||
|
int additions = 1;
|
||||||
|
for (int x_offset = 1; x_offset < BLUR_KERNEL_SIZE; x_offset++) {
|
||||||
|
if (is_in_bounds(x+x_offset, y)) {
|
||||||
|
sum += field[x + x_offset][y];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
if (is_in_bounds(x-x_offset, y)) {
|
||||||
|
sum += field[x - x_offset][y];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first_pass[x][y] = (sum/additions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// vertical pass
|
||||||
|
for (int x = 0; x < PANEL_WIDTH; x++) {
|
||||||
|
for(int y = 0; y < PANEL_HEIGHT; y++) {
|
||||||
|
float sum = first_pass[x][y]; //0.0;
|
||||||
|
int additions = 1;
|
||||||
|
for (int y_offset = 1; y_offset < BLUR_KERNEL_SIZE; y_offset++) {
|
||||||
|
if (is_in_bounds(x, y + y_offset)) {
|
||||||
|
sum += first_pass[x][y + y_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
if (is_in_bounds(x, y - y_offset)) {
|
||||||
|
sum += first_pass[x][y - y_offset];
|
||||||
|
additions++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float result = (sum/additions); // * DECAY_FACTOR;
|
||||||
|
//attractant[x][y] = (((8.0*attractant[x][y]) + result) / 9.0);
|
||||||
|
field[x][y] = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] first_pass;
|
||||||
|
}
|
3
organism/src/blur.h
Normal file
3
organism/src/blur.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "constants.h"
|
||||||
|
void gaussian_blur(float *field[PANEL_WIDTH][PANEL_HEIGHT]);
|
||||||
|
void box_blur(float field[PANEL_WIDTH][PANEL_HEIGHT]);
|
18
organism/src/config.h
Normal file
18
organism/src/config.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// gaussian blur
|
||||||
|
#define GAUSS_WIDTH 1
|
||||||
|
#define GAUSS_SIGMA 1.0
|
||||||
|
#define DECAY_FACTOR 0.9
|
||||||
|
// box blur
|
||||||
|
#define BLUR_KERNEL_SIZE 1
|
||||||
|
// agent params
|
||||||
|
#define NUM_AGENTS_MIN 64
|
||||||
|
#define NUM_AGENTS_MAX 301
|
||||||
|
#define AGENT_DROP_AMOUNT 10
|
||||||
|
#define AGENT_SENSOR_DISTANCE_MIN 2.0
|
||||||
|
#define AGENT_SENSOR_DISTANCE_MAX 3.5
|
||||||
|
// general params
|
||||||
|
#define NUM_ITERATIONS 500
|
||||||
|
#define SPAWN_MIN_X 2
|
||||||
|
#define SPAWN_MAX_X 63
|
||||||
|
#define SPAWN_MIN_Y 2
|
||||||
|
#define SPAWN_MAX_Y 31
|
26
organism/src/constants.h
Normal file
26
organism/src/constants.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#define R1 42
|
||||||
|
#define G1 40
|
||||||
|
#define BL1 41
|
||||||
|
#define R2 38
|
||||||
|
#define G2 37
|
||||||
|
#define BL2 39
|
||||||
|
#define CH_A 45
|
||||||
|
#define CH_B 36
|
||||||
|
#define CH_C 48
|
||||||
|
#define CH_D 35
|
||||||
|
#define CH_E 21
|
||||||
|
#define CLK 2
|
||||||
|
#define LAT 47
|
||||||
|
#define OE 14
|
||||||
|
|
||||||
|
#define PIN_E 21
|
||||||
|
#define PANEL_WIDTH 64
|
||||||
|
#define PANEL_HEIGHT 32 // Panel height of 64 will required PIN_E to be defined.
|
||||||
|
|
||||||
|
#define PANELS_NUMBER 1
|
||||||
|
|
||||||
|
#define PANE_WIDTH PANEL_WIDTH * PANELS_NUMBER
|
||||||
|
#define PANE_HEIGHT PANEL_HEIGHT
|
||||||
|
#define NUM_LEDS PANE_WIDTH*PANE_HEIGHT
|
||||||
|
|
||||||
|
#define ONBOARD_LED 13
|
177
organism/src/main.cpp
Normal file
177
organism/src/main.cpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "xtensa/core-macros.h"
|
||||||
|
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "overlay.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "visual.h"
|
||||||
|
#include "blur.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
MatrixPanel_I2S_DMA *matrix = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
struct SlimeAgent {
|
||||||
|
int x_position;
|
||||||
|
int y_position;
|
||||||
|
float heading;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int NUM_AGENTS;
|
||||||
|
int AGENT_MOVE_DISTANCE;
|
||||||
|
float AGENT_SENSOR_DISTANCE;
|
||||||
|
float AGENT_MOVE_ANGLE;
|
||||||
|
float AGENT_SENSOR_ANGLE;
|
||||||
|
|
||||||
|
float attractant[PANEL_WIDTH][PANEL_HEIGHT] = {};
|
||||||
|
int iterations = 0;
|
||||||
|
std::vector<SlimeAgent> agents;
|
||||||
|
|
||||||
|
void init_attractant() {
|
||||||
|
memset(attractant, 0.0, sizeof attractant);
|
||||||
|
// draw a circle out of attractant
|
||||||
|
//for (int p = 0; p < PANEL_WIDTH; p++) {
|
||||||
|
// float angle = ((PI * 2) / PANEL_WIDTH) * p;
|
||||||
|
// int x = PANEL_WIDTH/2 + round(10 * sin(angle));
|
||||||
|
// int y = PANEL_WIDTH/2 + round(10 * cos(angle));
|
||||||
|
// attractant[x][y] = 15.0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// draw a bitmap
|
||||||
|
//for(int x = 0; x < PANEL_WIDTH; x++) {
|
||||||
|
// for(int y = 0; y < PANEL_HEIGHT; y++) {
|
||||||
|
// int pixel_num = (y * PANEL_WIDTH) + x;
|
||||||
|
// if(overlay[ pixel_num / 8 ] & (1 << (7 - (pixel_num % 8)) ) ){
|
||||||
|
// attractant[x][y] = 255.0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_agents() {
|
||||||
|
AGENT_MOVE_DISTANCE = 1;
|
||||||
|
AGENT_MOVE_ANGLE = 0.175;//random(0, 334) / 1000.0;
|
||||||
|
//if (random(0, 2) > 0) {
|
||||||
|
// AGENT_SENSOR_ANGLE = 0.175;
|
||||||
|
//} else {
|
||||||
|
AGENT_SENSOR_ANGLE = 0.0875;
|
||||||
|
//}
|
||||||
|
AGENT_SENSOR_DISTANCE = random(AGENT_SENSOR_DISTANCE_MIN * 1000.0, AGENT_SENSOR_DISTANCE_MAX * 1000.0) / 1000.0;
|
||||||
|
NUM_AGENTS = random(NUM_AGENTS_MIN, NUM_AGENTS_MAX);
|
||||||
|
|
||||||
|
agents.clear();
|
||||||
|
for(int a = 0; a < NUM_AGENTS; a++) {
|
||||||
|
float angle = ((PI * 2) / NUM_AGENTS) * a;
|
||||||
|
//agents[a].x_position = 31 + round(10*sin(angle));
|
||||||
|
//agents[a].y_position = 15 + round(10*cos(angle));
|
||||||
|
// agents[a].heading = ((PI * 2) / NUM_AGENTS) * );
|
||||||
|
agents.push_back({
|
||||||
|
random(SPAWN_MIN_X, SPAWN_MAX_X),
|
||||||
|
random(SPAWN_MIN_Y, SPAWN_MAX_Y),
|
||||||
|
(random(0, 100) / 100.0) * (PI*2)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(BAUD_RATE);
|
||||||
|
//while (!Serial) {
|
||||||
|
// ; // wait for serial port to connect. Needed for native USB
|
||||||
|
//}
|
||||||
|
pinMode(ONBOARD_LED, OUTPUT);
|
||||||
|
|
||||||
|
// redefine pins if required
|
||||||
|
HUB75_I2S_CFG::i2s_pins _pins={R1, G1, BL1, R2, G2, BL2, CH_A, CH_B, CH_C, CH_D, CH_E, LAT, OE, CLK};
|
||||||
|
HUB75_I2S_CFG mxconfig(PANEL_WIDTH, PANEL_HEIGHT, PANELS_NUMBER, _pins);
|
||||||
|
|
||||||
|
mxconfig.gpio.e = PIN_E;
|
||||||
|
mxconfig.driver = HUB75_I2S_CFG::FM6126A; // for panels using FM6126A chips
|
||||||
|
|
||||||
|
mxconfig.latch_blanking = 4;
|
||||||
|
mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M;
|
||||||
|
mxconfig.clkphase = false;
|
||||||
|
|
||||||
|
mxconfig.double_buff = true;
|
||||||
|
|
||||||
|
matrix = new MatrixPanel_I2S_DMA(mxconfig);
|
||||||
|
matrix->begin();
|
||||||
|
matrix->setBrightness8(64);
|
||||||
|
matrix->fillScreenRGB888(0, 0, 0);
|
||||||
|
|
||||||
|
init_agents();
|
||||||
|
init_attractant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
matrix ->flipDMABuffer();
|
||||||
|
delay(10);
|
||||||
|
matrix->fillScreenRGB888(15, 0, 10);
|
||||||
|
|
||||||
|
// draw background and organism
|
||||||
|
draw_bg(matrix);
|
||||||
|
draw_attractant(matrix, attractant);
|
||||||
|
|
||||||
|
for(int a = 0; a < NUM_AGENTS; a++) {
|
||||||
|
//matrix->drawPixel(agents[a].x_position, agents[a].y_position, matrix->color565(0, 0, attractant[agents[a].x_position][agents[a].y_position]));
|
||||||
|
// motor step: check if agent can move forward
|
||||||
|
// if yes, do so, if not, turn randomly
|
||||||
|
float target_x = agents[a].x_position + cos(agents[a].heading) * AGENT_MOVE_DISTANCE;
|
||||||
|
float target_y = agents[a].y_position + sin(agents[a].heading) * AGENT_MOVE_DISTANCE;
|
||||||
|
int move_x = round(target_x);
|
||||||
|
int move_y = round(target_y);
|
||||||
|
if (is_in_bounds(move_x, move_y)) {
|
||||||
|
agents[a].x_position = move_x;
|
||||||
|
agents[a].y_position = move_y;
|
||||||
|
if (attractant[move_x][move_y] < 255.0 - AGENT_DROP_AMOUNT) {
|
||||||
|
attractant[move_x][move_y] += AGENT_DROP_AMOUNT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
agents[a].heading = (random(0, 100)/100.0) * (PI*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sample step - check the 3 positions
|
||||||
|
for(int a = 0; a < NUM_AGENTS; a++) {
|
||||||
|
//matrix->drawPixel(agents[a].x_position, agents[a].y_position, matrix->color565(0, 0, attractant[agents[a].x_position][agents[a].y_position]));
|
||||||
|
int front_x = round(agents[a].x_position + cos(agents[a].heading) * AGENT_SENSOR_DISTANCE);
|
||||||
|
int front_y = round(agents[a].y_position + sin(agents[a].heading) * AGENT_SENSOR_DISTANCE);
|
||||||
|
int left_x = round(agents[a].x_position + cos(agents[a].heading - (AGENT_SENSOR_ANGLE * (PI * 2))) * AGENT_SENSOR_DISTANCE);
|
||||||
|
int left_y = round(agents[a].y_position + sin(agents[a].heading - (AGENT_SENSOR_ANGLE * (PI * 2))) * AGENT_SENSOR_DISTANCE);
|
||||||
|
int right_x = round(agents[a].x_position + cos(agents[a].heading + (AGENT_SENSOR_ANGLE * (PI * 2))) * AGENT_SENSOR_DISTANCE);
|
||||||
|
int right_y = round(agents[a].y_position + sin(agents[a].heading + (AGENT_SENSOR_ANGLE * (PI * 2))) * AGENT_SENSOR_DISTANCE);
|
||||||
|
float front_value = attractant[front_x][front_y];
|
||||||
|
float left_value = attractant[left_x][left_y];
|
||||||
|
float right_value = attractant[right_x][right_y];
|
||||||
|
if (front_value > right_value and front_value > left_value) {
|
||||||
|
;
|
||||||
|
} else if (front_value < right_value and front_value < left_value) {
|
||||||
|
agents[a].heading += (random(0, 2) * 2 - 1) * (AGENT_MOVE_ANGLE / 100.0) * (PI*2) ;
|
||||||
|
} else if (left_value > right_value) {
|
||||||
|
agents[a].heading -= AGENT_MOVE_ANGLE * (PI * 2);
|
||||||
|
} else {
|
||||||
|
agents[a].heading += AGENT_MOVE_ANGLE * (PI * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterations++;
|
||||||
|
if (iterations % 2 == 0) { //64 && iterations % 64 == 0) { // (( == 0) {
|
||||||
|
box_blur(attractant);
|
||||||
|
//gaussian_blur();
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (iterations >= NUM_ITERATIONS) {
|
||||||
|
//cleanup();
|
||||||
|
if (cleanup(matrix, &iterations)) {
|
||||||
|
init_attractant();
|
||||||
|
init_agents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
10
organism/src/main.h
Normal file
10
organism/src/main.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <FastLED.h>
|
||||||
|
|
||||||
|
#define BAUD_RATE 115200 // serial debug port baud rate
|
||||||
|
|
||||||
|
void buffclear(CRGB *buf);
|
||||||
|
uint16_t XY16( uint16_t x, uint16_t y);
|
||||||
|
void mxfill(CRGB *leds);
|
||||||
|
uint16_t colorWheel(uint8_t pos);
|
||||||
|
void drawText(int colorWheelOffset);
|
||||||
|
|
19
organism/src/overlay.h
Normal file
19
organism/src/overlay.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const unsigned char overlay [] PROGMEM = {
|
||||||
|
// 'bw2, 64x32px
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
|
||||||
|
0x01, 0xf8, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x80, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x80,
|
||||||
|
0x01, 0xff, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x80, 0x01, 0xc7, 0x80, 0x00, 0x00, 0x1c, 0x00, 0x00,
|
||||||
|
0x01, 0xc3, 0x80, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x01, 0xc3, 0x8f, 0xe1, 0xbe, 0x1c, 0x7b, 0x80,
|
||||||
|
0x01, 0xc3, 0x8f, 0xe1, 0xff, 0x1c, 0x73, 0x80, 0x01, 0xc3, 0x88, 0x71, 0xe7, 0x1c, 0xe3, 0x80,
|
||||||
|
0x01, 0xc3, 0x80, 0x71, 0xc3, 0x9d, 0xe3, 0x80, 0x01, 0xff, 0x00, 0x71, 0xc3, 0x9d, 0xc3, 0x80,
|
||||||
|
0x01, 0xff, 0x03, 0xf1, 0xc3, 0x9f, 0x83, 0x80, 0x01, 0xfc, 0x0f, 0xf1, 0xc3, 0x9f, 0xc3, 0x80,
|
||||||
|
0x01, 0xc0, 0x1f, 0x71, 0xc3, 0x9f, 0xc3, 0x80, 0x01, 0xc0, 0x3c, 0x71, 0xc3, 0x9d, 0xe3, 0x80,
|
||||||
|
0x01, 0xc0, 0x38, 0x71, 0xc3, 0x9c, 0xe3, 0x80, 0x01, 0xc0, 0x38, 0x71, 0xc3, 0x9c, 0xf3, 0x80,
|
||||||
|
0x01, 0xc0, 0x1c, 0xf1, 0xc3, 0x9c, 0x73, 0x80, 0x01, 0xc0, 0x1f, 0xf1, 0xc3, 0x9c, 0x7b, 0x80,
|
||||||
|
0x01, 0xc0, 0x0f, 0xb1, 0x83, 0x9c, 0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
5
organism/src/util.cpp
Normal file
5
organism/src/util.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
bool is_in_bounds(int x, int y) {
|
||||||
|
return (x < PANEL_WIDTH) and (y < PANEL_HEIGHT) and (x >= 0) and (y >= 0);
|
||||||
|
}
|
2
organism/src/util.h
Normal file
2
organism/src/util.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bool is_in_bounds(int x, int y);
|
||||||
|
|
54
organism/src/visual.cpp
Normal file
54
organism/src/visual.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "constants.h"
|
||||||
|
#include "visual.h"
|
||||||
|
|
||||||
|
void draw_bg(MatrixPanel_I2S_DMA *matrix) {
|
||||||
|
int h_lines = round(PANEL_HEIGHT / 7);
|
||||||
|
int v_lines = round(PANEL_WIDTH / 7);
|
||||||
|
for(int v = 0; v <= v_lines; v++) {
|
||||||
|
matrix->drawFastVLine(v*7+2, 0, PANEL_HEIGHT, matrix->color565(41, 17, 76));
|
||||||
|
}
|
||||||
|
for(int h = 0; h <= h_lines; h++) {
|
||||||
|
matrix->drawFastHLine(0, 7*h + 1, PANEL_WIDTH, matrix->color565(41, 17, 76));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_attractant(MatrixPanel_I2S_DMA *matrix, float attractant[PANEL_WIDTH][PANEL_HEIGHT]) {
|
||||||
|
for(int x = 0; x<PANEL_WIDTH; x++) {
|
||||||
|
for(int y = 0; y<PANEL_HEIGHT; y++){
|
||||||
|
if (attractant[x][y] > 15.0) {
|
||||||
|
matrix->drawPixel(x, y, matrix->color565(
|
||||||
|
int((255.0 / 255.0) * round(attractant[x][y])),
|
||||||
|
int((80.0 / 255.0) * round(attractant[x][y])),
|
||||||
|
int((83.0 / 255.0) * round(attractant[x][y]))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cleanup_x = 0;
|
||||||
|
bool cleanup(MatrixPanel_I2S_DMA *matrix, int* iterations) {
|
||||||
|
int progress = *iterations - NUM_ITERATIONS;
|
||||||
|
matrix->drawFastVLine(cleanup_x, 0, PANEL_HEIGHT, matrix->color565(254, 242, 255));
|
||||||
|
if (cleanup_x > 0) {
|
||||||
|
matrix->fillRect(0, 0, cleanup_x, PANEL_HEIGHT, matrix->color565(16, 0, 16));
|
||||||
|
}
|
||||||
|
int h_lines = round(PANEL_HEIGHT / 7);
|
||||||
|
int v_lines = round(cleanup_x / 7);
|
||||||
|
for(int v = 0; v < cleanup_x; v++) {
|
||||||
|
if (v%7 == 2) {
|
||||||
|
matrix->drawFastVLine(v, 0, PANEL_HEIGHT, matrix->color565(41, 17, 76));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int h = 0; h <= h_lines; h++) {
|
||||||
|
matrix->drawFastHLine(0, 7*h + 1, cleanup_x-1, matrix->color565(41, 17, 76));
|
||||||
|
}
|
||||||
|
cleanup_x++;
|
||||||
|
if (cleanup_x > PANEL_WIDTH) {
|
||||||
|
*iterations = 0;
|
||||||
|
cleanup_x = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
6
organism/src/visual.h
Normal file
6
organism/src/visual.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||||
|
#include "constants.h"
|
||||||
|
#include "config.h"
|
||||||
|
void draw_bg(MatrixPanel_I2S_DMA *matrix);
|
||||||
|
void draw_attractant(MatrixPanel_I2S_DMA *matrix, float attractant[PANEL_WIDTH][PANEL_HEIGHT]);
|
||||||
|
bool cleanup(MatrixPanel_I2S_DMA *matrix, int* iterations);
|
Loading…
Reference in New Issue
Block a user