chore: import local project into Gitea

This commit is contained in:
2026-05-20 10:04:29 -07:00
commit 0969724f16
7 changed files with 420 additions and 0 deletions

30
.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# OS / tooling
.DS_Store
Thumbs.db
# Editors
.cursor/
# Secrets
.env
.env.*
!.env.example
!.env.template
# Python
__pycache__/
*.py[cod]
.venv/
venv/
# Node / frontend
node_modules/
dist/
# Typical embedded / tooling noise
*.log
# Builds (adjust per subtree if needed)
**/build/.ninja_deps
**/build/.ninja_log

18
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "windows-gcc-x64",
"includePath": [
"${workspaceFolder}/**"
],
"compilerPath": "gcc",
"cStandard": "${default}",
"cppStandard": "${default}",
"intelliSenseMode": "windows-gcc-x64",
"compilerArgs": [
""
]
}
],
"version": 4
}

24
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++ Runner: Debug Session",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"externalConsole": true,
"cwd": "f:/dev_shit/p4 pannel",
"program": "f:/dev_shit/p4 pannel/build/Debug/outDebug",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

59
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,59 @@
{
"C_Cpp_Runner.cCompilerPath": "gcc",
"C_Cpp_Runner.cppCompilerPath": "g++",
"C_Cpp_Runner.debuggerPath": "gdb",
"C_Cpp_Runner.cStandard": "",
"C_Cpp_Runner.cppStandard": "",
"C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat",
"C_Cpp_Runner.useMsvc": false,
"C_Cpp_Runner.warnings": [
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wshadow",
"-Wformat=2",
"-Wcast-align",
"-Wconversion",
"-Wsign-conversion",
"-Wnull-dereference"
],
"C_Cpp_Runner.msvcWarnings": [
"/W4",
"/permissive-",
"/w14242",
"/w14287",
"/w14296",
"/w14311",
"/w14826",
"/w44062",
"/w44242",
"/w14905",
"/w14906",
"/w14263",
"/w44265",
"/w14928"
],
"C_Cpp_Runner.enableWarnings": true,
"C_Cpp_Runner.warningsAsError": false,
"C_Cpp_Runner.compilerArgs": [],
"C_Cpp_Runner.linkerArgs": [],
"C_Cpp_Runner.includePaths": [],
"C_Cpp_Runner.includeSearch": [
"*",
"**/*"
],
"C_Cpp_Runner.excludeSearch": [
"**/build",
"**/build/**",
"**/.*",
"**/.*/**",
"**/.vscode",
"**/.vscode/**"
],
"C_Cpp_Runner.useAddressSanitizer": false,
"C_Cpp_Runner.useUndefinedSanitizer": false,
"C_Cpp_Runner.useLeakSanitizer": false,
"C_Cpp_Runner.showCompilationTime": false,
"C_Cpp_Runner.useLinkTimeOptimization": false,
"C_Cpp_Runner.msvcSecureNoWarnings": false
}

13
README.md Normal file
View File

@@ -0,0 +1,13 @@
# P4 voice panel
Bundles **`voice_assistant/`** firmware plus `.vscode`/`.cursor` configs and **`example.code`**.
Treat this as companion UI work to **`p4 chatbot 83125/`** unless you refactor modules.
Recommended flow:
```bash
cd voice_assistant
```
Follow manifests inside (`CMakeLists.txt`, `sdkconfig.defaults`, Arduino project files, etc.—whichever framework that folder uses). Keep generated `build/` / `.pio/` directories excluded from commits.

128
example.code Normal file
View File

