aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile35
-rw-r--r--README.md30
-rw-r--r--include/rctp.h50
-rw-r--r--kociemba/Makefile44
-rw-r--r--kociemba/README.md0
-rw-r--r--master/CMakeLists.txt8
-rw-r--r--master/README.md0
-rw-r--r--master/main/CMakeLists.txt2
-rw-r--r--master/main/main.c34
-rw-r--r--slave/Makefile0
-rw-r--r--slave/README.md0
12 files changed, 207 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c29eb74
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+**/bin/
+**/obj/
+**/build/
+**/sdkconfig \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..be34b04
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+PORT ?= ttyUSB0
+
+ifeq ($(origin IDF_PATH),undefined)
+IDF_ENV=0
+else
+IDF_ENV=1
+endif
+
+all: kociemba master slave
+
+kociemba slave:
+ $(MAKE) -C $(shell pwd)/$@ all PROD=1
+
+master:
+ifeq ($(IDF_ENV), 1)
+ cd $(shell pwd)/$@ && PATH=$(PATH) idf.py build
+else
+ @echo "FAILED: ESP-IDF export script is not sourced!"
+ @echo -e "\t(use 'source <esp-idf path>/export.sh')"
+ @exit 1
+endif
+
+run: kociemba slave master
+ifeq ($(FLASH),1)
+ifeq ($(IDF_ENV),1)
+ cd $(shell pwd)/master && idf.py flash -p $(PORT)
+else
+ @echo "FAILED: FLASH is set to 1 but ESP-IDS export script is not sourced!"
+ @exit 1
+endif
+endif
+ $(MAKE) -C $(shell pwd)/kociemba run
+
+
+.PHONY: all kociemba slave master run
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3898a1f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+### Rubik's Cube Solving Robot
+
+This repository is for a robot that solves the rubik's cube. The idea is that after a scrambled rubik's cube has been places in the robot, an ESP32 (master) gets the cube's state (using 2 cameras, looking at opposite corners, each seeing 3 faces). The data is then sent to a more powerful computer (slave) which puts the data through [kociemba's algorithm](http://kociemba.org/cube.htm). The solution is then sent back to the master for servos to execute and (hopefully) solve the cube.
+
+#### Master-Slave Relationship
+
+The data is sent through the default UART connection between the master and the slave in the simple RCTP protocol (Rubik's Cube Transfer Protocol) (see `include/rctp.h`) (Note that both machines have to have the same endianess since the protocol is binary)
+
+### Building
+
+The projects can all be built separately, but only the implementation of kociemba's algorithm (`kociemba/`) can be useful on its own.
+
+- **`kociemba/`:** built using `GNU make` (`kociemba/README.md` for more details)
+
+- **`slave/`:** built using `GNU make` (`slave/README.md` for more details)
+
+ - **`master/`:** in contrast with the other parts, the master is built using`esp-idf`'s build system (`master/README.md` for more details)
+
+The Makfile in the root of this repo is a wrapper around the other build systems, so just use:
+
+- **`make all/kociemba/slave/master`** to build all or a single one (with nondebug flags)
+
+- **`make run [FLASH=1] [PORT=ttyUSBn]`** to build and run the slave, and when `FLASH` is set the master program is flashed, and when `PORT` is set, the given port is tried instead of the default `ttyUSB0`
+
+Note that building `master/` using the wrapper requires the `esp-idf` export script to be sourced.
+
+### References
+
+- <http://kociemba.org/cube.htm>
+- <https://docs.espressif.com/projects/esp-idf/en/latest/esp32/index.html>
diff --git a/include/rctp.h b/include/rctp.h
new file mode 100644
index 0000000..71aa812
--- /dev/null
+++ b/include/rctp.h
@@ -0,0 +1,50 @@
+#ifndef RCTP_H
+#define RCTP_H
+
+typedef unsigned char rctp_byte;
+
+typedef struct request rctp_req_t;
+typedef struct response rctp_res_t;
+
+typedef enum {
+ RCTP_OK = 0,
+ RCTP_ERROR, // unknown error
+
+ RCTP_UNKNOWN_METHOD,
+ RCTP_UNKNOWN_STATUS,
+
+ RCTP_INVALID_STRING,
+} RCTP_STAT;
+
+#define RCTP_METHODS(X) \
+ X(PING) \
+
+#define RCTP_STATUSES(X) \
+ X(PONG) \
+
+#define TO_ENUM(s) s,
+#define TO_STR(s) #s,
+
+enum rctp_method {
+ RCTP_METHODS(TO_ENUM)
+} __attribute__((packed));
+
+enum rctp_status {
+ RCTP_STATUSES(TO_ENUM)
+} __attribute__((packed));
+
+struct request {
+ enum rctp_req method;
+ union {
+ /* ... */
+ };
+} __attribute__((packed));
+
+struct response {
+ enum rctp_res status;
+ union {
+ /* ... */
+ };
+} __attribute__((packed));
+
+#endif
diff --git a/kociemba/Makefile b/kociemba/Makefile
new file mode 100644
index 0000000..61fa1aa
--- /dev/null
+++ b/kociemba/Makefile
@@ -0,0 +1,44 @@
+CC := gcc
+AR := ar
+
+ifeq ($(PROD),1)
+CFLAGS := -std=c99 -O2 # production flags
+else
+CFLAGS := -std=c99 -Wall -Wextra -Wpedantic -g -DDEBUG # debug flags
+endif
+
+SRCD := src
+OBJD := obj
+BIND := bin
+
+FILES = $(shell find $(SRCD)/ -type f 2> /dev/null)
+CSRCS = $(filter %.c, $(FILES))
+COBJS = $(CSRCS:$(SRCD)/%.c=$(OBJD)/%.o)
+
+CDEPS = $(COBJS:%.o=%.d)
+-include $(CDEPS)
+
+NAME := kociemba
+
+all: standalone lib
+
+standalone $(NAME): $(BIND)/$(NAME)
+static $(NAME).a: $(BIND)/$(NAME).a
+
+clean:
+ rm -rf $(OBJD)
+ rm -rf $(BIND)
+
+$(OBJD)/%.o: $(SRCD)/%.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -c $< -o $@
+
+$(BIND)/$(NAME): $(COBJS)
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $^ -o $@
+
+$(BIND)/$(NAME).a: $(COBJS)
+ @mkdir -p $(dir $@)
+ $(AR) rsc $@ $^
+
+.PHONY: all standalone lib clean $(NAME) $(NAME).a
diff --git a/kociemba/README.md b/kociemba/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kociemba/README.md
diff --git a/master/CMakeLists.txt b/master/CMakeLists.txt
new file mode 100644
index 0000000..664d458
--- /dev/null
+++ b/master/CMakeLists.txt
@@ -0,0 +1,8 @@
+# For more information about build system see
+# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
+# The following five lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(main)
diff --git a/master/README.md b/master/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/master/README.md
diff --git a/master/main/CMakeLists.txt b/master/main/CMakeLists.txt
new file mode 100644
index 0000000..cf2c455
--- /dev/null
+++ b/master/main/CMakeLists.txt
@@ -0,0 +1,2 @@
+idf_component_register(SRCS "main.c"
+ INCLUDE_DIRS ".")
diff --git a/master/main/main.c b/master/main/main.c
new file mode 100644
index 0000000..ee170bc
--- /dev/null
+++ b/master/main/main.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include "driver/uart.h"
+
+#define ECHECK(...) ESP_ERROR_CHECK(__VA_ARGS__)
+
+QueueHandle_t uart_queue;
+
+void uart_setup(void);
+
+void app_main(void)
+{
+ uart_setup();
+
+ char message[] = "Hello World\n";
+ uart_write_bytes(UART_NUM_0, message, sizeof(message));
+}
+
+void uart_setup(void)
+{
+ // stty -F /dev/ttyUSB0 cs8 -parenb -crtscts -cstopb
+ uart_config_t uart_config = {
+ .baud_rate = 9600,
+ .data_bits = UART_DATA_8_BITS,
+ .parity = UART_PARITY_DISABLE,
+ .stop_bits = UART_STOP_BITS_1,
+ .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
+ .source_clk = UART_SCLK_DEFAULT,
+ };
+
+ #define UART_BUFFER_SIZE 2048
+ ECHECK(uart_param_config(UART_NUM_0, &uart_config));
+ ECHECK(uart_driver_install(UART_NUM_0, UART_BUFFER_SIZE, UART_BUFFER_SIZE, 10, &uart_queue, 0));
+}
+
diff --git a/slave/Makefile b/slave/Makefile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/slave/Makefile
diff --git a/slave/README.md b/slave/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/slave/README.md