Uploaded main files

Added main GrainOS, license and documentation files.
This commit is contained in:
dangrain 2025-06-25 10:11:00 +02:00
commit b059500a70
3 changed files with 369 additions and 0 deletions

295
GrainOS.ino Normal file
View file

@ -0,0 +1,295 @@
#include <WiFi.h>
struct File {
String name;
String content;
bool used;
};
const int MAX_FILES = 10; //file limit
File files[MAX_FILES];
void clearScreen() {
for (int i = 0; i < 50; i++) {
Serial.println(); //function that clears your screen (again this is stupid)
}
}
void listFiles() {
Serial.println("Files:");
for (int i = 0; i < MAX_FILES; i++) {
if (files[i].used) { //FUNCTION THAT MAKES LS WORK
Serial.println("- " + files[i].name);
}
}
}
void writeFile(String name, String content) {
for (int i = 0; i < MAX_FILES; i++) {
if (!files[i].used) {
files[i].name = name; //function that writes to file
files[i].content = content;
files[i].used = true;
Serial.println("File written: " + name);
return;
}
}
Serial.println("Error: No space left in RAM!");
}
void readFile(String name) {
for (int i = 0; i < MAX_FILES; i++) {
if (files[i].used && files[i].name == name) {
Serial.println("Content of " + name + ": " + files[i].content); //function that reads written files
return;
}
}
Serial.println("Error: File not found!");
}
void deleteFile(String name) {
for (int i = 0; i < MAX_FILES; i++) {
if (files[i].used && files[i].name == name) {
files[i].used = false; // Marks files as deleted
Serial.println("Deleted file: " + name);
return;
}
}
Serial.println("Error: File not found!"); // WAH WAH WAH
}
void showHelp() { //I think this is fairly self explanatory, but still, making sure. It's just the guts of the `help` command
Serial.println("Available commands:");
Serial.println(" clear - Clears the screen");
Serial.println(" echo <message> - Prints the message");
Serial.println(" format(\"text,text,text\") - Formats input");
Serial.println(" write <filename> <content> - Writes content to a file");
Serial.println(" read <filename> - Reads and prints the content of a file");
Serial.println(" delete <filename> - Deletes a file");
Serial.println(" ls - Lists all files");
Serial.println(" help - Displays this help message");
Serial.println(" calc <number> <operator> <number> - calculates command");
Serial.println(" run <script.gs> - Runs a script file");
Serial.println(" loop <number> <command> - Loops a command the inputted amout of times");
Serial.println(" high <pin-number> - sets the inputted pin to high");// 12
Serial.println(" low <pin-number> - sets the inputted pin to low"); //13
}
void calculate(String input) {
int firstSpace = input.indexOf(' ');
int secondSpace = input.indexOf(' ', firstSpace + 1); // this is likely not the best way to do this as It takes up a *lot* of space, but hey. It works. I'll see If I keep It.
if (firstSpace == -1 || secondSpace == -1) {
Serial.println("Usage: calc <number> <operator> <number>");
return;
}
String num1Str = input.substring(0, firstSpace);
String op = input.substring(firstSpace + 1, secondSpace);
String num2Str = input.substring(secondSpace + 1);
float num1 = num1Str.toFloat();
float num2 = num2Str.toFloat();
float result;
if (op == "+") {
result = num1 + num2;
}
else if (op == "-") {
result = num1 - num2;
}
else if (op == "*") {
result = num1 * num2;
}
else if (op == "/") {
if (num2 == 0) {
Serial.println("Error: Division by zero");
return;
}
result = num1 / num2;
}
else {
Serial.println("Error: Unknown operator. Use +, -, *, or /");
return;
}
Serial.println(String(result));
}
void runScript(String name) { //script interpreter!
if (!name.endsWith(".gs")) {
Serial.println("Must end with .gs!");
return;
}
for (int i = 0; i < MAX_FILES; i++) {
if (files[i].used && files[i].name == name) {
Serial.println("Running script: " + name);
String content = files[i].content;
content.replace("\\n", "\n");
int start = 0;
while (start < content.length()) {
int end = content.indexOf('\n', start);
if (end == -1) end = content.length();
String command = content.substring(start, end);
command.trim();
Serial.print("Extracted Command: [");
Serial.print(command);
Serial.println("]");
if (command.length() > 0) {
Serial.println("> " + command);
processCommand(command);
}
start = end + 1;
}
return;
}
}
Serial.println("Error: No script found.");
}
void loopCommand(String input) {
int firstSpace = input.indexOf(' ');
if (firstSpace == -1) {
Serial.println("Use `help`");
return;
}
String numStr = input.substring(0, firstSpace); // loop command !
String command = input.substring(firstSpace + 1);
int times = numStr.toInt();
if (times <= 0) {
Serial.println("Must be positive number");
return;
}
for (int i = 0; i < times; i++) {
processCommand(command);
}
}
void setPinLow(String input) {
int pin = input.toInt();
if (pin >= 0) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
Serial.println("Pin " + String(pin) + " set to LOW");
} else {
Serial.println("Invalid pin number");
}
}
void setPinHigh(String input) {
int pin = input.toInt();
if (pin >= 0){
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
Serial.println("Pin " + String(pin) + " set to HIGH");
} else {
Serial.println("Invalid pin number");
}
}
void processCommand(String input) {
input.trim();
if (input == "clear") {
clearScreen();
}
else if (input.startsWith("echo ")) {
String message = input.substring(5);
message.trim();
Serial.println(message);
}
else if (input.startsWith("format(") && input.endsWith(")")) {
input = input.substring(7, input.length() - 1);
input.replace("\"", "");
input.replace(",", " ");
Serial.println(input);
}
else if (input.startsWith("write ")) {
int space = input.indexOf(' ', 6);
if (space != -1) {
String name = input.substring(6, space);
String content = input.substring(space + 1);
writeFile(name, content);
} else {
Serial.println("use `help`");
}
}
else if (input.startsWith("read ")) {
String name = input.substring(5);
readFile(name);
}
else if (input.startsWith("delete ")) {
String name = input.substring(7);
deleteFile(name);
}
else if (input == "ls") {
listFiles();
}
else if (input == "help") {
showHelp();
}
else if (input.startsWith("calc ")) {
calculate(input.substring(5));
}
else if (input == "cat"){
Serial.println(" /\\_/\\");
Serial.println("( o.o )");
Serial.println("/> ^ <\\");
}
else if (input.startsWith("loop ")) {
loopCommand(input.substring(5));
}
else if (input.startsWith("high ")) {
setPinHigh(input.substring(5));
}
else if (input.startsWith("low ")){
setPinLow(input.substring(4));
}
else if (input.startsWith("send ")){ // sends UART messages (pin 1) exclusive
String message = input.substring(5);
message.trim();
Serial1.println(message);
Serial.println("Sent '" + message + "'");
}
else {
Serial.println("Unknown command " + input); //changed this because I realized It makes more sense
}
}
void setup() {
Serial.begin(9600);
delay(500);
Serial.println("Welcome to GrainOS 1.8.3, `help` for a list of commands");
Serial1.begin(9600, SERIAL_8N1, -1, 1);
}
void loop() { //the script runner :)
if (Serial.available()) {
String input = Serial.readStringUntil(' \n');
input.trim();
if (input.startsWith("run ")) {
String scriptName = input.substring(4);
runScript(scriptName);
} else {
processCommand(input);
}
}
}

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Dangrain
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
README.md Normal file
View file

@ -0,0 +1,53 @@
# Usage tutorial
For a most basic overview, you can always type `help` in the terminal, but not all commands are shown there due to memory restrictions.
# General terminal commands
`help` will display the help menu which will tell you about *most* commands.
`echo` will print anything you write behind it right back to the terminal - Usage input: `echo <text>`, output: `<text>`
`clear` will clear the terminal of any existing text on It, `clear` command doesn't take any arguments - Usage input: `clear`
`format` will format any string(s) you write behind It - Usage `format("<text", "<text>", "<text>")`, output: `<text> <text> <text>`
`loop` will loop any command behind It for the specified amount of times - Usage `loop <number> <command>`
`calc` will calculate any two numbers specified and with the operation you specified - Usage `calc <number> <operation> <number>`, output: `<result>`
(And a secret command `cat`, which prints a cute little kitty to your terminal! :) prrr lol)
# File manipulation commands
`write` will write to a file - Usage input: `write <filename> <content>`, takes `\n` as sign to move to a new line, useful for scripts!
`read` will read from a file as long as It exists - Usage input: `read <filename>`, output: `<content>`
`ls` will list all existing files - Usage input: `ls`, output: `Files - ...`
`delete` will delete the specified file as long as It exists - Usage input `delete <filename>`
# Hardware commands
`high` will set the specified pin to high - Usage input: `high <pinnumber>`
`low` will set the specified pin to low - Usage input: `low <pinnumber>`
`send` will send the specified message as UART on pin 2
# G-Script run command
`run` will run any G-Script files specified - Usage input: `run <scriptname.gs>`
# G-Script usage
G-Script is very simple and is a way of automating commands within files. Essentially It just bundles commands and executes them in the order that they were typed in.
To let the system know that you are writing a G-Script file, It has to end with the .gs suffix. To run a G-Script file utilize the `run` command.