Uploaded main files
Added main GrainOS, license and documentation files.
This commit is contained in:
commit
b059500a70
3 changed files with 369 additions and 0 deletions
295
GrainOS.ino
Normal file
295
GrainOS.ino
Normal 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
21
LICENSE
Normal 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
53
README.md
Normal 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue