commit b059500a70513f8265faa78d1985efd033087fb7 Author: dangrain Date: Wed Jun 25 10:11:00 2025 +0200 Uploaded main files Added main GrainOS, license and documentation files. diff --git a/GrainOS.ino b/GrainOS.ino new file mode 100644 index 0000000..533e598 --- /dev/null +++ b/GrainOS.ino @@ -0,0 +1,295 @@ +#include + +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 - Prints the message"); + Serial.println(" format(\"text,text,text\") - Formats input"); + Serial.println(" write - Writes content to a file"); + Serial.println(" read - Reads and prints the content of a file"); + Serial.println(" delete - Deletes a file"); + Serial.println(" ls - Lists all files"); + Serial.println(" help - Displays this help message"); + Serial.println(" calc - calculates command"); + Serial.println(" run - Runs a script file"); + Serial.println(" loop - Loops a command the inputted amout of times"); + Serial.println(" high - sets the inputted pin to high");// 12 + Serial.println(" low - 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 "); + 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); + } + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4ed1619 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9e44ed2 --- /dev/null +++ b/README.md @@ -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 `, output: `` + +`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("", "")`, output: ` ` + +`loop` will loop any command behind It for the specified amount of times - Usage `loop ` + +`calc` will calculate any two numbers specified and with the operation you specified - Usage `calc `, output: `` + + (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 `, 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 `, output: `` + +`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 ` + +# Hardware commands + +`high` will set the specified pin to high - Usage input: `high ` + +`low` will set the specified pin to low - Usage input: `low ` + +`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 ` + +# 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. + + + + + +