Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,41 @@ project(StenoByte_Prototype C)

set(CMAKE_C_STANDARD 23)

find_package(PkgConfig REQUIRED)
pkg_search_module(LIBEVDEV REQUIRED libevdev)

add_executable(StenoByte_Prototype main.c
StenoByte_Helper.c
StenoByte_Helper.h)
target_include_directories(StenoByte_Prototype PRIVATE ${LIBEVDEV_INCLUDE_DIRS})
target_link_libraries(StenoByte_Prototype PRIVATE ${LIBEVDEV_LIBRARIES})
# Linux Variant
if (LINUX)
# Finds Libevdev Library
find_package(PkgConfig REQUIRED)
pkg_search_module(LIBEVDEV REQUIRED libevdev)

# Prints Location of Libevdev Library
message(STATUS "libevdev include dirs: ${LIBEVDEV_INCLUDE_DIRS}")
message(STATUS "libevdev libraries: ${LIBEVDEV_LIBRARIES}")

## StenoByte Library for Linux Library
add_library(StenoByte_Library STATIC
includes/StenoByte_Helper_for_Linux.c
includes/StenoByte_Core.c)
target_include_directories(StenoByte_Library PRIVATE
${LIBEVDEV_INCLUDE_DIRS}
includes)
target_link_libraries(StenoByte_Library PRIVATE ${LIBEVDEV_LIBRARIES})

