commit ba56de6d2e0b8d1f316650ccd896c269b3404c5f Author: hybris Date: Sun Feb 18 14:09:30 2024 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..e181d17 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +; 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:esp32dev] +framework = arduino +platform = espressif32 @ 4.1.0 +board = esp32dev +upload_speed = 115200 +lib_deps = + bodmer/TFT_eSPI @ ^2.5.23 + arturo182/BBQ10Keyboard@^1.1.0 diff --git a/src/main.ino b/src/main.ino new file mode 100644 index 0000000..e33b04c --- /dev/null +++ b/src/main.ino @@ -0,0 +1,352 @@ +// This will run quite slowly due to the large number of floating point calculations per pixel + +#include // Hardware-specific library +#include +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library +#define TFT_GREY 0x7BEF +#include +#include + +#include +BBQ10Keyboard keyboard; + +/* CLIENT */ +const char* ssid = "freethelong3"; +const char* password = "alle_informationen"; + +/* UDP SETUP */ +const char * udpAddress = "192.168.4.1"; +const int udpPort = 2390; +boolean connected = false; +int breakudp=0; +#define CELLXY 2 + +int findex = 0; +int s1values[15]; +int click_count = 0; + +int paint_active = 0; + +int cursor_x = 0; +int cursor_y = 0; + +uint16_t cursorColor = 0x0000; +uint8_t colorIndex = 0; + +#define GRIDX 160 +#define GRIDY 120 +#define CELLXY 12 + +#define GEN_DELAY 0 +//Current grid +uint8_t grid[GRIDX][GRIDY]; + +//The new grid for the next generation +uint8_t newgrid[GRIDX][GRIDY]; + +//Number of generations +#define NUMGEN 1200 + +uint16_t genCount = 0; + +WiFiUDP udp; + +uint8_t posX; +uint8_t posY; + +bool blink_state; + + + +void setup() { + Serial.begin(115200); + // Set initial position + posX = 0; + posY = 0; + blink_state = true; + + // Setup the LCD + tft.init(); + tft.setRotation(3); + tft.fillScreen(TFT_BLUE); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE); + tft.setCursor(0, 0); + // activate led backlight + pinMode(32, OUTPUT); + digitalWrite(32, HIGH); + + Wire.begin(); + + keyboard.begin(); + keyboard.setBacklight(0.5f); + + WiFi.begin(ssid, password); + delay(1000); + Serial.println("Connecting WiFi.."); + Serial.println(WiFi.localIP()); + Serial.println("Init complete"); + tft.println("init complete"); + tft.println(""); + delay(1000); +} + +void loop() { + const int trackpad_x = keyboard.trackpad_x(); + const int trackpad_y = keyboard.trackpad_y(); + if (trackpad_x != 0 || trackpad_y != 0) { + Serial.println("trackpad_x: "+String(trackpad_x)+"trackpad_y: "+String(trackpad_y)); + + if (paint_active == 0) tft.fillRect(cursor_x, cursor_y, CELLXY, CELLXY, TFT_BLUE); + + cursor_x += trackpad_x; + cursor_y += trackpad_y; + + if (cursor_x<0) cursor_x = 0; + if (cursor_y<0) cursor_y = 0; + if ((cursor_x)>(320-CELLXY)) cursor_x = 320-CELLXY; + if ((cursor_y)>(240-CELLXY)) cursor_y = 240-CELLXY; + + tft.fillRect(cursor_x, cursor_y, CELLXY, CELLXY, cursorColor); + } + + const int keyCount = keyboard.keyCount(); + if (keyCount == 0) + return; + + const BBQ10Keyboard::KeyEvent key = keyboard.keyEvent(); + String state = "pressed"; + if (key.state == BBQ10Keyboard::StateLongPress) { + state = "held down"; + } else if (key.state == BBQ10Keyboard::StateRelease) { + state = "released"; + + if ((uint8_t)key.key == 6) { + + if (paint_active == 1) { + paint_active = 0; + } else { + paint_active = 1; + } + } + if ((uint8_t)key.key == 18) { + colorIndex++; + uint8_t color = colorIndex % 8; + switch (color) { + case 0: + cursorColor = 0xf800; + break; + case 1: + cursorColor = 0x07e0; + break; + case 2: + cursorColor = 0x001f; + break; + case 3: + cursorColor = 0xffe0; + break; + case 4: + cursorColor = 0x07ff; + break; + case 5: + cursorColor = 0xf81f; + break; + case 6: + cursorColor = 0xfdbf; + break; + case 7: + cursorColor = 0xf652; + break; + default: + cursorColor = 0x0000; + break; + } + } + } + // Serial.printf("key: '%c' (dec %d, hex %02x) %s\r\n", key.key, key.key, key.key, state.c_str()); + + if (key.state == BBQ10Keyboard::StatePress) { + + /* TETRIS P1 RIGHT */ + if ((uint8_t)key.key == 100) { + udp.beginPacket(udpAddress,udpPort); + udp.printf("f%c",53); + udp.endPacket(); + } + + /* TETRIS P1 LEFT */ + if ((uint8_t)key.key == 97) { + udp.beginPacket(udpAddress,udpPort); + udp.printf("f%c",51); + udp.endPacket(); + } + + /* TETRIS P1 ROTATE */ + if ((uint8_t)key.key == 119) { + udp.beginPacket(udpAddress,udpPort); + udp.printf("f%c",55); + udp.endPacket(); + } + + /* TETRIS P1 DOWN */ + if ((uint8_t)key.key == 115) { + udp.beginPacket(udpAddress,udpPort); + udp.printf("f%c",54); + udp.endPacket(); + } + + if ((uint8_t)key.key == 5) { + tft.fillScreen(TFT_BLUE); + posX = 0; + posY = 0; + tft.setCursor(posX,posY); + if (click_count>6) { + click_count=0; + } else { + click_count+=1; + } + + + int sensorValue = 20; + int sensorValue2 = 20; + int sensorValue3 = 20; + Serial.println(sensorValue); + Serial.println(sensorValue2); + Serial.println(sensorValue3); + Serial.println(" "); + delay(5); + + if (breakudp==0) { + udp.beginPacket(udpAddress,udpPort); + if (click_count==0) { + sensorValue = 53; + udp.printf("e%c",sensorValue); + } + if (click_count==1) { + sensorValue = 49; + udp.printf("e%c",sensorValue); + } + if (click_count==2) { + sensorValue = 56; + udp.printf("e%c",sensorValue); + } + + if (click_count==3) { + sensorValue = 50; + udp.printf("e%c",sensorValue); + } + if (click_count==4) { + sensorValue = 51; + udp.printf("e%c",sensorValue); + } + + if (click_count==5) { + sensorValue = 57; + udp.printf("e%c",sensorValue); + } + if (click_count==6) { + sensorValue = 54; + udp.printf("e%c",sensorValue); + } + + udp.endPacket(); + } + + } + } + Serial.printf("posX: '%d' | posY: '%d' | key: '%d'\n", posX, posY, (uint8_t)key.key); +} + + +unsigned int rainbow(byte value) +{ + // Value is expected to be in range 0-127 + // The value is converted to a spectrum colour from 0 = blue through to 127 = red + + byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte green = 0;// Green is the middle 6 bits + byte blue = 0; // Blue is the bottom 5 bits + + byte quadrant = value / 32; + + if (quadrant == 0) { + blue = 31; + green = 2 * (value % 32); + red = 0; + } + if (quadrant == 1) { + blue = 31 - (value % 32); + green = 63; + red = 0; + } + if (quadrant == 2) { + blue = 0; + green = 63; + red = value % 32; + } + if (quadrant == 3) { + blue = 0; + green = 63 - 2 * (value % 32); + red = 31; + } + return (red << 11) + (green << 5) + blue; +} + +//Draws the grid on the display +void drawGrid(int gen) { + + uint16_t color = TFT_WHITE; + for (int16_t x = 1; x < GRIDX - 1; x++) { + for (int16_t y = 1; y < GRIDY - 1; y++) { + if ((grid[x][y]) != (newgrid[x][y])) { + if (newgrid[x][y] == 1) color = rainbow(map(int(gen*.09)%200, 0, 80, 0, 100));//color = 0xF000; //random(0xFFFF); + else color = 0; + tft.fillRect(CELLXY * x, CELLXY * y, CELLXY, CELLXY, color); + } + } + } +} + +//Initialise Grid +void initGrid(void) { + for (int16_t x = 0; x < GRIDX; x++) { + for (int16_t y = 0; y < GRIDY; y++) { + newgrid[x][y] = 0; + + if (x == 0 || x == GRIDX - 1 || y == 0 || y == GRIDY - 1) { + grid[x][y] = 0; + } + else { + if (random(12) == 1) + grid[x][y] = 1; + else + grid[x][y] = 0; + } + + } + } +} + +//Compute the CA. Basically everything related to CA starts here +void computeCA() { + for (int16_t x = 1; x < GRIDX; x++) { + for (int16_t y = 1; y < GRIDY; y++) { + int neighbors = getNumberOfNeighbors(x, y); + if (grid[x][y] == 1 && (neighbors == 2 || neighbors == 3 )) + { + newgrid[x][y] = 1; + } + else if (grid[x][y] == 1) newgrid[x][y] = 0; + if (grid[x][y] == 0 && (neighbors == 3)) + { + newgrid[x][y] = 1; + } + else if (grid[x][y] == 0) newgrid[x][y] = 0; + } + } +} + +// Check the Moore neighbourhood +int getNumberOfNeighbors(int x, int y) { + return grid[x - 1][y] + grid[x - 1][y - 1] + grid[x][y - 1] + grid[x + 1][y - 1] + grid[x + 1][y] + grid[x + 1][y + 1] + grid[x][y + 1] + grid[x - 1][y + 1]; +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html