@@ -0,0 +1,128 @@
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED config
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define I2C_SDA 21
#define I2C_SCL 22
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// WiFi
const char* ssid = "your wifi id";
const char* password = "your wifi password";
const String gemini_api_key = "your api key";
// MAX9814 microphone input pin
#define MIC_PIN 34
void setup() {
Serial.begin(115200);
delay(1000);
Wire.begin(I2C_SDA, I2C_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED init failed!");
while (1);
}
displayMessage("Connecting WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
displayMessage("WiFi connected!");
pinMode(MIC_PIN, INPUT);
delay(500);
displayMessage("Ready! Speak loud...");
}
void loop() {
static unsigned long lastTrigger = 0;
int micValue = analogRead(MIC_PIN);
Serial.println(micValue);
if (micValue > 1500 && millis() - lastTrigger > 5000) {
lastTrigger = millis();
displayMessage("Detecting...");
String response = askGemini("who are you.");
displayMultilineText(response);
}
delay(100);
}
void displayMessage(String msg) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(msg);
display.display();
}
void displayMultilineText(String text) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
int maxCharsPerLine = 21;
int lineHeight = 10;
int y = 0;
while (text.length() > 0 && y < SCREEN_HEIGHT) {
String line = text.substring(0, maxCharsPerLine);
text = text.substring(min((unsigned int)maxCharsPerLine, text.length()));
display.setCursor(0, y);
display.println(line);
y += lineHeight;
}
display.display();
}
// Gemini API call
String askGemini(String prompt) {
HTTPClient http;
String endpoint = "https://generativelanguage.googleapis.com/v1/models/gemini-1.5-flash-002:generateContent?key=" + gemini_api_key;
http.begin(endpoint);
http.addHeader("Content-Type", "application/json");
prompt.replace("\"", "\\\"");
String requestBody = "{ \"contents\": [ { \"parts\": [ { \"text\": \"" + prompt + "\" } ] } ] }";
int code = http.POST(requestBody);
String reply = "";
if (code == 200) {
String payload = http.getString();
StaticJsonDocument<2048> doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
reply = doc["candidates"][0]["content"]["parts"][0]["text"].as<String>();
reply.replace("\\n", "\n");
} else {
Serial.println("JSON Error: " + String(error.c_str()));
reply = "I am Gemini, your AI assistant.";
}
} else {
Serial.println("Gemini API error: " + String(code));
// Fallback reply when API fails
reply = "I am Gemini, your AI assistant.";
}
http.end();
return reply;
}

View File

@@ -0,0 +1,148 @@
// Include necessary libraries
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// WiFi credentials
const char* ssid = "thetempleofdoom";
const char* password = "myhandsonmyself";
// Gemini API key
const char* geminiApiKey = "AIzaSyAzFzg_MAcwoH3O-nfriBjlFw5x6UBU5hk";
// Pin for the button
// IMPORTANT: Please verify the pin number for your button and update the value below.
const int buttonPin = 0;
// Display pins
// IMPORTANT: Please verify the pin numbers for your display and update the values below.
#define TFT_CS 5
#define TFT_DC 4
#define TFT_RST -1 // Reset pin (often not needed)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
void setup() {
// Initialize serial communication
Serial.begin(115200);
// Initialize the button pin
pinMode(buttonPin, INPUT_PULLUP);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Initialize the display
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(2);
tft.println("Hacker Voice Assistant");
tft.println("--------------------");
tft.setTextSize(1);
tft.print("IP: ");
tft.println(WiFi.localIP());
tft.setTextSize(2);
tft.println("\nReady for command...");
}
void loop() {
// Check if the button is pressed
if (digitalRead(buttonPin) == LOW) {
// Start a voice session
startVoiceSession();
// After the session, clear the screen and show the ready message again
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0,0);
tft.setTextSize(2);
tft.println("Hacker Voice Assistant");
tft.println("--------------------");
tft.setTextSize(1);
tft.print("IP: ");
tft.println(WiFi.localIP());
tft.setTextSize(2);
tft.println("\nReady for command...");
}
}
void startVoiceSession() {
// Clear the screen for the new session
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0,0);
tft.setTextSize(2);
// TODO: Add voice recording and processing code here
Serial.println("Button pressed, starting voice session...");
displayHackerText("Listening...");
// For now, we'll just send a test query to Gemini
delay(2000); // Simulate recording time
displayHackerText("Processing...");
String query = "Hello, Gemini!";
String response = sendToGemini(query);
// Display the response
displayHackerText("User: " + query);
displayHackerText("Gemini: " + response);
Serial.println("Gemini response: " + response);
}
String sendToGemini(String query) {
HTTPClient http;
String url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=";
url += geminiApiKey;
http.begin(url);
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> doc;
JsonObject content = doc.createNestedObject("contents");
JsonArray parts = content.createNestedArray("parts");
JsonObject part = parts.createNestedObject();
part["text"] = query;
String requestBody;
serializeJson(doc, requestBody);
int httpResponseCode = http.POST(requestBody);
if (httpResponseCode > 0) {
String payload = http.getString();
StaticJsonDocument<1024> responseDoc;
DeserializationError error = deserializeJson(responseDoc, payload);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return "Error: Failed to parse response.";
}
if (responseDoc.containsKey("candidates")) {
const char* responseText = responseDoc["candidates"][0]["content"]["parts"][0]["text"];
return String(responseText);
} else {
return "Error: Invalid response from Gemini.";
}
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
return "Error: Unable to get response from Gemini.";
}
http.end();
return "";
}
void displayHackerText(String text) {
tft.println(text);
}