# MacOS Variant
elseif (APPLE)
message(FATAL_ERROR "Unfortunately StenoByte is not yet compatible with MacOS,
but support for MacOS is in the works!")

# Windows Variant
elseif (WIN32)
message(FATAL_ERROR "Unfortunately StenoByte is not yet compatible with Windows,
but support for Windows is in the works!")

# Throws an error if system is incompatible
else ()
message(FATAL_ERROR "Unfortunately your system is not compatible with StenoByte")
endif ()

# Main App
add_executable(StenoByte_Prototype main.c)
target_include_directories(StenoByte_Prototype PRIVATE ${LIBEVDEV_INCLUDE_DIRS} StenoByte_Library)
target_link_libraries(StenoByte_Prototype PRIVATE ${LIBEVDEV_LIBRARIES} StenoByte_Library)
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
A stenotype inspired terminal app for typing out bytes quickly.

This program is designed to allow you to build up a byte using eight keys from your keyboard, with each key
corresponding to a bit in a byte (which is made up of eight bits). When you press & hold down those keys, their
corresponding to a bit in a byte (which is made up of eight bits). When you press and hold down those keys, their
associated bits are set to 1. When the keys are released or are not being pushed, their associated bits are set to 0.

When you are ready to turn those bits into a byte, press the Space Bar and the application will convert those bits into
When you are ready to turn those bits into a byte, press the Space Bar, and the application will convert those bits into
a byte and display it as a decimal.

This application is currently designed to work in Linux.
This application is currently designed to work on Linux.

For the time-being, this app requires elevated privileges (e.g. `sudo`) to run.

Expand Down Expand Up @@ -40,6 +40,11 @@ sudo apt -y install build-essential cmake git libevdev-dev
sudo pacman -S gcc cmake git libevdev
````

#### Install Dependencies on Alpine
```shell
apk add --update build-base 'cmake>3.30' libevdev libevdev-dev gdb
```

### Step 2: Clone this repository
Run:
```shell
Expand Down Expand Up @@ -80,5 +85,5 @@ maintaining this repository.
## License
Copyright (C) 2025 Asami De Almeida

Released under the Apache License 2.0 License. See the following pages for more information:
* [Apache License 2.0](LICENSE)
Released under the Apache Licence 2.0 Licence. See the following pages for more information:
* [Apache Licence 2.0](LICENSE)
6 changes: 6 additions & 0 deletions dockerfiles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Dockerfiles

This directory will contain directories of Dockerfiles used for building a local Linux sandbox environment.
This is useful for developing for Linux while using a Mac or Windows machine.

If you are using CLion, visit [this tutorial](https://www.jetbrains.com/help/clion/clion-toolchains-in-docker.html) to learn how to connect a Docker image to your project for development.
3 changes: 3 additions & 0 deletions dockerfiles/alpine-dev-test/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM alpine:latest

RUN apk add --update build-base 'cmake>3.30' libevdev libevdev-dev gdb
117 changes: 117 additions & 0 deletions includes/StenoByte_Core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
StenoByte: a stenotype inspired keyboard app for typing out bytes.

StenoByte_Core.c is the source file for implementing resources related to processing the Bits into a Byte and
for producing the result as an output.

This file is intended to be Operating System agnostic and to be compiled for any Operating System.

Copyright 2025 Asami De Almeida

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "StenoByte_Core.h"

// Arrays & Variables
// Bit Array that contains the bits that forms a byte
bool bit_arr[BITS_ARR_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0}; // ordered from b0 to b7 during initialisation
char keys_arr[BITS_ARR_SIZE] = {';', 'L', 'K', 'J', 'F', 'D', 'S', 'A'}; // ';' = b0, 'L' = b1, ... 'A' = b7
u_int8_t subvalues_arr[BITS_ARR_SIZE];
bool ready_to_compute_byte = false; // the state for whether to convert the bit array into a byte and process it

u_int8_t current_byte = 0x00; // The byte last computed from the bit array


// Methods & Functions

/*
* Generates the Byte based on the bits in the array
*/
void compute_byte() {
current_byte = 0x00; // Resets the Byte to zero
for (int i = 0; i < BITS_ARR_SIZE; i++) {
current_byte = current_byte ^ bit_arr[i] << i;
}
ready_to_compute_byte = false;
}

/*
* Sets up the sub-values array for labelling
*/
void setup_subvalues_array() {
for (int i = BITS_ARR_SIZE; i >= 0; i--) {
const u_int8_t val = 0;
subvalues_arr[i] = val ^ 1 << i;
}
}

/*
* Gets Byte Summary as a String (an array of chars)
* Assumes msg has a minimum length of 35. Assumes value of current_byte will not exceed 255.
*/
void get_byte_summary(char* msg) {
sprintf(msg + strlen(msg), "Last Computed Byte as decimal: %d\n", current_byte); // Prints between 33 and 35 chars
}

/*
* Prints the Byte Summary
*/
void print_byte_summary() {
char msg[35];
get_byte_summary(msg);
printf("%s", msg);
}

/*
* Prints the current state of the Bit Array
* TODO: The repeated for loops could probably be simplified into a dedicated method
*/
void print_bit_arr_summary() {
char msg[654] = "";

sprintf(msg + strlen(msg), "\nBits in Array:\n"); // Prints 16 chars
sprintf(msg + strlen(msg), "\tBit Value:\t| "); // Prints 14 chars
for (int i = 7; i >= 0; i--) { // Repeats 8 times
sprintf(msg + strlen(msg), "\t%d\t|", bit_arr[i]); // Prints between 4 and 6 chars
}
sprintf(msg + strlen(msg), "\n"); // Prints 1 char

for (int i=0; i<24+16*BITS_ARR_SIZE; i++) { // Repeats 24+(16*8) times, which is 152
sprintf(msg + strlen(msg), "-"); // Prints 1 char
}

sprintf(msg + strlen(msg), "\n\tSub-Value:\t|"); // Prints 14 chars
for (int i = 7; i >= 0; i--) { // Repeats 8 times
sprintf(msg + strlen(msg), "\t[%d]\t|", subvalues_arr[i]); // Prints between 6 and 8 chars
}

sprintf(msg + strlen(msg), "\n\tBit Index:\t|"); // Prints 14 chars
for (int i = 7; i >= 0; i--) { // Repeats 8 times
sprintf(msg + strlen(msg), "\t[b%d]\t|", i); // Prints 7 chars
}
sprintf(msg + strlen(msg), "\n\tKey:\t\t|"); // Prints 9 times

for (int i = 7; i >= 0; i--) { // Repeats 8 times
sprintf(msg + strlen(msg), "\t[%c]\t|", keys_arr[i]); // Prints 6 chars
}
sprintf(msg + strlen(msg), "\n"); // Prints 1 char
get_byte_summary(msg); // Prints between 33 and 35 chars
sprintf(msg + strlen(msg), "\nPress & Hold the keys corresponding to the bits in the"
" byte you would like to set to 1."); // Prints 88 chars
sprintf(msg + strlen(msg), "\nBits will be 0 if keys are not pressed."); // Prints 40 chars
sprintf(msg + strlen(msg), "\nPress SPACE BAR to compute Byte\t\t|\t"
"Press ESC to exit\n"); // Prints 53 chars

printf("%s", msg);
}
50 changes: 15 additions & 35 deletions StenoByte_Helper.h → includes/StenoByte_Core.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/**
StenoByte: a stenotype inspired keyboard app for typing out bytes.

Copyright 2025 Asami De Almeida
StenoByte_Core.h is the header file for defining resources related to processing the Bits into a Byte and
for producing the result as an output.

Copyright 2025 Asami De Almeida

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -16,57 +19,34 @@
limitations under the License.
*/

#ifndef STENOBYTE_HELPER_H
#define STENOBYTE_HELPER_H

#include <linux/input.h>
#include <libevdev/libevdev.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#ifndef STENOBYTE_CORE_H
#define STENOBYTE_CORE_H

// Key Press States
#define EV_KEY_RELEASED 0
#define EV_KEY_PRESSED 1
#define EV_KEY_REPEATED 2
#include "StenoByte_Helper.h"

// Number of Bits in the Bit Array (should be 8)
# define BITS_ARR_SIZE 8

extern struct termios original_terminal_settings; // Termios Struct to store original terminal settings

// Arrays & Variables
// Bit Array that contains the bits that forms a byte
extern bool bit_arr[BITS_ARR_SIZE]; // ordered from b0 to b7 during initialisation
extern char keys_arr[BITS_ARR_SIZE]; // ';' = b0, 'L' = b1, ... 'A' = b7
extern u_int8_t subvalues_arr[BITS_ARR_SIZE];
extern bool ready_to_compute_byte; // the state for whether to convert the bit array into a byte and process it

extern u_int8_t current_byte; // The byte last computed from the bit array


// Methods & Functions

bool is_valid_key(int key_code);

void update_bit_arr(int key_code, bool new_state);
// Externally Declared Methods & Functions (expected to be declared & defined StenoByte_Helper files)
extern void update_bit_arr(int key_code, bool new_state);
extern int setup_stenobyte();
extern void run_stenobyte();
extern void end_stenobyte();

// Methods & Functions
void compute_byte();

void setup_subvalues_array();

void print_event_summary(const struct input_event* current_event);

void get_byte_summary(char* msg);
void print_byte_summary();

void print_bit_arr_summary();

void process_key_presses(const struct input_event* current_event);

void disable_echo();

void restore_terminal();

#endif //STENOBYTE_HELPER_H
#endif //STENOBYTE_CORE_H
66 changes: 66 additions & 0 deletions includes/StenoByte_Helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
StenoByte: a stenotype inspired keyboard app for typing out bytes.

StenoByte_Helper.h is the header file for defining resources for Keyboard Event Reading for a range of
Operating Systems.

TODO: Implement conditional declarations that will be dependent on the target OS.

Copyright 2025 Asami De Almeida

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef STENOBYTE_HELPER_H
#define STENOBYTE_HELPER_H

#include <linux/input.h>
#include <libevdev/libevdev.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

// Key Press States
#define EV_KEY_RELEASED 0
#define EV_KEY_PRESSED 1
#define EV_KEY_REPEATED 2

// Externally Declared Structs and Variables (expected to be declared and implemented in dependencies)
extern struct libevdev *keyboard_device; // Struct to store the evdev device
extern struct termios original_terminal_settings; // Termios Struct to store original terminal settings
extern const int event_file_device;


// Externally Declared Methods & Functions
// (expected to be declared & defined in dependent libraries or in StenoByte_Core files)
extern void setup_subvalues_array(); // StenoByte_Core.h/c
extern void compute_byte();
extern void print_bit_arr_summary();
extern void update_bit_arr(int key_code, bool new_state);


// Methods & Functions
int setup_stenobyte();
void update_bit_arr(int key_code, bool new_state);
void run_stenobyte();
void end_stenobyte();
void process_key_presses(const struct input_event* current_event);
bool is_valid_key(int key_code);
void print_event_summary(const struct input_event* current_event);
void disable_echo();
void restore_terminal();

#endif //STENOBYTE_HELPER_H
Loading